summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/trap.c14
-rw-r--r--sys/i386/i386/trap.c14
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_prot.c21
-rw-r--r--sys/kern/subr_trap.c7
-rw-r--r--sys/sys/ucred.h1
6 files changed, 44 insertions, 15 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 07067c4..bc31c8c 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -256,9 +256,8 @@ trap(frame)
sticks = td->td_kse->ke_sticks;
td->td_frame = &frame;
KASSERT(td->td_ucred == NULL, ("already have a ucred"));
- PROC_LOCK(p);
- td->td_ucred = crhold(p->p_ucred);
- PROC_UNLOCK(p);
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
switch (type) {
case T_PRIVINFLT: /* privileged instruction fault */
@@ -644,10 +643,12 @@ user:
userret(td, &frame, sticks);
mtx_assert(&Giant, MA_NOTOWNED);
userout:
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
out:
return;
}
@@ -954,9 +955,8 @@ syscall(frame)
sticks = td->td_kse->ke_sticks;
td->td_frame = &frame;
KASSERT(td->td_ucred == NULL, ("already have a ucred"));
- PROC_LOCK(p);
- td->td_ucred = crhold(p->p_ucred);
- PROC_UNLOCK(p);
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
params = (caddr_t)frame.tf_esp + sizeof(int);
code = frame.tf_eax;
orig_tf_eflags = frame.tf_eflags;
@@ -1099,10 +1099,12 @@ bad:
*/
STOPEVENT(p, S_SCX, code);
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
#ifdef WITNESS
if (witness_list(td)) {
panic("system call %s returning with mutex(s) held\n",
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 07067c4..bc31c8c 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -256,9 +256,8 @@ trap(frame)
sticks = td->td_kse->ke_sticks;
td->td_frame = &frame;
KASSERT(td->td_ucred == NULL, ("already have a ucred"));
- PROC_LOCK(p);
- td->td_ucred = crhold(p->p_ucred);
- PROC_UNLOCK(p);
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
switch (type) {
case T_PRIVINFLT: /* privileged instruction fault */
@@ -644,10 +643,12 @@ user:
userret(td, &frame, sticks);
mtx_assert(&Giant, MA_NOTOWNED);
userout:
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
out:
return;
}
@@ -954,9 +955,8 @@ syscall(frame)
sticks = td->td_kse->ke_sticks;
td->td_frame = &frame;
KASSERT(td->td_ucred == NULL, ("already have a ucred"));
- PROC_LOCK(p);
- td->td_ucred = crhold(p->p_ucred);
- PROC_UNLOCK(p);
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
params = (caddr_t)frame.tf_esp + sizeof(int);
code = frame.tf_eax;
orig_tf_eflags = frame.tf_eflags;
@@ -1099,10 +1099,12 @@ bad:
*/
STOPEVENT(p, S_SCX, code);
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
#ifdef WITNESS
if (witness_list(td)) {
panic("system call %s returning with mutex(s) held\n",
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 3223f8b..c7cbf28 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -799,10 +799,12 @@ fork_exit(callout, arg, frame)
kthread_exit(0);
}
PROC_UNLOCK(p);
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
mtx_assert(&Giant, MA_NOTOWNED);
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 4214cc1..f7056a0 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1684,6 +1684,27 @@ crdup(cr)
}
/*
+ * small routine to swap a thread's current ucred for the correct one
+ * taken from the process.
+ */
+void
+cred_update_thread(struct thread *td)
+{
+ struct proc *p;
+
+ p = td->td_proc;
+ if (td->td_ucred != NULL) {
+ mtx_lock(&Giant);
+ crfree(td->td_ucred);
+ mtx_unlock(&Giant);
+ td->td_ucred = NULL;
+ }
+ PROC_LOCK(p);
+ td->td_ucred = crhold(p->p_ucred);
+ PROC_UNLOCK(p);
+}
+
+/*
* Get login name, if available.
*/
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 9c24e17..d599b91 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -161,9 +161,8 @@ ast(framep)
p->p_stats->p_prof.pr_ticks = 0;
}
mtx_unlock_spin(&sched_lock);
- PROC_LOCK(p);
- td->td_ucred = crhold(p->p_ucred);
- PROC_UNLOCK(p);
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
if (flags & KEF_OWEUPC && sflag & PS_PROFIL)
addupc_task(ke, p->p_stats->p_prof.pr_addr, prticks);
if (sflag & PS_ALRMPEND) {
@@ -188,10 +187,12 @@ ast(framep)
}
userret(td, framep, sticks);
+#ifdef INVARIANTS
mtx_lock(&Giant);
crfree(td->td_ucred);
mtx_unlock(&Giant);
td->td_ucred = NULL;
+#endif
s = cpu_critical_enter();
}
mtx_assert(&Giant, MA_NOTOWNED);
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index d92b45d..d26f318 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -83,6 +83,7 @@ struct xucred {
#ifdef _KERNEL
+void cred_update_thread(struct thread *td);
void change_egid (struct ucred *newcred, gid_t egid);
void change_euid (struct ucred *newcred, uid_t euid);
void change_rgid (struct ucred *newcred, gid_t rgid);
OpenPOWER on IntegriCloud