summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/subr_trap.c')
-rw-r--r--sys/kern/subr_trap.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index d599b91..cefce4e 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -131,7 +131,6 @@ ast(framep)
#endif
KASSERT(TRAPF_USERMODE(framep), ("ast in kernel mode"));
- KASSERT(td->td_ucred == NULL, ("leaked ucred"));
#ifdef WITNESS
if (witness_list(td))
panic("Returning to user mode with mutex(s) held");
@@ -161,6 +160,30 @@ ast(framep)
p->p_stats->p_prof.pr_ticks = 0;
}
mtx_unlock_spin(&sched_lock);
+
+#ifdef DIAGNOSTIC
+ /*
+ * As a diagnostic tool we make sure that td->td_ucred
+ * is NULL while we are in user space. This is
+ * because theoreticaly this field is only defined
+ * while the thread is in the kernel. Making it NULL
+ * will immediatly trap invalid usage of this field.
+ * In practice however we keep the reference to the ucred
+ * because it's almost always going to be the same cred we will
+ * need at the next syscall, and it can be expensive
+ * to keep dropping and reacquiring the reference.
+ * We thus stash it away elsewhere until we return
+ * to the kernel, where we bring it back. If
+ * DIAGNOSTIC is not defined we don't bother with
+ * making it NULL, and just leave it in place.
+ * (don't remove this comment without removing the pointers
+ * to it in sys/proc.h, */*/trap.c, kern/kern_fork.c and here.)
+ */
+ if (td->td_ucred)
+ panic("ast:thread got a cred before reaching AST");
+ td->td_ucred = td->td_ucred_cache;
+ td->td_ucred_cache = NULL;
+#endif /* DIAGNOSTIC */
if (td->td_ucred != p->p_ucred)
cred_update_thread(td);
if (flags & KEF_OWEUPC && sflag & PS_PROFIL)
@@ -187,12 +210,13 @@ ast(framep)
}
userret(td, framep, sticks);
-#ifdef INVARIANTS
- mtx_lock(&Giant);
- crfree(td->td_ucred);
- mtx_unlock(&Giant);
+#ifdef DIAGNOSTIC /* see comment above */
+ if (td->td_ucred_cache)
+ panic("ast:thread already has cached ucred");
+ td->td_ucred_cache = td->td_ucred;
td->td_ucred = NULL;
-#endif
+#endif /* DIAGNOSTIC */
+
s = cpu_critical_enter();
}
mtx_assert(&Giant, MA_NOTOWNED);
OpenPOWER on IntegriCloud