On Mon, Feb 10, 2025 at 09:45:46AM -0700, Theo de Raadt wrote:
> CVSROOT: /cvs
> Module name: src
> Changes by: [email protected] 2025/02/10 09:45:46
>
> Modified files:
> sys/sys : proc.h
> sys/kern : kern_event.c kern_pledge.c
> sys/dev/vmm : vmm.c
>
> Log message:
> A syzkaller report was diagnosed by semarie, and found a namei-related
> sleeping system call which was re-inspecting p->p_p->ps_pledge in one thread,
> after another thread had reduced the promises by calling pledge(), with
> promises which would have prevented that syscall from being called in
> the first place. This inconsistant promise view is dangerous. So let's
> change pledge semantics a tiny bit: We copy the per-process p_p->ps_pledge
> value to per-thread p_pledge at invocation of each system call, so that the
> configuration is stable.
> This method avoids increasing the cost of pledge checks.
> ok claudio kettenis semarie
This broke regress/sys/kern/pledge/execpromise. Keeping the new p_pledge
proc field in sync upon exec fixes the regression.
diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
index de95acf6b190..4e278920c7d3 100644
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -572,11 +572,13 @@ sys_execve(struct proc *p, void *v, register_t *retval)
atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC);
if (pr->ps_flags & PS_EXECPLEDGE) {
+ p->p_pledge = pr->ps_execpledge;
pr->ps_pledge = pr->ps_execpledge;
atomic_setbits_int(&pr->ps_flags, PS_PLEDGE);
} else {
atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE);
pr->ps_pledge = 0;
+ p->p_pledge = 0;
/* XXX XXX XXX XXX */
/* Clear our unveil paths out so the child
* starts afresh