⬢ DragonFlyBSD Kernel Audit
DF-5337 / fix.diff
← back to finding ↓ download raw
--- a/sys/platform/vkernel64/x86_64/trap.c
+++ b/sys/platform/vkernel64/x86_64/trap.c
@@ -87,6 +87,7 @@
 #include <ddb/ddb.h>
 
 #include <sys/msgport2.h>
+#include <sys/spinlock2.h>
 #include <sys/thread2.h>
 #include <sys/mplock2.h>
 
@@ -155,6 +156,9 @@
  * signal handling, faults, AST traps, and anything else that enters the
  * kernel from userland and provides the kernel with a stable read-only
  * copy of the process ucred.
+ *
+ * To avoid races with another thread updating p_ucred we obtain p_spin.
+ * The other thread doing the update will obtain both p_token and p_spin.
  */
 static __inline void
 userenter(struct thread *curtd, struct proc *curp)
@@ -164,8 +168,10 @@
 
 	curtd->td_release = lwkt_passive_release;
 
-	if (curtd->td_ucred != curp->p_ucred) {
+	if (__predict_false(curtd->td_ucred != curp->p_ucred)) {
+		spin_lock(&curp->p_spin);
 		ncred = crhold(curp->p_ucred);
+		spin_unlock(&curp->p_spin);
 		ocred = curtd->td_ucred;
 		curtd->td_ucred = ncred;
 		if (ocred)