From 8013d39c8f498beee8b0526f6f29524dac34cca7 Mon Sep 17 00:00:00 2001 From: visa Date: Wed, 8 Dec 2021 13:03:52 +0000 Subject: [PATCH] Fix select(2) exceptfds handling of FIFOs and pipes Prevent select(2) from indicating an exceptional condition when the other end of a FIFO or pipe is closed. Originally, select(2) returned an exceptfds event only with a pty or socket that has out-of-band data pending. millert@ says that OpenBSD diverged from this by accident when poll(2) and select(2) were changed to use the same backend code in year 2003. OK millert@ --- sys/kern/sys_generic.c | 7 ++++--- sys/kern/sys_pipe.c | 7 ++++++- sys/miscfs/fifofs/fifo_vnops.c | 6 +++++- sys/sys/event.h | 5 +++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 39a8ab7ae83..8fdfb8d8b84 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.144 2021/11/30 02:58:33 visa Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.145 2021/12/08 13:03:52 visa Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -762,7 +762,7 @@ pselregister(struct proc *p, fd_set *pibits[3], fd_set *pobits[3], int nfd, DPRINTFN(2, "select fd %d mask %d serial %lu\n", fd, msk, p->p_kq_serial); EV_SET(&kev, fd, evf[msk], - EV_ADD|EV_ENABLE|__EV_POLL, + EV_ADD|EV_ENABLE|__EV_POLL|__EV_SELECT, evff[msk], 0, (void *)(p->p_kq_serial)); #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) @@ -775,7 +775,8 @@ pselregister(struct proc *p, fd_set *pibits[3], fd_set *pobits[3], int nfd, /* FALLTHROUGH */ case EOPNOTSUPP:/* No underlying kqfilter */ case EINVAL: /* Unimplemented filter */ - case EPERM: /* Specific to FIFO */ + case EPERM: /* Specific to FIFO and + * __EV_SELECT */ error = 0; break; case EPIPE: /* Specific to pipes */ diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 3ece79221b3..4da474aa257 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_pipe.c,v 1.130 2021/12/07 14:06:16 visa Exp $ */ +/* $OpenBSD: sys_pipe.c,v 1.131 2021/12/08 13:03:52 visa Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -922,6 +922,11 @@ pipe_kqfilter(struct file *fp, struct knote *kn) klist_insert_locked(&wpipe->pipe_sel.si_note, kn); break; case EVFILT_EXCEPT: + if (kn->kn_flags & __EV_SELECT) { + /* Prevent triggering exceptfds. */ + error = EPERM; + break; + } kn->kn_fop = &pipe_efiltops; kn->kn_hook = rpipe; klist_insert_locked(&rpipe->pipe_sel.si_note, kn); diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c index c039fd411ec..ca8d40f6de0 100644 --- a/sys/miscfs/fifofs/fifo_vnops.c +++ b/sys/miscfs/fifofs/fifo_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fifo_vnops.c,v 1.85 2021/10/24 11:23:22 mpi Exp $ */ +/* $OpenBSD: fifo_vnops.c,v 1.86 2021/12/08 13:03:52 visa Exp $ */ /* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */ /* @@ -540,6 +540,10 @@ fifo_kqfilter(void *v) sb = &so->so_snd; break; case EVFILT_EXCEPT: + if (ap->a_kn->kn_flags & __EV_SELECT) { + /* Prevent triggering exceptfds. */ + return (EPERM); + } ap->a_kn->kn_fop = &fifoexcept_filtops; so = fip->fi_readsock; sb = &so->so_rcv; diff --git a/sys/sys/event.h b/sys/sys/event.h index 20a1fd33c82..5004978e348 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.59 2021/11/29 15:54:04 visa Exp $ */ +/* $OpenBSD: event.h,v 1.60 2021/12/08 13:03:53 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon @@ -74,7 +74,7 @@ struct kevent { #define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ #define EV_DISPATCH 0x0080 /* disable event after reporting */ -#define EV_SYSFLAGS 0xF000 /* reserved by system */ +#define EV_SYSFLAGS 0xf800 /* reserved by system */ #define EV_FLAG1 0x2000 /* filter-specific flag */ /* returned values */ @@ -141,6 +141,7 @@ struct klist { #ifdef _KERNEL /* kernel-only flags */ +#define __EV_SELECT 0x0800 /* match behavior of select */ #define __EV_POLL 0x1000 /* match behavior of poll & select */ #define __EV_HUP EV_FLAG1 /* device or socket disconnected */ -- 2.20.1