From owner-dev-commits-src-branches@freebsd.org Wed Feb 24 01:42:04 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id D881355BCF8; Wed, 24 Feb 2021 01:42:04 +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 4DldvJ5qLLz3Gt8; Wed, 24 Feb 2021 01:42:04 +0000 (UTC) (envelope-from git@FreeBSD.org) 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 BAC2624183; Wed, 24 Feb 2021 01:42:04 +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 11O1g47p054459; Wed, 24 Feb 2021 01:42:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 11O1g4fS054458; Wed, 24 Feb 2021 01:42:04 GMT (envelope-from git) Date: Wed, 24 Feb 2021 01:42:04 GMT Message-Id: <202102240142.11O1g4fS054458@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: b306be13a9c7 - releng/12.2 - MFC jail: Handle a possible race between jail_remove(2) and fork(2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/releng/12.2 X-Git-Reftype: branch X-Git-Commit: b306be13a9c7ea0db8979a8a53dca93f90ec59cc Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Feb 2021 01:42:04 -0000 The branch releng/12.2 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=b306be13a9c7ea0db8979a8a53dca93f90ec59cc commit b306be13a9c7ea0db8979a8a53dca93f90ec59cc Author: Jamie Gritton AuthorDate: 2021-02-16 19:19:13 +0000 Commit: Mark Johnston CommitDate: 2021-02-24 01:41:49 +0000 MFC jail: Handle a possible race between jail_remove(2) and fork(2) jail_remove(2) includes a loop that sends SIGKILL to all processes in a jail, but skips processes in PRS_NEW state. Thus it is possible the a process in mid-fork(2) during jail removal can survive the jail being removed. Add a prison flag PR_REMOVE, which is checked before the new process returns. If the jail is being removed, the process will then exit. Also check this flag in jail_attach(2) which has a similar issue. Approved by: so Security: CVE-2020-25581 Security: FreeBSD-SA-21:04.jail_remove Reported by: mjg Approved by: kib (cherry picked from commit cc7b73065302005ebc4a19503188c8d6d5eb923d) (cherry picked from commit f7007a7d05255a6859dea0982b1f0a6d695e8881) --- sys/kern/kern_fork.c | 6 ++++++ sys/kern/kern_jail.c | 18 ++++++++++++++++++ sys/sys/jail.h | 1 + 3 files changed, 25 insertions(+) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index e427164cd150..f8e134c30948 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1138,6 +1138,12 @@ fork_return(struct thread *td, struct trapframe *frame) PROC_UNLOCK(p); } + /* + * If the prison was killed mid-fork, die along with it. + */ + if (td->td_ucred->cr_prison->pr_flags & PR_REMOVE) + exit1(td, 0, SIGKILL); + userret(td, frame); #ifdef KTRACE diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 60cbea3c9849..b4a20b4d29e9 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -1768,6 +1768,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) } } pr->pr_flags = (pr->pr_flags & ~ch_flags) | pr_flags; + pr->pr_flags &= ~PR_REMOVE; mtx_unlock(&pr->pr_mtx); #ifdef RACCT @@ -2306,6 +2307,12 @@ prison_remove_one(struct prison *pr) struct proc *p; int deuref; + /* + * Mark the prison as doomed, so it doesn't accidentally come back + * to life. It may still be explicitly brought back by jail_set(2). + */ + pr->pr_flags |= PR_REMOVE; + /* If the prison was persistent, it is not anymore. */ deuref = 0; if (pr->pr_flags & PR_PERSIST) { @@ -2450,6 +2457,17 @@ do_jail_attach(struct thread *td, struct prison *pr) #endif prison_deref(oldcred->cr_prison, PD_DEREF | PD_DEUREF); crfree(oldcred); + + /* + * If the prison was killed while changing credentials, die along + * with it. + */ + if (pr->pr_flags & PR_REMOVE) { + PROC_LOCK(p); + kern_psignal(p, SIGKILL); + PROC_UNLOCK(p); + } + return (0); e_unlock: diff --git a/sys/sys/jail.h b/sys/sys/jail.h index 878b97a064a3..8baf784d6b6d 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -213,6 +213,7 @@ struct prison_racct { /* primary jail address. */ /* Internal flag bits */ +#define PR_REMOVE 0x01000000 /* In process of being removed */ #define PR_IP4 0x02000000 /* IPv4 restricted or disabled */ /* by this jail or an ancestor */ #define PR_IP6 0x04000000 /* IPv6 restricted or disabled */