On Sun, Aug 16, 2020 at 11:39:31AM +0000, Visa Hankala wrote: > The kernel message buffer is circular. This is not handled properly > by filt_logread(). When the write index wraps, and becomes smaller than > the read index, filt_logread() reports an incorrect number of available > bytes. This has not affected the activation of the event, though, > because the reported number is non-zero even in the incorrect case. > > The error looks like the following with ktrace: > > 60243 syslogd STRU struct kevent { ident=10, filter=EVFILT_READ, > flags=0x1<EV_ADD>, fflags=0<>, data=18446744073709551615, udata=0x34c7e21000 }
Here is an updated diff. It uses the same buffer length computation for kn_data and FIONREAD. These interfaces, kevent(2) and ioctl(2), should indicate the same number of available bytes after all. Also, now the computation has the more compact form used by FIONREAD. OK? Index: kern/subr_log.c =================================================================== RCS file: src/sys/kern/subr_log.c,v retrieving revision 1.66 diff -u -p -r1.66 subr_log.c --- kern/subr_log.c 7 Apr 2020 13:27:51 -0000 1.66 +++ kern/subr_log.c 17 Aug 2020 05:37:41 -0000 @@ -95,6 +95,7 @@ const struct filterops logread_filtops = int dosendsyslog(struct proc *, const char *, size_t, int, enum uio_seg); void logtick(void *); +size_t msgbuf_getlen(struct msgbuf *); void initmsgbuf(caddr_t buf, size_t bufsize) @@ -163,6 +163,20 @@ msgbuf_putchar(struct msgbuf *mbp, const splx(s); } +size_t +msgbuf_getlen(struct msgbuf *mbp) +{ + long len; + int s; + + s = splhigh(); + len = mbp->msg_bufx - mbp->msg_bufr; + if (len < 0) + len += mbp->msg_bufs; + splx(s); + return (len); +} + int logopen(dev_t dev, int flags, int mode, struct proc *p) { @@ -297,14 +311,10 @@ filt_logrdetach(struct knote *kn) int filt_logread(struct knote *kn, long hint) { - struct msgbuf *p = (struct msgbuf *)kn->kn_hook; - int s, event = 0; + struct msgbuf *mbp = kn->kn_hook; - s = splhigh(); - kn->kn_data = (int)(p->msg_bufx - p->msg_bufr); - event = (p->msg_bufx != p->msg_bufr); - splx(s); - return (event); + kn->kn_data = msgbuf_getlen(mbp); + return (kn->kn_data != 0); } void @@ -357,19 +367,13 @@ int logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct proc *p) { struct file *fp; - long l; - int error, s; + int error; switch (com) { /* return number of characters immediately available */ case FIONREAD: - s = splhigh(); - l = msgbufp->msg_bufx - msgbufp->msg_bufr; - splx(s); - if (l < 0) - l += msgbufp->msg_bufs; - *(int *)data = l; + *(int *)data = (int)msgbuf_getlen(msgbufp); break; case FIONBIO: