The branch stable/12 has been updated by jamie:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f7007a7d05255a6859dea0982b1f0a6d695e8881

commit f7007a7d05255a6859dea0982b1f0a6d695e8881
Author:     Jamie Gritton <[email protected]>
AuthorDate: 2021-02-16 19:19:13 +0000
Commit:     Jamie Gritton <[email protected]>
CommitDate: 2021-02-19 21:44:19 +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.
    
    Reported by:    trasz
    Approved by:    kib
    
    (cherry picked from commit cc7b73065302005ebc4a19503188c8d6d5eb923d)
---
 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 
*/
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to