On Thu, Mar 11, 2021 at 12:40:37AM +0300, Vitaliy Makkoveev wrote: > 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?
regress passes, OK bluhm@ > 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, \