⬢ DragonFlyBSD Kernel Audit
DF-5822 / fix.diff
← back to finding ↓ download raw
--- 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);