Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_prot.c
| Show First 20 Lines • Show All 826 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| /* | /* | ||||
| * Privilege check. | * Privilege check. | ||||
| */ | */ | ||||
| error = priv_check_cred(old_cred, PRIV_CRED_SETCRED); | error = priv_check_cred(old_cred, PRIV_CRED_SETCRED); | ||||
| if (error != 0) | if (error != 0) | ||||
| goto unlock_finish; | goto unlock_finish; | ||||
| #ifdef RACCT | |||||
| /* | /* | ||||
| * Set the new credentials, noting that they have changed. | * Hold a reference to 'new_cred', as we need to call some functions on | ||||
| * it after proc_set_cred_enforce_proc_lim(). | |||||
| */ | */ | ||||
| crhold(new_cred); | |||||
| #endif | |||||
| /* Set the new credentials. */ | |||||
| cred_set = proc_set_cred_enforce_proc_lim(p, new_cred); | cred_set = proc_set_cred_enforce_proc_lim(p, new_cred); | ||||
| if (cred_set) { | if (cred_set) { | ||||
| setsugid(p); | setsugid(p); | ||||
| to_free_cred = old_cred; | |||||
| #ifdef RACCT | #ifdef RACCT | ||||
| /* Adjust RACCT counters. */ | |||||
| racct_proc_ucred_changed(p, old_cred, new_cred); | racct_proc_ucred_changed(p, old_cred, new_cred); | ||||
| #endif | #endif | ||||
| #ifdef RCTL | to_free_cred = old_cred; | ||||
| crhold(new_cred); | |||||
| #endif | |||||
| MPASS(error == 0); | MPASS(error == 0); | ||||
| } else | } else { | ||||
| #ifdef RACCT | |||||
| /* Matches the crhold() just before the containing 'if'. */ | |||||
| crfree(new_cred); | |||||
| #endif | |||||
| error = EAGAIN; | error = EAGAIN; | ||||
| } | |||||
| unlock_finish: | unlock_finish: | ||||
| PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
| /* | /* | ||||
| * Part 3: After releasing the process lock, we perform cleanups and | * Part 3: After releasing the process lock, we perform cleanups and | ||||
| * finishing operations. | * finishing operations. | ||||
| */ | */ | ||||
| #ifdef RCTL | #ifdef RACCT | ||||
| if (cred_set) { | if (cred_set) { | ||||
| #ifdef RCTL | |||||
| rctl_proc_ucred_changed(p, new_cred); | rctl_proc_ucred_changed(p, new_cred); | ||||
| /* Paired with the crhold() just above. */ | #endif | ||||
| /* Paired with the crhold() above. */ | |||||
| crfree(new_cred); | crfree(new_cred); | ||||
| } | } | ||||
| #endif | #endif | ||||
| #ifdef MAC | #ifdef MAC | ||||
| if (mac_set_proc_data != NULL) | if (mac_set_proc_data != NULL) | ||||
| mac_set_proc_finish(td, proc_label_set, mac_set_proc_data); | mac_set_proc_finish(td, proc_label_set, mac_set_proc_data); | ||||
| mac_cred_setcred_exit(); | mac_cred_setcred_exit(); | ||||
| ▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | #endif | ||||
| /* | /* | ||||
| * In all permitted cases, we are changing the euid. | * In all permitted cases, we are changing the euid. | ||||
| */ | */ | ||||
| if (uid != oldcred->cr_uid) { | if (uid != oldcred->cr_uid) { | ||||
| change_euid(newcred, uip); | change_euid(newcred, uip); | ||||
| setsugid(p); | setsugid(p); | ||||
| } | } | ||||
| /* | |||||
| * This also transfers the proc count to the new user. | |||||
| */ | |||||
| proc_set_cred(p, newcred); | |||||
| #ifdef RACCT | #ifdef RACCT | ||||
| racct_proc_ucred_changed(p, oldcred, newcred); | racct_proc_ucred_changed(p, oldcred, newcred); | ||||
| #endif | #endif | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| crhold(newcred); | crhold(newcred); | ||||
| #endif | #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); | PROC_UNLOCK(p); | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| rctl_proc_ucred_changed(p, newcred); | rctl_proc_ucred_changed(p, newcred); | ||||
| crfree(newcred); | crfree(newcred); | ||||
| #endif | #endif | ||||
| uifree(uip); | uifree(uip); | ||||
| crfree(oldcred); | crfree(oldcred); | ||||
| return (0); | return (0); | ||||
| ▲ Show 20 Lines • Show All 387 Lines • ▼ Show 20 Lines | if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { | ||||
| change_ruid(newcred, ruip); | change_ruid(newcred, ruip); | ||||
| setsugid(p); | setsugid(p); | ||||
| } | } | ||||
| if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && | if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && | ||||
| newcred->cr_svuid != newcred->cr_uid) { | newcred->cr_svuid != newcred->cr_uid) { | ||||
| change_svuid(newcred, newcred->cr_uid); | change_svuid(newcred, newcred->cr_uid); | ||||
| setsugid(p); | setsugid(p); | ||||
| } | } | ||||
| proc_set_cred(p, newcred); | |||||
| #ifdef RACCT | #ifdef RACCT | ||||
| racct_proc_ucred_changed(p, oldcred, newcred); | racct_proc_ucred_changed(p, oldcred, newcred); | ||||
| #endif | #endif | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| crhold(newcred); | crhold(newcred); | ||||
| #endif | #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); | PROC_UNLOCK(p); | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| rctl_proc_ucred_changed(p, newcred); | rctl_proc_ucred_changed(p, newcred); | ||||
| crfree(newcred); | crfree(newcred); | ||||
| #endif | #endif | ||||
| uifree(ruip); | uifree(ruip); | ||||
| uifree(euip); | uifree(euip); | ||||
| crfree(oldcred); | crfree(oldcred); | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | #endif | ||||
| if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { | if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { | ||||
| change_ruid(newcred, ruip); | change_ruid(newcred, ruip); | ||||
| setsugid(p); | setsugid(p); | ||||
| } | } | ||||
| if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { | if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { | ||||
| change_svuid(newcred, suid); | change_svuid(newcred, suid); | ||||
| setsugid(p); | setsugid(p); | ||||
| } | } | ||||
| proc_set_cred(p, newcred); | |||||
| #ifdef RACCT | #ifdef RACCT | ||||
| racct_proc_ucred_changed(p, oldcred, newcred); | racct_proc_ucred_changed(p, oldcred, newcred); | ||||
| #endif | #endif | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| crhold(newcred); | crhold(newcred); | ||||
| #endif | #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); | PROC_UNLOCK(p); | ||||
| #ifdef RCTL | #ifdef RCTL | ||||
| rctl_proc_ucred_changed(p, newcred); | rctl_proc_ucred_changed(p, newcred); | ||||
| crfree(newcred); | crfree(newcred); | ||||
| #endif | #endif | ||||
| uifree(ruip); | uifree(ruip); | ||||
| uifree(euip); | uifree(euip); | ||||
| crfree(oldcred); | crfree(oldcred); | ||||
| ▲ Show 20 Lines • Show All 1,208 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * Callers are responsible for providing the reference for passed credentials | * Callers are responsible for providing the reference for passed credentials | ||||
| * and for freeing old ones. Calls chgproccnt() to correctly account the | * and for freeing old ones. Calls chgproccnt() to correctly account the | ||||
| * current process to the proper real UID, if the latter has changed. Returns | * current process to the proper real UID, if the latter has changed. Returns | ||||
| * whether the operation was successful. Failure can happen only on | * whether the operation was successful. Failure can happen only on | ||||
| * 'enforce_proc_lim' being true and if no new process can be accounted to the | * '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 | * 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 | * details) and the caller does not have privilege (PRIV_PROC_LIMIT) to override | ||||
| * that. | * that. In this case, the reference to 'newcred' is not taken over. | ||||
| */ | */ | ||||
| static bool | static bool | ||||
| _proc_set_cred(struct proc *p, struct ucred *newcred, bool enforce_proc_lim) | _proc_set_cred(struct proc *p, struct ucred *newcred, bool enforce_proc_lim) | ||||
| { | { | ||||
| struct ucred *const oldcred = p->p_ucred; | struct ucred *const oldcred = p->p_ucred; | ||||
| MPASS(oldcred != NULL); | MPASS(oldcred != NULL); | ||||
| PROC_LOCK_ASSERT(p, MA_OWNED); | PROC_LOCK_ASSERT(p, MA_OWNED); | ||||
| ▲ Show 20 Lines • Show All 421 Lines • Show Last 20 Lines | |||||