Since UNIX domain sockets are unlocked it makes sense to unlock
sys_sendsyslog too. Console output still requires kernel lock to be
held but this path is only followed while `syslogf' socket is not set.

New `syslogf_rwlock' used to protect `syslogf' access.

ok?

Index: sys/kern/subr_log.c
===================================================================
RCS file: /cvs/src/sys/kern/subr_log.c,v
retrieving revision 1.73
diff -u -p -r1.73 subr_log.c
--- sys/kern/subr_log.c 9 Mar 2021 15:08:23 -0000       1.73
+++ sys/kern/subr_log.c 10 Mar 2021 21:25:24 -0000
@@ -86,7 +86,9 @@ int   log_open;                       /* also used in log() */
 int    msgbufmapped;                   /* is the message buffer mapped */
 struct msgbuf *msgbufp;                /* the mapped buffer, itself. */
 struct msgbuf *consbufp;               /* console message buffer. */
+
 struct file *syslogf;
+struct rwlock syslogf_rwlock = RWLOCK_INITIALIZER("syslogf");
 
 /*
  * Lock that serializes access to log message buffers.
@@ -215,8 +217,11 @@ logclose(dev_t dev, int flag, int mode, 
 {
        struct file *fp;
 
+       rw_enter_write(&syslogf_rwlock);
        fp = syslogf;
        syslogf = NULL;
+       rw_exit(&syslogf_rwlock);
+
        if (fp)
                FRELE(fp, p);
        log_open = 0;
@@ -407,7 +412,7 @@ out:
 int
 logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct proc *p)
 {
-       struct file *fp;
+       struct file *fp, *newfp;
        int error;
 
        switch (com) {
@@ -441,9 +446,14 @@ logioctl(dev_t dev, u_long com, caddr_t 
        case LIOCSFD:
                if ((error = suser(p)) != 0)
                        return (error);
-               fp = syslogf;
-               if ((error = getsock(p, *(int *)data, &syslogf)) != 0)
+               if ((error = getsock(p, *(int *)data, &newfp)) != 0)
                        return (error);
+
+               rw_enter_write(&syslogf_rwlock);
+               fp = syslogf;
+               syslogf = newfp;
+               rw_exit(&syslogf_rwlock);
+
                if (fp)
                        FRELE(fp, p);
                break;
@@ -635,12 +645,15 @@ dosendsyslog(struct proc *p, const char 
        int error;
 
        /* Global variable syslogf may change during sleep, use local copy. */
+       rw_enter_read(&syslogf_rwlock);
        fp = syslogf;
        if (fp)
                FREF(fp);
-       else if (!ISSET(flags, LOG_CONS))
-               return (ENOTCONN);
-       else {
+       rw_exit(&syslogf_rwlock);
+
+       if (fp == NULL) {
+               if (!ISSET(flags, LOG_CONS))
+                       return (ENOTCONN);
                /*
                 * Strip off syslog priority when logging to console.
                 * LOG_PRIMASK | LOG_FACMASK is 0x03ff, so at most 4
@@ -690,41 +703,45 @@ dosendsyslog(struct proc *p, const char 
                error = sosend(fp->f_data, NULL, &auio, NULL, NULL, flags);
                if (error == 0)
                        len -= auio.uio_resid;
-       } else if (constty || cn_devvp) {
-               error = cnwrite(0, &auio, 0);
-               if (error == 0)
-                       len -= auio.uio_resid;
-               aiov.iov_base = "\r\n";
-               aiov.iov_len = 2;
-               auio.uio_iov = &aiov;
-               auio.uio_iovcnt = 1;
-               auio.uio_segflg = UIO_SYSSPACE;
-               auio.uio_rw = UIO_WRITE;
-               auio.uio_procp = p;
-               auio.uio_offset = 0;
-               auio.uio_resid = aiov.iov_len;
-               cnwrite(0, &auio, 0);
        } else {
-               /* XXX console redirection breaks down... */
-               if (sflg == UIO_USERSPACE) {
-                       kbuf = malloc(len, M_TEMP, M_WAITOK);
-                       error = copyin(aiov.iov_base, kbuf, len);
+               KERNEL_LOCK();
+               if (constty || cn_devvp) {
+                       error = cnwrite(0, &auio, 0);
+                       if (error == 0)
+                               len -= auio.uio_resid;
+                       aiov.iov_base = "\r\n";
+                       aiov.iov_len = 2;
+                       auio.uio_iov = &aiov;
+                       auio.uio_iovcnt = 1;
+                       auio.uio_segflg = UIO_SYSSPACE;
+                       auio.uio_rw = UIO_WRITE;
+                       auio.uio_procp = p;
+                       auio.uio_offset = 0;
+                       auio.uio_resid = aiov.iov_len;
+                       cnwrite(0, &auio, 0);
                } else {
-                       kbuf = aiov.iov_base;
-                       error = 0;
-               }
-               if (error == 0)
-                       for (i = 0; i < len; i++) {
-                               if (kbuf[i] == '\0')
-                                       break;
-                               cnputc(kbuf[i]);
-                               auio.uio_resid--;
+                       /* XXX console redirection breaks down... */
+                       if (sflg == UIO_USERSPACE) {
+                               kbuf = malloc(len, M_TEMP, M_WAITOK);
+                               error = copyin(aiov.iov_base, kbuf, len);
+                       } else {
+                               kbuf = aiov.iov_base;
+                               error = 0;
                        }
-               if (sflg == UIO_USERSPACE)
-                       free(kbuf, M_TEMP, len);
-               if (error == 0)
-                       len -= auio.uio_resid;
-               cnputc('\n');
+                       if (error == 0)
+                               for (i = 0; i < len; i++) {
+                                       if (kbuf[i] == '\0')
+                                               break;
+                                       cnputc(kbuf[i]);
+                                       auio.uio_resid--;
+                               }
+                       if (sflg == UIO_USERSPACE)
+                               free(kbuf, M_TEMP, len);
+                       if (error == 0)
+                               len -= auio.uio_resid;
+                       cnputc('\n');
+               }
+               KERNEL_UNLOCK();
        }
 
 #ifdef KTRACE
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.208
diff -u -p -r1.208 syscalls.master
--- sys/kern/syscalls.master    18 Jan 2021 18:25:51 -0000      1.208
+++ sys/kern/syscalls.master    10 Mar 2021 21:25:25 -0000
@@ -235,7 +235,7 @@
                            fd_set *ex, const struct timespec *ts, \
                            const sigset_t *mask); }
 111    STD             { int sys_sigsuspend(int mask); }
-112    STD             { int sys_sendsyslog(const char *buf, size_t nbyte, \
+112    STD NOLOCK      { int sys_sendsyslog(const char *buf, size_t nbyte, \
                            int flags); }
 113    UNIMPL          fktrace
 114    STD             { int sys_unveil(const char *path, \

Reply via email to