From nobody Mon Sep 05 11:56:14 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4MLn6R3gzWz4cBHf; Mon, 5 Sep 2022 11:56:15 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MLn6R0lGyz3ZG2; Mon, 5 Sep 2022 11:56:15 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662378975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VvmOdKazhzyh9Gkpzm3qs8XbabDsyXstfxJSuHGxUfM=; b=KsiKfko+J1BEJhct8deLvZQ4675FibXb+rx5hK9E12jbcCOJUeB6jZaF+SKvDl8ty78LOX 2X/tvyAowygmCHxyB8V42X780zZBxsM740hCqrZueiZ6AwnzBsFSLFFnc6aX9rLqxZgrJ7 Rtad7gOZI/Z3lj2SmFh+B4hpOPskkIwxwaF9+5+fTmmzpgygwsgDo3nmyIgbqJZNct9uaH MD59xzT52EzL7dwyLJyYSSmO2A867fGSXuHa/29AKZVLOctYvr1FUen2sWVs6eKbAtDjbv PUIlsXO0zQ8q81Py+WLHWgPYWx0xuYTxAIGDeDTsw0p3sA9i1QmxPTOd396T9g== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4MLn6Q6qZDzptn; Mon, 5 Sep 2022 11:56:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 285BuESA076759; Mon, 5 Sep 2022 11:56:14 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 285BuEZQ076758; Mon, 5 Sep 2022 11:56:14 GMT (envelope-from git) Date: Mon, 5 Sep 2022 11:56:14 GMT Message-Id: <202209051156.285BuEZQ076758@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mateusz Guzik Subject: git: 5ecb5444aa34 - main - jail: add process linkage List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mjg X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 5ecb5444aa349246568dc6f9a615630e29191f7c Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1662378975; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=VvmOdKazhzyh9Gkpzm3qs8XbabDsyXstfxJSuHGxUfM=; b=czKabx0/9MRn2XMvEd2+hxb7CZU/xNIIgoP/ItGTUSobQF15rGqNSM8+Ea1XPdj+5kywxA 5oLZPY0J03YHjDk5DOzjbYKmskXqs6LqhPRIjxlIh56g3a3tpvKkX/rxuGHgx0Ni0tBn82 MzuUr7hTfc3pOrqioQgpbW9zeJjhv+WwoOVH5ri6g2hXtl1zNtv0zd3kNzYap2CrVIz96S KwTJibpnad4u3Iv2YoWEbKesWnxF20patLWFHcSY06+m4ccyohTMyS1B7NjTtN/RFxKrTS N2wsRuQepssLD3UnD/Ac5nHueNVS2QT+FNwdgHALAAArmgZ96S1AtI6xHPzMmw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1662378975; a=rsa-sha256; cv=none; b=xHf3KDIny20f6j+6OJPVXH3OT+vcQ6FobIzIuMsUBuW036nW990bvyrtAJ806mDeDMHY29 HpFu7Pnj7T6cgNwmGM8eGBUCYfNS44389c7ZB46WRXl7KcxS5WrnfDTGpTUCeN9ezY1xW4 nxyk6AkYwEf+4g9mmIDL+FXHedRURCThRQjNGVxwJJYLMk6JlBEbp9LlwGeAhSN27jW3lo /si7aMrqgwOKK5/M08BFcIOd5XeSb3Ihf/n3b8iR5wJWRqfo5GwJEWmm8dvUEB+g+FkOFH qKcnRbBmrPMnAx2Cg0C/rde5d5Utt98uM2beY0nxaCZkwO6WhccTxr46j7XxRA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mjg: URL: https://cgit.FreeBSD.org/src/commit/?id=5ecb5444aa349246568dc6f9a615630e29191f7c commit 5ecb5444aa349246568dc6f9a615630e29191f7c Author: Mateusz Guzik AuthorDate: 2022-03-10 18:42:37 +0000 Commit: Mateusz Guzik CommitDate: 2022-09-05 11:54:47 +0000 jail: add process linkage It allows iteration over processes belonging to given jail instead of having to walk the entire allproc list. Note the iteration can miss processes which remains bug-compatible with previous code. Reviewed by: jamie (previous version), markj (previous version) Differential Revision: https://reviews.freebsd.org/D34522 --- sys/kern/kern_exit.c | 1 + sys/kern/kern_fork.c | 1 + sys/kern/kern_jail.c | 103 ++++++++++++++++++++++++++++++++++++++++++--------- sys/sys/jail.h | 5 +++ sys/sys/proc.h | 1 + 5 files changed, 93 insertions(+), 18 deletions(-) diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index e7a6f8d66c39..3f64343aea0e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -473,6 +473,7 @@ exit1(struct thread *td, int rval, int signo) */ p->p_list.le_prev = NULL; #endif + prison_proc_unlink(p->p_ucred->cr_prison, p); sx_xunlock(&allproc_lock); sx_xlock(&proctree_lock); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 58f386f20544..87c14670ae10 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -398,6 +398,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * sx_xlock(&allproc_lock); LIST_INSERT_HEAD(&allproc, p2, p_list); allproc_gen++; + prison_proc_link(p2->p_ucred->cr_prison, p2); sx_xunlock(&allproc_lock); sx_xlock(PIDHASHLOCK(p2->p_pid)); diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 108432c53bca..853d5b1faf5f 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -147,6 +147,8 @@ static int prison_lock_xlock(struct prison *pr, int flags); static void prison_cleanup(struct prison *pr); static void prison_free_not_last(struct prison *pr); static void prison_proc_free_not_last(struct prison *pr); +static void prison_proc_relink(struct prison *opr, struct prison *npr, + struct proc *p); static void prison_set_allow_locked(struct prison *pr, unsigned flag, int enable); static char *prison_path(struct prison *pr1, struct prison *pr2); @@ -2648,6 +2650,7 @@ do_jail_attach(struct thread *td, struct prison *pr, int drflags) rctl_proc_ucred_changed(p, newcred); crfree(newcred); #endif + prison_proc_relink(oldcred->cr_prison, pr, p); prison_deref(oldcred->cr_prison, drflags); crfree(oldcred); @@ -2919,6 +2922,32 @@ prison_proc_free_not_last(struct prison *pr) #endif } +void +prison_proc_link(struct prison *pr, struct proc *p) +{ + + sx_assert(&allproc_lock, SA_XLOCKED); + LIST_INSERT_HEAD(&pr->pr_proclist, p, p_jaillist); +} + +void +prison_proc_unlink(struct prison *pr, struct proc *p) +{ + + sx_assert(&allproc_lock, SA_XLOCKED); + LIST_REMOVE(p, p_jaillist); +} + +static void +prison_proc_relink(struct prison *opr, struct prison *npr, struct proc *p) +{ + + sx_xlock(&allproc_lock); + prison_proc_unlink(opr, p); + prison_proc_link(npr, p); + sx_xunlock(&allproc_lock); +} + /* * Complete a call to either prison_free or prison_proc_free. */ @@ -2940,6 +2969,60 @@ prison_complete(void *context, int pending) prison_deref(pr, drflags); } +static void +prison_kill_processes_cb(struct proc *p, void *arg __unused) +{ + + kern_psignal(p, SIGKILL); +} + +/* + * Note the iteration does not guarantee acting on all processes. + * Most notably there may be fork or jail_attach in progress. + */ +void +prison_proc_iterate(struct prison *pr, void (*cb)(struct proc *, void *), + void *cbarg) +{ + struct prison *ppr; + struct proc *p; + + if (atomic_load_int(&pr->pr_childcount) == 0) { + sx_slock(&allproc_lock); + LIST_FOREACH(p, &pr->pr_proclist, p_jaillist) { + if (p->p_state == PRS_NEW) + continue; + PROC_LOCK(p); + cb(p, cbarg); + PROC_UNLOCK(p); + } + sx_sunlock(&allproc_lock); + if (atomic_load_int(&pr->pr_childcount) == 0) + return; + /* + * Some jails popped up during the iteration, fall through to a + * system-wide search. + */ + } + + sx_slock(&allproc_lock); + FOREACH_PROC_IN_SYSTEM(p) { + PROC_LOCK(p); + if (p->p_state != PRS_NEW && p->p_ucred != NULL) { + for (ppr = p->p_ucred->cr_prison; + ppr != &prison0; + ppr = ppr->pr_parent) { + if (ppr == pr) { + cb(p, cbarg); + break; + } + } + } + PROC_UNLOCK(p); + } + sx_sunlock(&allproc_lock); +} + /* * Remove a prison reference and/or user reference (usually). * This assumes context that allows sleeping (for allprison_lock), @@ -2953,7 +3036,6 @@ prison_deref(struct prison *pr, int flags) { struct prisonlist freeprison; struct prison *killpr, *rpr, *ppr, *tpr; - struct proc *p; killpr = NULL; TAILQ_INIT(&freeprison); @@ -3064,23 +3146,8 @@ prison_deref(struct prison *pr, int flags) sx_xunlock(&allprison_lock); /* Kill any processes attached to a killed prison. */ - if (killpr != NULL) { - sx_slock(&allproc_lock); - FOREACH_PROC_IN_SYSTEM(p) { - PROC_LOCK(p); - if (p->p_state != PRS_NEW && p->p_ucred != NULL) { - for (ppr = p->p_ucred->cr_prison; - ppr != &prison0; - ppr = ppr->pr_parent) - if (ppr == killpr) { - kern_psignal(p, SIGKILL); - break; - } - } - PROC_UNLOCK(p); - } - sx_sunlock(&allproc_lock); - } + if (killpr != NULL) + prison_proc_iterate(killpr, prison_kill_processes_cb, NULL); /* * Finish removing any unreferenced prisons, which couldn't happen diff --git a/sys/sys/jail.h b/sys/sys/jail.h index b7ecfc198b4c..743b413bc06d 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -159,6 +159,7 @@ typedef enum { * * Lock key: * (a) allprison_lock + * (A) allproc_lock * (c) set only during creation before the structure is shared, no mutex * required to read * (m) locked by pr_mtx @@ -176,6 +177,7 @@ struct prison { volatile u_int pr_uref; /* (r) user (alive) refcount */ unsigned pr_flags; /* (p) PR_* flags */ LIST_HEAD(, prison) pr_children; /* (a) list of child jails */ + LIST_HEAD(, proc) pr_proclist; /* (A) list of jailed processes */ LIST_ENTRY(prison) pr_sibling; /* (a) next in parent's list */ struct prison *pr_parent; /* (c) containing jail */ struct mtx pr_mtx; @@ -432,6 +434,9 @@ void prison_hold(struct prison *pr); void prison_hold_locked(struct prison *pr); void prison_proc_hold(struct prison *); void prison_proc_free(struct prison *); +void prison_proc_link(struct prison *, struct proc *); +void prison_proc_unlink(struct prison *, struct proc *); +void prison_proc_iterate(struct prison *, void (*)(struct proc *, void *), void *); void prison_set_allow(struct ucred *cred, unsigned flag, int enable); int prison_ischild(struct prison *, struct prison *); bool prison_isalive(const struct prison *); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fb1553539b1c..08a74c7326cf 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -773,6 +773,7 @@ struct proc { LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */ TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */ + LIST_ENTRY(proc) p_jaillist; /* (d) Jail process linkage. */ }; #define p_session p_pgrp->pg_session