diff options
author | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2024-01-15 15:47:38 +0000 |
---|---|---|
committer | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2024-01-15 15:47:38 +0000 |
commit | cea5479f9f05a949289015fe5b468b9ce0cc62a1 (patch) | |
tree | 37eca19b5080b89dbc3685f827b0348d7bd030fe /sys | |
parent | 576454b99fe7638b52cdfea5d10bf7f6bfef2a1f (diff) |
Introduce priterator(), the `ps_list' iterator. Some of `allprocess'
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_exit.c | 5 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 22 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 6 | ||||
-rw-r--r-- | sys/sys/proc.h | 5 |
5 files changed, 33 insertions, 8 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index ce6aea2aa1b..06aabdc0775 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -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); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 1e5fa351f0b..438a01ba7f3 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -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); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 3c19519629b..66a8a4d03ad 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -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 */ diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index ac3a350698b..8fcf58a7a07 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -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 diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 6ed699d9bc0..b5c0776130e 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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 *); |