aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2023-07-07 17:19:33 +0000
committerGordon Tetlow <gordon@FreeBSD.org>2024-06-18 17:26:29 +0000
commiteb410545d00d55a40c4c30eb42b9d2ef5bb2361d (patch)
tree042e9d94ac755d8aaff8c0474d7ba5fb7dae04b4
parentd45cf1d2f1249d5b30c9fa0d35476dc9b9ee0321 (diff)
killpg(): more carefully avoid LoR
Approved by: so Security: FreeBSD-EN-24:12.killpg (cherry picked from commit 7a70f17ac4bd64dc1a5020f963ba4380cf37b7e5) (cherry picked from commit cd73b38955f62d9c05ded8e641a7462ca0f06179)
-rw-r--r--sys/kern/kern_proc.c15
-rw-r--r--sys/kern/kern_prot.c6
2 files changed, 15 insertions, 6 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 61c389f0b345..0db3718e15ff 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -587,8 +587,12 @@ enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp, struct session *sess)
("enterpgrp: session leader attempted setpgrp"));
old_pgrp = p->p_pgrp;
- if (!sx_try_xlock(&old_pgrp->pg_killsx))
+ if (!sx_try_xlock(&old_pgrp->pg_killsx)) {
+ sx_xunlock(&proctree_lock);
+ sx_xlock(&old_pgrp->pg_killsx);
+ sx_xunlock(&old_pgrp->pg_killsx);
return (ERESTART);
+ }
MPASS(old_pgrp == p->p_pgrp);
if (sess != NULL) {
@@ -656,11 +660,18 @@ enterthispgrp(struct proc *p, struct pgrp *pgrp)
("%s: p %p belongs to pgrp %p", __func__, p, pgrp));
old_pgrp = p->p_pgrp;
- if (!sx_try_xlock(&old_pgrp->pg_killsx))
+ if (!sx_try_xlock(&old_pgrp->pg_killsx)) {
+ sx_xunlock(&proctree_lock);
+ sx_xlock(&old_pgrp->pg_killsx);
+ sx_xunlock(&old_pgrp->pg_killsx);
return (ERESTART);
+ }
MPASS(old_pgrp == p->p_pgrp);
if (!sx_try_xlock(&pgrp->pg_killsx)) {
sx_xunlock(&old_pgrp->pg_killsx);
+ sx_xunlock(&proctree_lock);
+ sx_xlock(&pgrp->pg_killsx);
+ sx_xunlock(&pgrp->pg_killsx);
return (ERESTART);
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index a91b7ec3015f..5dea43971e3d 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -345,10 +345,8 @@ again:
error = EPERM;
} else {
error = enterpgrp(p, p->p_pid, newpgrp, newsess);
- if (error == ERESTART) {
- sx_xunlock(&proctree_lock);
+ if (error == ERESTART)
goto again;
- }
MPASS(error == 0);
td->td_retval[0] = p->p_pid;
newpgrp = NULL;
@@ -458,11 +456,11 @@ again:
error = enterthispgrp(targp, pgrp);
}
done:
- sx_xunlock(&proctree_lock);
KASSERT(error == 0 || newpgrp != NULL,
("setpgid failed and newpgrp is NULL"));
if (error == ERESTART)
goto again;
+ sx_xunlock(&proctree_lock);
uma_zfree(pgrp_zone, newpgrp);
return (error);
}