aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2026-06-05 23:29:23 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2026-06-06 20:00:30 +0000
commit390ae06d4f524a6f32383cbc1bcbdecdb3738bc3 (patch)
treebc73458697a596590fdbe5f0e89a70fe0493bd58
parent261c97b47ea4f120bfa4a04aab7d35c70dde8c8f (diff)
procctl(PROC_REAP_GETPIDS): re-validate reaper after relock of proctree_lock
Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57487
-rw-r--r--sys/kern/kern_procctl.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index db9de394c101..1ff1b15767b5 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -204,27 +204,48 @@ reap_status(struct thread *td, struct proc *p, void *data)
}
static int
+reap_getpids_count(struct proc **reapp, struct proc *p,
+ const struct procctl_reaper_pids *rp)
+{
+ struct proc *reap, *p2;
+ int n;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ reap = get_reaper_or_p(p);
+ n = 0;
+ LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling)
+ n++;
+ if (rp->rp_count < n)
+ n = rp->rp_count;
+ *reapp = reap;
+ return (n);
+}
+
+static int
reap_getpids(struct thread *td, struct proc *p, void *data)
{
struct proc *reap, *p2;
struct procctl_reaper_pidinfo *pi, *pip;
struct procctl_reaper_pids *rp;
- u_int i, n;
+ u_int i, n, n1;
int error;
rp = data;
sx_assert(&proctree_lock, SX_LOCKED);
PROC_UNLOCK(p);
- reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p;
- n = i = 0;
- error = 0;
- LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling)
- n++;
- sx_unlock(&proctree_lock);
- if (rp->rp_count < n)
- n = rp->rp_count;
- pi = malloc(n * sizeof(*pi), M_TEMP, M_WAITOK);
- sx_slock(&proctree_lock);
+ i = 0;
+ for (;;) {
+ n1 = reap_getpids_count(&reap, p, rp);
+ sx_unlock(&proctree_lock);
+ pi = mallocarray(n1, sizeof(*pi), M_TEMP, M_WAITOK);
+ sx_slock(&proctree_lock);
+ n = reap_getpids_count(&reap, p, rp);
+ if (n <= n1)
+ break;
+ free(pi, M_TEMP);
+ }
+
LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) {
if (i == n)
break;