summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_exec.c5
-rw-r--r--sys/kern/kern_prot.c54
2 files changed, 44 insertions, 15 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 913f951..39da17e 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -128,6 +128,7 @@ execve(td, uap)
struct proc *p = td->td_proc;
struct nameidata nd, *ndp;
struct ucred *newcred = NULL, *oldcred;
+ struct uidinfo *euip;
register_t *stack_base;
int error, len, i;
struct image_params image_params, *imgp;
@@ -303,6 +304,7 @@ interpret:
* Malloc things before we need locks.
*/
newcred = crget();
+ euip = uifind(attr.va_uid);
i = imgp->endargs - imgp->stringbase;
if (ps_arg_cache_limit >= i + sizeof(struct pargs))
newargs = pargs_alloc(i);
@@ -390,7 +392,7 @@ interpret:
*/
crcopy(newcred, oldcred);
if (attr.va_mode & VSUID)
- change_euid(newcred, attr.va_uid);
+ change_euid(newcred, euip);
if (attr.va_mode & VSGID)
change_egid(newcred, attr.va_gid);
setugidsafety(td);
@@ -472,6 +474,7 @@ interpret:
/*
* Free any resources malloc'd earlier that we didn't use.
*/
+ uifree(euip);
if (newcred == NULL)
crfree(oldcred);
else
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index cadfd62..20273ce 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -503,11 +503,13 @@ setuid(struct thread *td, struct setuid_args *uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t uid;
+ struct uidinfo *uip;
int error;
mtx_lock(&Giant);
uid = uap->uid;
newcred = crget();
+ uip = uifind(uid);
PROC_LOCK(p);
oldcred = p->p_ucred;
@@ -537,11 +539,15 @@ setuid(struct thread *td, struct setuid_args *uap)
#endif
(error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
PROC_UNLOCK(p);
+ uifree(uip);
crfree(newcred);
mtx_unlock(&Giant);
return (error);
}
+ /*
+ * Copy credentials so other references do not see our changes.
+ */
crcopy(newcred, oldcred);
#ifdef _POSIX_SAVED_IDS
/*
@@ -559,7 +565,7 @@ setuid(struct thread *td, struct setuid_args *uap)
* Set the real uid and transfer proc count to new user.
*/
if (uid != oldcred->cr_ruid) {
- change_ruid(newcred, uid);
+ change_ruid(newcred, uip);
setsugid(p);
}
/*
@@ -577,14 +583,14 @@ setuid(struct thread *td, struct setuid_args *uap)
/*
* In all permitted cases, we are changing the euid.
- * Copy credentials so other references do not see our changes.
*/
if (uid != oldcred->cr_uid) {
- change_euid(newcred, uid);
+ change_euid(newcred, uip);
setsugid(p);
}
p->p_ucred = newcred;
PROC_UNLOCK(p);
+ uifree(uip);
crfree(oldcred);
mtx_unlock(&Giant);
return (0);
@@ -605,17 +611,20 @@ seteuid(struct thread *td, struct seteuid_args *uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t euid;
+ struct uidinfo *euip;
int error;
euid = uap->euid;
mtx_lock(&Giant);
newcred = crget();
+ euip = uifind(euid);
PROC_LOCK(p);
oldcred = p->p_ucred;
if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */
euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */
(error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
PROC_UNLOCK(p);
+ uifree(euip);
crfree(newcred);
mtx_unlock(&Giant);
return (error);
@@ -626,11 +635,12 @@ seteuid(struct thread *td, struct seteuid_args *uap)
*/
crcopy(newcred, oldcred);
if (oldcred->cr_uid != euid) {
- change_euid(newcred, euid);
+ change_euid(newcred, euip);
setsugid(p);
}
p->p_ucred = newcred;
PROC_UNLOCK(p);
+ uifree(euip);
crfree(oldcred);
mtx_unlock(&Giant);
return (0);
@@ -858,12 +868,15 @@ setreuid(register struct thread *td, struct setreuid_args *uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t euid, ruid;
+ struct uidinfo *euip, *ruip;
int error;
euid = uap->euid;
ruid = uap->ruid;
mtx_lock(&Giant);
newcred = crget();
+ euip = uifind(euid);
+ ruip = uifind(ruid);
PROC_LOCK(p);
oldcred = p->p_ucred;
if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
@@ -872,17 +885,19 @@ setreuid(register struct thread *td, struct setreuid_args *uap)
euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
(error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
PROC_UNLOCK(p);
+ uifree(ruip);
+ uifree(euip);
crfree(newcred);
mtx_unlock(&Giant);
return (error);
}
crcopy(newcred, oldcred);
if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
- change_euid(newcred, euid);
+ change_euid(newcred, euip);
setsugid(p);
}
if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
- change_ruid(newcred, ruid);
+ change_ruid(newcred, ruip);
setsugid(p);
}
if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) &&
@@ -892,6 +907,8 @@ setreuid(register struct thread *td, struct setreuid_args *uap)
}
p->p_ucred = newcred;
PROC_UNLOCK(p);
+ uifree(ruip);
+ uifree(euip);
crfree(oldcred);
mtx_unlock(&Giant);
return (0);
@@ -975,6 +992,7 @@ setresuid(register struct thread *td, struct setresuid_args *uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t euid, ruid, suid;
+ struct uidinfo *euip, *ruip;
int error;
euid = uap->euid;
@@ -982,6 +1000,8 @@ setresuid(register struct thread *td, struct setresuid_args *uap)
suid = uap->suid;
mtx_lock(&Giant);
newcred = crget();
+ euip = uifind(euid);
+ ruip = uifind(ruid);
PROC_LOCK(p);
oldcred = p->p_ucred;
if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
@@ -995,6 +1015,8 @@ setresuid(register struct thread *td, struct setresuid_args *uap)
suid != oldcred->cr_uid)) &&
(error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
PROC_UNLOCK(p);
+ uifree(ruip);
+ uifree(euip);
crfree(newcred);
mtx_unlock(&Giant);
return (error);
@@ -1002,11 +1024,11 @@ setresuid(register struct thread *td, struct setresuid_args *uap)
crcopy(newcred, oldcred);
if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
- change_euid(newcred, euid);
+ change_euid(newcred, euip);
setsugid(p);
}
if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) {
- change_ruid(newcred, ruid);
+ change_ruid(newcred, ruip);
setsugid(p);
}
if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) {
@@ -1015,6 +1037,8 @@ setresuid(register struct thread *td, struct setresuid_args *uap)
}
p->p_ucred = newcred;
PROC_UNLOCK(p);
+ uifree(ruip);
+ uifree(euip);
crfree(oldcred);
mtx_unlock(&Giant);
return (0);
@@ -1876,12 +1900,13 @@ setsugid(struct proc *p)
* duration of the call.
*/
void
-change_euid(struct ucred *newcred, uid_t euid)
+change_euid(struct ucred *newcred, struct uidinfo *euip)
{
- newcred->cr_uid = euid;
+ newcred->cr_uid = euip->ui_uid;
+ uihold(euip);
uifree(newcred->cr_uidinfo);
- newcred->cr_uidinfo = uifind(euid);
+ newcred->cr_uidinfo = euip;
}
/*-
@@ -1906,13 +1931,14 @@ change_egid(struct ucred *newcred, gid_t egid)
* duration of the call.
*/
void
-change_ruid(struct ucred *newcred, uid_t ruid)
+change_ruid(struct ucred *newcred, struct uidinfo *ruip)
{
(void)chgproccnt(newcred->cr_ruidinfo, -1, 0);
- newcred->cr_ruid = ruid;
+ newcred->cr_ruid = ruip->ui_uid;
+ uihold(ruip);
uifree(newcred->cr_ruidinfo);
- newcred->cr_ruidinfo = uifind(ruid);
+ newcred->cr_ruidinfo = ruip;
(void)chgproccnt(newcred->cr_ruidinfo, 1, 0);
}
OpenPOWER on IntegriCloud