diff options
Diffstat (limited to 'sys/kern/kern_prot.c')
| -rw-r--r-- | sys/kern/kern_prot.c | 54 |
1 files changed, 15 insertions, 39 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index f93cee6d7698..3c145851b683 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -832,31 +832,22 @@ kern_setcred(struct thread *const td, const u_int flags, if (error != 0) goto unlock_finish; -#ifdef RACCT /* - * Hold a reference to 'new_cred', as we need to call some functions on - * it after proc_set_cred_enforce_proc_lim(). + * Set the new credentials, noting that they have changed. */ - crhold(new_cred); -#endif - - /* Set the new credentials. */ cred_set = proc_set_cred_enforce_proc_lim(p, new_cred); if (cred_set) { setsugid(p); + to_free_cred = old_cred; #ifdef RACCT - /* Adjust RACCT counters. */ racct_proc_ucred_changed(p, old_cred, new_cred); #endif - to_free_cred = old_cred; - MPASS(error == 0); - } else { -#ifdef RACCT - /* Matches the crhold() just before the containing 'if'. */ - crfree(new_cred); +#ifdef RCTL + crhold(new_cred); #endif + MPASS(error == 0); + } else error = EAGAIN; - } unlock_finish: PROC_UNLOCK(p); @@ -866,12 +857,10 @@ unlock_finish: * finishing operations. */ -#ifdef RACCT - if (cred_set) { #ifdef RCTL + if (cred_set) { rctl_proc_ucred_changed(p, new_cred); -#endif - /* Paired with the crhold() above. */ + /* Paired with the crhold() just above. */ crfree(new_cred); } #endif @@ -1002,19 +991,16 @@ sys_setuid(struct thread *td, struct setuid_args *uap) change_euid(newcred, uip); setsugid(p); } - + /* + * This also transfers the proc count to the new user. + */ + proc_set_cred(p, newcred); #ifdef RACCT racct_proc_ucred_changed(p, oldcred, newcred); #endif #ifdef RCTL crhold(newcred); #endif - /* - * Takes over 'newcred''s reference, so 'newcred' must not be used - * besides this point except on RCTL where we took an additional - * reference above. - */ - proc_set_cred(p, newcred); PROC_UNLOCK(p); #ifdef RCTL rctl_proc_ucred_changed(p, newcred); @@ -1418,18 +1404,13 @@ sys_setreuid(struct thread *td, struct setreuid_args *uap) change_svuid(newcred, newcred->cr_uid); setsugid(p); } + proc_set_cred(p, newcred); #ifdef RACCT racct_proc_ucred_changed(p, oldcred, newcred); #endif #ifdef RCTL crhold(newcred); #endif - /* - * Takes over 'newcred''s reference, so 'newcred' must not be used - * besides this point except on RCTL where we took an additional - * reference above. - */ - proc_set_cred(p, newcred); PROC_UNLOCK(p); #ifdef RCTL rctl_proc_ucred_changed(p, newcred); @@ -1571,18 +1552,13 @@ sys_setresuid(struct thread *td, struct setresuid_args *uap) change_svuid(newcred, suid); setsugid(p); } + proc_set_cred(p, newcred); #ifdef RACCT racct_proc_ucred_changed(p, oldcred, newcred); #endif #ifdef RCTL crhold(newcred); #endif - /* - * Takes over 'newcred''s reference, so 'newcred' must not be used - * besides this point except on RCTL where we took an additional - * reference above. - */ - proc_set_cred(p, newcred); PROC_UNLOCK(p); #ifdef RCTL rctl_proc_ucred_changed(p, newcred); @@ -2807,7 +2783,7 @@ cru2xt(struct thread *td, struct xucred *xcr) * 'enforce_proc_lim' being true and if no new process can be accounted to the * new real UID because of the current limit (see the inner comment for more * details) and the caller does not have privilege (PRIV_PROC_LIMIT) to override - * that. In this case, the reference to 'newcred' is not taken over. + * that. */ static bool _proc_set_cred(struct proc *p, struct ucred *newcred, bool enforce_proc_lim) |
