Introduce priterator(), the `ps_list' iterator. Some of `allprocess'
authormvs <mvs@openbsd.org>
Mon, 15 Jan 2024 15:47:37 +0000 (15:47 +0000)
committermvs <mvs@openbsd.org>
Mon, 15 Jan 2024 15:47:37 +0000 (15:47 +0000)
list walkthroughs have context switch within, so make exit1() wait
until the last reference released.

Reported-by: syzbot+0e9dda76c42c82c626d7@syzkaller.appspotmail.com
ok bluhm claudio

sys/kern/kern_exit.c
sys/kern/kern_fork.c
sys/kern/kern_proc.c
sys/kern/kern_sysctl.c
sys/sys/proc.h

index ce6aea2..06aabdc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_exit.c,v 1.217 2023/09/29 12:47:34 claudio Exp $ */
+/*     $OpenBSD: kern_exit.c,v 1.218 2024/01/15 15:47:37 mvs Exp $     */
 /*     $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $  */
 
 /*
@@ -165,6 +165,8 @@ exit1(struct proc *p, int xexit, int xsig, int flags)
                /* main thread gotta wait because it has the pid, et al */
                while (pr->ps_threadcnt > 1)
                        tsleep_nsec(&pr->ps_threads, PWAIT, "thrdeath", INFSLP);
+               LIST_REMOVE(pr, ps_list);
+               refcnt_finalize(&pr->ps_refcnt, "psdtor");
        }
 
        rup = pr->ps_ru;
@@ -252,7 +254,6 @@ exit1(struct proc *p, int xexit, int xsig, int flags)
 
        if ((p->p_flag & P_THREAD) == 0) {
                LIST_REMOVE(pr, ps_hash);
-               LIST_REMOVE(pr, ps_list);
 
                if ((pr->ps_flags & PS_NOZOMBIE) == 0)
                        LIST_INSERT_HEAD(&zombprocess, pr, ps_list);
index 1e5fa35..438a01b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_fork.c,v 1.253 2023/10/24 13:20:11 claudio Exp $ */
+/*     $OpenBSD: kern_fork.c,v 1.254 2024/01/15 15:47:37 mvs Exp $     */
 /*     $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $  */
 
 /*
@@ -197,6 +197,7 @@ process_initialize(struct process *pr, struct proc *p)
        LIST_INIT(&pr->ps_sigiolst);
        TAILQ_INIT(&pr->ps_tslpqueue);
 
+       refcnt_init(&pr->ps_refcnt);
        rw_init(&pr->ps_lock, "pslock");
        mtx_init(&pr->ps_mtx, IPL_HIGH);
 
index 3c19519..66a8a4d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_proc.c,v 1.95 2023/09/19 11:35:30 claudio Exp $  */
+/*     $OpenBSD: kern_proc.c,v 1.96 2024/01/15 15:47:37 mvs Exp $      */
 /*     $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $  */
 
 /*
@@ -231,6 +231,26 @@ prfind(pid_t pid)
        return (NULL);
 }
 
+struct process *
+priterator(struct process *ps)
+{
+       struct process *nps;
+
+       KERNEL_ASSERT_LOCKED();
+
+       if (ps == NULL)
+               nps = LIST_FIRST(&allprocess);
+       else
+               nps = LIST_NEXT(ps, ps_list);
+
+       if (nps)
+               refcnt_take(&nps->ps_refcnt);
+       if (ps)
+               refcnt_rele_wake(&ps->ps_refcnt);
+
+       return nps;
+}
+
 /*
  * Locate a process group by number
  */
index ac3a350..8fcf58a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sysctl.c,v 1.421 2024/01/10 16:44:30 bluhm Exp $ */
+/*     $OpenBSD: kern_sysctl.c,v 1.422 2024/01/15 15:47:37 mvs Exp $   */
 /*     $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $     */
 
 /*-
@@ -1534,7 +1534,7 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep,
                        break;
                }
                matched = 0;
-               LIST_FOREACH(pr, &allprocess, ps_list) {
+               for (pr = priterator(NULL); pr != NULL; pr = priterator(pr)) {
                        /*
                         * skip system, exiting, embryonic and undead
                         * processes
@@ -1566,7 +1566,7 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep,
                        error = ESRCH;
                break;
        case KERN_FILE_BYUID:
-               LIST_FOREACH(pr, &allprocess, ps_list) {
+               for (pr = priterator(NULL); pr != NULL; pr = priterator(pr)) {
                        /*
                         * skip system, exiting, embryonic and undead
                         * processes
index 6ed699d..b5c0776 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: proc.h,v 1.352 2023/09/29 12:47:34 claudio Exp $      */
+/*     $OpenBSD: proc.h,v 1.353 2024/01/15 15:47:37 mvs Exp $  */
 /*     $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $       */
 
 /*-
@@ -50,6 +50,7 @@
 #include <sys/resource.h>              /* For struct rusage */
 #include <sys/rwlock.h>                        /* For struct rwlock */
 #include <sys/sigio.h>                 /* For struct sigio */
+#include <sys/refcnt.h>
 
 #ifdef _KERNEL
 #include <sys/atomic.h>
@@ -164,6 +165,7 @@ struct process {
 
        struct  futex_list ps_ftlist;   /* futexes attached to this process */
        struct  tslpqueue ps_tslpqueue; /* [p] queue of threads in thrsleep */
+       struct  refcnt  ps_refcnt;
        struct  rwlock  ps_lock;        /* per-process rwlock */
        struct  mutex   ps_mtx;         /* per-process mutex */
 
@@ -526,6 +528,7 @@ void        freepid(pid_t);
 
 struct process *prfind(pid_t); /* Find process by id. */
 struct process *zombiefind(pid_t); /* Find zombie process by id. */
+struct process *priterator(struct process *);
 struct proc *tfind(pid_t);     /* Find thread by id. */
 struct pgrp *pgfind(pid_t);    /* Find process group by id. */
 struct proc *tfind_user(pid_t, struct process *);