From be29726c64cb8bfe8bf5fd96343305e37989cc0b Mon Sep 17 00:00:00 2001 From: mvs Date: Sat, 25 Feb 2023 09:55:46 +0000 Subject: [PATCH] Unlock select(2), pselect(2), poll(2) and ppoll(2). The assertion within tsleep(9) was relaxed to allow calls on special `nowake' channel without kernel lock held. So the sisguspend(2) like cases "select(0, NULL, NULL, NULL, NULL)" and "poll(NULL, 0, INFTIM)" should not trigger it. Commit reverted diff back. ok claudio@ --- sys/kern/sys_generic.c | 23 +++++++++++++++-------- sys/kern/syscalls.master | 10 +++++----- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index c17c3289a8f..9eccb48a3f1 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.154 2023/02/14 08:34:49 mvs Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.155 2023/02/25 09:55:46 mvs Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -596,15 +596,16 @@ dopselect(struct proc *p, int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timespec zerots = {}; fd_mask bits[6]; fd_set *pibits[3], *pobits[3]; - int error, ncollected = 0, nevents = 0; + int error, nfiles, ncollected = 0, nevents = 0; u_int ni; if (nd < 0) return (EINVAL); - if (nd > p->p_fd->fd_nfiles) { - /* forgiving; slightly wrong */ - nd = p->p_fd->fd_nfiles; - } + + nfiles = READ_ONCE(p->p_fd->fd_nfiles); + if (nd > nfiles) + nd = nfiles; + ni = howmany(nd, NFDBITS) * sizeof(fd_mask); if (ni > sizeof(bits[0])) { caddr_t mbits; @@ -643,8 +644,11 @@ dopselect(struct proc *p, int nd, fd_set *in, fd_set *ou, fd_set *ex, } #endif - if (sigmask) + if (sigmask) { + KERNEL_LOCK(); dosigsuspend(p, *sigmask &~ sigcantmask); + KERNEL_UNLOCK(); + } /* Register kqueue events */ error = pselregister(p, pibits, pobits, nd, &nevents, &ncollected); @@ -948,8 +952,11 @@ doppoll(struct proc *p, struct pollfd *fds, u_int nfds, if ((error = copyin(fds, pl, sz)) != 0) goto bad; - if (sigmask) + if (sigmask) { + KERNEL_LOCK(); dosigsuspend(p, *sigmask &~ sigcantmask); + KERNEL_UNLOCK(); + } /* Register kqueue events */ ppollregister(p, pl, nfds, &nevents, &ncollected); diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 08260095e5e..7f437623b94 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.245 2023/02/16 08:53:16 claudio Exp $ +; $OpenBSD: syscalls.master,v 1.246 2023/02/25 09:55:46 mvs Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -165,7 +165,7 @@ struct itimerval *oitv); } 70 STD NOLOCK { int sys_getitimer(int which, \ struct itimerval *itv); } -71 STD { int sys_select(int nd, fd_set *in, fd_set *ou, \ +71 STD NOLOCK { int sys_select(int nd, fd_set *in, fd_set *ou, \ fd_set *ex, struct timeval *tv); } 72 STD NOLOCK { int sys_kevent(int fd, \ const struct kevent *changelist, int nchanges, \ @@ -230,10 +230,10 @@ u_int flags, int atflags); } 108 STD NOLOCK { int sys_pledge(const char *promises, \ const char *execpromises); } -109 STD { int sys_ppoll(struct pollfd *fds, \ +109 STD NOLOCK { int sys_ppoll(struct pollfd *fds, \ u_int nfds, const struct timespec *ts, \ const sigset_t *mask); } -110 STD { int sys_pselect(int nd, fd_set *in, fd_set *ou, \ +110 STD NOLOCK { int sys_pselect(int nd, fd_set *in, fd_set *ou, \ fd_set *ex, const struct timespec *ts, \ const sigset_t *mask); } 111 STD { int sys_sigsuspend(int mask); } @@ -443,7 +443,7 @@ 250 STD NOLOCK { int sys_minherit(void *addr, size_t len, \ int inherit); } 251 OBSOL rfork -252 STD { int sys_poll(struct pollfd *fds, \ +252 STD NOLOCK { int sys_poll(struct pollfd *fds, \ u_int nfds, int timeout); } 253 STD NOLOCK { int sys_issetugid(void); } 254 STD { int sys_lchown(const char *path, uid_t uid, gid_t gid); } -- 2.20.1