diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 07067c407b3f..bc31c8ce21ec 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 @@ trap(frame) 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 @@ syscall(frame) */ 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 07067c407b3f..bc31c8ce21ec 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 @@ trap(frame) 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 @@ syscall(frame) */ 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 3223f8b55386..c7cbf2808543 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 4214cc1ddf40..f7056a0eca53 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1683,6 +1683,27 @@ crdup(cr) return (newcr); } +/* + * 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. */ diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 9c24e172215c..d599b91bfa23 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 d92b45deafdc..d26f3183fe84 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);