DF-5822 / fix.diff
--- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1666,7 +1666,13 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS) int error = 0; int n; int origcpu; - struct ucred *cr1 = curproc->p_ucred; + /* + * cr1 is used across blocking SYSCTL_OUT()s and must carry a + * reference. td_ucred is the trap-layer cache which is held + * (crhold) for the duration of the syscall, while p_ucred can + * be replaced and crfree()d concurrently (cratom_proc()). + */ + struct ucred *cr1 = curthread->td_ucred; struct ucred *crcache = NULL; flags = oid & KERN_PROC_FLAGMASK; @@ -1875,7 +1881,8 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) #endif struct pargs *pa; int error = 0; - struct ucred *cr1 = curproc->p_ucred; + /* referenced credential; p_ucred may be replaced+freed */ + struct ucred *cr1 = curthread->td_ucred; if (namelen != 1 && namelen != 2) return (EINVAL); @@ -2035,7 +2042,8 @@ sysctl_kern_proc_cwd(SYSCTL_HANDLER_ARGS) struct proc *p; int error = 0; char *fullpath, *freepath; - struct ucred *cr1 = curproc->p_ucred; + /* referenced credential; p_ucred may be replaced+freed */ + struct ucred *cr1 = curthread->td_ucred; if (namelen != 1) return (EINVAL); |