Unlock select(2), pselect(2), poll(2) and ppoll(2).
authormvs <mvs@openbsd.org>
Sat, 25 Feb 2023 09:55:46 +0000 (09:55 +0000)
committermvs <mvs@openbsd.org>
Sat, 25 Feb 2023 09:55:46 +0000 (09:55 +0000)
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
sys/kern/syscalls.master

index c17c328..9eccb48 100644 (file)
@@ -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);
index 0826009..7f43762 100644 (file)
@@ -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
                            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, \
                            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); }
 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); }