diff options
Diffstat (limited to 'sys/kern/kern_prot.c')
-rw-r--r-- | sys/kern/kern_prot.c | 451 |
1 files changed, 271 insertions, 180 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index f0b4ff8..fcef6d0 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -210,7 +210,7 @@ getuid(p, uap) struct getuid_args *uap; { - p->p_retval[0] = p->p_cred->p_ruid; + p->p_retval[0] = p->p_ucred->cr_ruid; #if defined(COMPAT_43) || defined(COMPAT_SUNOS) p->p_retval[1] = p->p_ucred->cr_uid; #endif @@ -253,7 +253,7 @@ getgid(p, uap) struct getgid_args *uap; { - p->p_retval[0] = p->p_cred->p_rgid; + p->p_retval[0] = p->p_ucred->cr_rgid; #if defined(COMPAT_43) || defined(COMPAT_SUNOS) p->p_retval[1] = p->p_ucred->cr_groups[0]; #endif @@ -293,18 +293,18 @@ getgroups(p, uap) struct proc *p; register struct getgroups_args *uap; { - register struct pcred *pc = p->p_cred; - register u_int ngrp; + struct ucred *cred = p->p_ucred; + u_int ngrp; int error; if ((ngrp = uap->gidsetsize) == 0) { - p->p_retval[0] = pc->pc_ucred->cr_ngroups; + p->p_retval[0] = cred->cr_ngroups; return (0); } - if (ngrp < pc->pc_ucred->cr_ngroups) + if (ngrp < cred->cr_ngroups) return (EINVAL); - ngrp = pc->pc_ucred->cr_ngroups; - if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, + ngrp = cred->cr_ngroups; + if ((error = copyout((caddr_t)cred->cr_groups, (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) return (error); p->p_retval[0] = ngrp; @@ -427,10 +427,12 @@ setuid(p, uap) struct proc *p; struct setuid_args *uap; { - register struct pcred *pc = p->p_cred; - register uid_t uid; + struct ucred *newcred, *oldcred; + uid_t uid; int error; + uid = uap->uid; + oldcred = p->p_ucred; /* * See if we have "permission" by POSIX 1003.1 rules. * @@ -448,17 +450,17 @@ setuid(p, uap) * change. Determined by compile options. * 3: Change euid last. (after tests in #2 for "appropriate privs") */ - uid = uap->uid; - if (uid != pc->p_ruid && /* allow setuid(getuid()) */ + if (uid != oldcred->cr_ruid && /* allow setuid(getuid()) */ #ifdef _POSIX_SAVED_IDS - uid != pc->p_svuid && /* allow setuid(saved gid) */ + uid != oldcred->cr_svuid && /* allow setuid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ + uid != oldcred->cr_uid && /* allow setuid(geteuid()) */ #endif - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) return (error); + newcred = crdup(oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or uid == euid) @@ -466,16 +468,16 @@ setuid(p, uap) */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ - uid == pc->pc_ucred->cr_uid || + uid == oldcred->cr_uid || #endif - suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ + suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ #endif { /* * Set the real uid and transfer proc count to new user. */ - if (uid != pc->p_ruid) { - change_ruid(p, uid); + if (uid != oldcred->cr_ruid) { + change_ruid(newcred, uid); setsugid(p); } /* @@ -485,8 +487,8 @@ setuid(p, uap) * the security of seteuid() depends on it. B.4.2.2 says it * is important that we should do this. */ - if (pc->p_svuid != uid) { - pc->p_svuid = uid; + if (uid != oldcred->cr_svuid) { + change_svuid(newcred, uid); setsugid(p); } } @@ -495,10 +497,12 @@ setuid(p, uap) * In all permitted cases, we are changing the euid. * Copy credentials so other references do not see our changes. */ - if (pc->pc_ucred->cr_uid != uid) { - change_euid(p, uid); + if (uid != oldcred->cr_uid) { + change_euid(newcred, uid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -513,23 +517,27 @@ seteuid(p, uap) struct proc *p; struct seteuid_args *uap; { - register struct pcred *pc = p->p_cred; - register uid_t euid; + struct ucred *newcred, *oldcred; + uid_t euid; int error; euid = uap->euid; - if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ - euid != pc->p_svuid && /* allow seteuid(saved uid) */ - (error = suser_xxx(0, p, PRISON_ROOT))) + oldcred = p->p_ucred; + if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */ + euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */ + (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) return (error); /* * Everything's okay, do it. Copy credentials so other references do * not see our changes. */ - if (pc->pc_ucred->cr_uid != euid) { - change_euid(p, euid); + newcred = crdup(oldcred); + if (oldcred->cr_uid != euid) { + change_euid(newcred, euid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -544,10 +552,12 @@ setgid(p, uap) struct proc *p; struct setgid_args *uap; { - register struct pcred *pc = p->p_cred; - register gid_t gid; + struct ucred *newcred, *oldcred; + gid_t gid; int error; + gid = uap->gid; + oldcred = p->p_ucred; /* * See if we have "permission" by POSIX 1003.1 rules. * @@ -559,17 +569,17 @@ setgid(p, uap) * * For notes on the logic here, see setuid() above. */ - gid = uap->gid; - if (gid != pc->p_rgid && /* allow setgid(getgid()) */ + if (gid != oldcred->cr_rgid && /* allow setgid(getgid()) */ #ifdef _POSIX_SAVED_IDS - gid != pc->p_svgid && /* allow setgid(saved gid) */ + gid != oldcred->cr_svgid && /* allow setgid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ - gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ + gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */ #endif - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) return (error); + newcred = crdup(oldcred); #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or gid == egid) @@ -577,16 +587,16 @@ setgid(p, uap) */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ - gid == pc->pc_ucred->cr_groups[0] || + gid == oldcred->cr_groups[0] || #endif - suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ + suser_xxx(oldcred, NULL, PRISON_ROOT) == 0) /* we are using privs */ #endif { /* * Set real gid */ - if (pc->p_rgid != gid) { - pc->p_rgid = gid; + if (oldcred->cr_rgid != gid) { + change_rgid(newcred, gid); setsugid(p); } /* @@ -596,8 +606,8 @@ setgid(p, uap) * the security of setegid() depends on it. B.4.2.2 says it * is important that we should do this. */ - if (pc->p_svgid != gid) { - pc->p_svgid = gid; + if (oldcred->cr_svgid != gid) { + change_svgid(newcred, gid); setsugid(p); } } @@ -605,11 +615,12 @@ setgid(p, uap) * In all cases permitted cases, we are changing the egid. * Copy credentials so other references do not see our changes. */ - if (pc->pc_ucred->cr_groups[0] != gid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_groups[0] = gid; + if (oldcred->cr_groups[0] != gid) { + change_egid(newcred, gid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -624,20 +635,23 @@ setegid(p, uap) struct proc *p; struct setegid_args *uap; { - register struct pcred *pc = p->p_cred; - register gid_t egid; + struct ucred *newcred, *oldcred; + gid_t egid; int error; egid = uap->egid; - if (egid != pc->p_rgid && /* allow setegid(getgid()) */ - egid != pc->p_svgid && /* allow setegid(saved gid) */ - (error = suser_xxx(0, p, PRISON_ROOT))) + oldcred = p->p_ucred; + if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */ + egid != oldcred->cr_svgid && /* allow setegid(saved gid) */ + (error = suser_xxx(oldcred, NULL, PRISON_ROOT))) return (error); - if (pc->pc_ucred->cr_groups[0] != egid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_groups[0] = egid; + newcred = crdup(oldcred); + if (oldcred->cr_groups[0] != egid) { + change_egid(newcred, egid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -653,20 +667,21 @@ setgroups(p, uap) struct proc *p; struct setgroups_args *uap; { - register struct pcred *pc = p->p_cred; - register u_int ngrp; + struct ucred *newcred, *oldcred; + u_int ngrp; int error; - if ((error = suser_xxx(0, p, PRISON_ROOT))) - return (error); ngrp = uap->gidsetsize; + oldcred = p->p_ucred; + if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT))) + return (error); if (ngrp > NGROUPS) return (EINVAL); /* * XXX A little bit lazy here. We could test if anything has * changed before crcopy() and setting P_SUGID. */ - pc->pc_ucred = crcopy(pc->pc_ucred); + newcred = crdup(oldcred); if (ngrp < 1) { /* * setgroups(0, NULL) is a legitimate way of clearing the @@ -674,14 +689,18 @@ setgroups(p, uap) * have the egid in the groups[0]). We risk security holes * when running non-BSD software if we do not do the same. */ - pc->pc_ucred->cr_ngroups = 1; + newcred->cr_ngroups = 1; } else { if ((error = copyin((caddr_t)uap->gidset, - (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) + (caddr_t)newcred->cr_groups, ngrp * sizeof(gid_t)))) { + crfree(newcred); return (error); - pc->pc_ucred->cr_ngroups = ngrp; + } + newcred->cr_ngroups = ngrp; } setsugid(p); + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -697,31 +716,35 @@ setreuid(p, uap) register struct proc *p; struct setreuid_args *uap; { - register struct pcred *pc = p->p_cred; - register uid_t ruid, euid; + struct ucred *newcred, *oldcred; + uid_t ruid, euid; int error; ruid = uap->ruid; euid = uap->euid; - if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || - (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && - euid != pc->p_ruid && euid != pc->p_svuid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + oldcred = p->p_ucred; + if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && + ruid != oldcred->cr_svuid) || + (euid != (uid_t)-1 && euid != oldcred->cr_uid && + euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) && + (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) return (error); - - if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { - change_euid(p, euid); + newcred = crdup(oldcred); + if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { + change_euid(newcred, euid); setsugid(p); } - if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { - change_ruid(p, ruid); + if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { + change_ruid(newcred, ruid); setsugid(p); } - if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && - pc->p_svuid != pc->pc_ucred->cr_uid) { - pc->p_svuid = pc->pc_ucred->cr_uid; + if ((ruid != (uid_t)-1 || newcred->cr_uid != newcred->cr_ruid) && + newcred->cr_svuid != newcred->cr_uid) { + change_svuid(newcred, newcred->cr_uid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -737,30 +760,32 @@ setregid(p, uap) register struct proc *p; struct setregid_args *uap; { - register struct pcred *pc = p->p_cred; - register gid_t rgid, egid; + struct ucred *newcred, *oldcred; + gid_t rgid, egid; int error; rgid = uap->rgid; egid = uap->egid; - if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || - (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && - egid != pc->p_rgid && egid != pc->p_svgid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + oldcred = p->p_ucred; + if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && + rgid != oldcred->cr_svgid) || + (egid != (gid_t)-1 && egid != oldcred->cr_groups[0] && + egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) && + (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) return (error); - if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_groups[0] = egid; + newcred = crdup(oldcred); + if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + change_egid(newcred, egid); setsugid(p); } - if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { - pc->p_rgid = rgid; + if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { + change_rgid(newcred, rgid); setsugid(p); } - if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && - pc->p_svgid != pc->pc_ucred->cr_groups[0]) { - pc->p_svgid = pc->pc_ucred->cr_groups[0]; + if ((rgid != (gid_t)-1 || newcred->cr_groups[0] != newcred->cr_rgid) && + newcred->cr_svgid != newcred->cr_groups[0]) { + change_svgid(newcred, newcred->cr_groups[0]); setsugid(p); } return (0); @@ -784,33 +809,41 @@ setresuid(p, uap) register struct proc *p; struct setresuid_args *uap; { - register struct pcred *pc = p->p_cred; - register uid_t ruid, euid, suid; + struct ucred *newcred, *oldcred; + uid_t ruid, euid, suid; int error; ruid = uap->ruid; euid = uap->euid; suid = uap->suid; - if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && - ruid != pc->pc_ucred->cr_uid) || - (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && - euid != pc->pc_ucred->cr_uid) || - (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && - suid != pc->pc_ucred->cr_uid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + oldcred = p->p_ucred; + if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid && + ruid != oldcred->cr_svuid && + ruid != oldcred->cr_uid) || + (euid != (uid_t)-1 && euid != oldcred->cr_ruid && + euid != oldcred->cr_svuid && + euid != oldcred->cr_uid) || + (suid != (uid_t)-1 && suid != oldcred->cr_ruid && + suid != oldcred->cr_svuid && + suid != oldcred->cr_uid)) && + (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) return (error); - if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { - change_euid(p, euid); + + newcred = crdup(oldcred); + if (euid != (uid_t)-1 && oldcred->cr_uid != euid) { + change_euid(newcred, euid); setsugid(p); } - if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { - change_ruid(p, ruid); + if (ruid != (uid_t)-1 && oldcred->cr_ruid != ruid) { + change_ruid(newcred, ruid); setsugid(p); } - if (suid != (uid_t)-1 && pc->p_svuid != suid) { - pc->p_svuid = suid; + if (suid != (uid_t)-1 && oldcred->cr_svuid != suid) { + change_svuid(newcred, suid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -832,35 +865,41 @@ setresgid(p, uap) register struct proc *p; struct setresgid_args *uap; { - register struct pcred *pc = p->p_cred; - register gid_t rgid, egid, sgid; + struct ucred *newcred, *oldcred; + gid_t rgid, egid, sgid; int error; rgid = uap->rgid; egid = uap->egid; sgid = uap->sgid; - if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && - rgid != pc->pc_ucred->cr_groups[0]) || - (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && - egid != pc->pc_ucred->cr_groups[0]) || - (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && - sgid != pc->pc_ucred->cr_groups[0])) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + oldcred = p->p_ucred; + if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid && + rgid != oldcred->cr_svgid && + rgid != oldcred->cr_groups[0]) || + (egid != (gid_t)-1 && egid != oldcred->cr_rgid && + egid != oldcred->cr_svgid && + egid != oldcred->cr_groups[0]) || + (sgid != (gid_t)-1 && sgid != oldcred->cr_rgid && + sgid != oldcred->cr_svgid && + sgid != oldcred->cr_groups[0])) && + (error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) return (error); - if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_groups[0] = egid; + newcred = crdup(oldcred); + if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) { + change_egid(newcred, egid); setsugid(p); } - if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { - pc->p_rgid = rgid; + if (rgid != (gid_t)-1 && oldcred->cr_rgid != rgid) { + change_rgid(newcred, rgid); setsugid(p); } - if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { - pc->p_svgid = sgid; + if (sgid != (gid_t)-1 && oldcred->cr_svgid != sgid) { + change_svgid(newcred, sgid); setsugid(p); } + p->p_ucred = newcred; + crfree(oldcred); return (0); } @@ -877,18 +916,18 @@ getresuid(p, uap) register struct proc *p; struct getresuid_args *uap; { - struct pcred *pc = p->p_cred; + struct ucred *cred = p->p_ucred; int error1 = 0, error2 = 0, error3 = 0; if (uap->ruid) - error1 = copyout((caddr_t)&pc->p_ruid, - (caddr_t)uap->ruid, sizeof(pc->p_ruid)); + error1 = copyout((caddr_t)&cred->cr_ruid, + (caddr_t)uap->ruid, sizeof(cred->cr_ruid)); if (uap->euid) - error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, - (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); + error2 = copyout((caddr_t)&cred->cr_uid, + (caddr_t)uap->euid, sizeof(cred->cr_uid)); if (uap->suid) - error3 = copyout((caddr_t)&pc->p_svuid, - (caddr_t)uap->suid, sizeof(pc->p_svuid)); + error3 = copyout((caddr_t)&cred->cr_svuid, + (caddr_t)uap->suid, sizeof(cred->cr_svuid)); return error1 ? error1 : (error2 ? error2 : error3); } @@ -905,18 +944,18 @@ getresgid(p, uap) register struct proc *p; struct getresgid_args *uap; { - struct pcred *pc = p->p_cred; + struct ucred *cred = p->p_ucred; int error1 = 0, error2 = 0, error3 = 0; if (uap->rgid) - error1 = copyout((caddr_t)&pc->p_rgid, - (caddr_t)uap->rgid, sizeof(pc->p_rgid)); + error1 = copyout((caddr_t)&cred->cr_rgid, + (caddr_t)uap->rgid, sizeof(cred->cr_rgid)); if (uap->egid) - error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], - (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); + error2 = copyout((caddr_t)&cred->cr_groups[0], + (caddr_t)uap->egid, sizeof(cred->cr_groups[0])); if (uap->sgid) - error3 = copyout((caddr_t)&pc->p_svgid, - (caddr_t)uap->sgid, sizeof(pc->p_svgid)); + error3 = copyout((caddr_t)&cred->cr_svgid, + (caddr_t)uap->sgid, sizeof(cred->cr_svgid)); return error1 ? error1 : (error2 ? error2 : error3); } @@ -972,7 +1011,7 @@ __setugid(p, uap) int groupmember(gid, cred) gid_t gid; - register struct ucred *cred; + struct ucred *cred; { register gid_t *gp; gid_t *egp; @@ -1038,7 +1077,7 @@ u_cansee(struct ucred *u1, struct ucred *u2) if ((error = prison_check(u1, u2))) return (error); - if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) { + if (!ps_showallprocs && u1->cr_ruid != u2->cr_ruid) { if (suser_xxx(u1, NULL, PRISON_ROOT) != 0) return (ESRCH); } @@ -1113,10 +1152,10 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum) * Generally, the object credential's ruid or svuid must match the * subject credential's ruid or euid. */ - if (p1->p_cred->p_ruid != p2->p_cred->p_ruid && - p1->p_cred->p_ruid != p2->p_cred->p_svuid && - p1->p_ucred->cr_uid != p2->p_cred->p_ruid && - p1->p_ucred->cr_uid != p2->p_cred->p_svuid) { + if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid && + p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid && + p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid && + p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) { /* Not permitted, try privilege. */ error = suser_xxx(NULL, p1, PRISON_ROOT); if (error) @@ -1140,9 +1179,9 @@ p_cansched(struct proc *p1, struct proc *p2, int *privused) if ((error = prison_check(p1->p_ucred, p2->p_ucred))) return (error); - if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) + if (p1->p_ucred->cr_ruid == p2->p_ucred->cr_ruid) return (0); - if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) + if (p1->p_ucred->cr_uid == p2->p_ucred->cr_ruid) return (0); if (!suser_xxx(0, p1, PRISON_ROOT)) { @@ -1178,9 +1217,9 @@ p_candebug(struct proc *p1, struct proc *p2, int *privused) /* not owned by you, has done setuid (unless you're root) */ /* add a CAP_SYS_PTRACE here? */ - if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->pc_ucred->cr_uid || - p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_svuid || - p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid || + if (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid || + p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid || + p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid || p2->p_flag & P_SUGID) { if ((error = suser_xxx(0, p1, PRISON_ROOT))) return (error); @@ -1308,6 +1347,7 @@ crdup(cr) *newcr = *cr; mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); uihold(newcr->cr_uidinfo); + uihold(newcr->cr_ruidinfo); if (jailed(newcr)) prison_hold(newcr->cr_prison); newcr->cr_ref = 1; @@ -1375,48 +1415,99 @@ setsugid(p) } /* - * Helper function to change the effective uid of a process + * change_euid(): Change a process's effective uid. + * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified. + * References: newcred must be an exclusive credential reference for the + * duration of the call. */ void -change_euid(p, euid) - struct proc *p; - uid_t euid; +change_euid(newcred, euid) + struct ucred *newcred; + uid_t euid; { - struct pcred *pc; - struct uidinfo *uip; - pc = p->p_cred; - /* - * crcopy is essentially a NOP if ucred has a reference count - * of 1, which is true if it has already been copied. - */ - pc->pc_ucred = crcopy(pc->pc_ucred); - uip = pc->pc_ucred->cr_uidinfo; - pc->pc_ucred->cr_uid = euid; - pc->pc_ucred->cr_uidinfo = uifind(euid); - uifree(uip); + newcred->cr_uid = euid; + uifree(newcred->cr_uidinfo); + newcred->cr_uidinfo = uifind(euid); } /* - * Helper function to change the real uid of a process - * - * The per-uid process count for this process is transfered from - * the old uid to the new uid. + * change_egid(): Change a process's effective gid. + * Side effects: newcred->cr_gid will be modified. + * References: newcred must be an exclusive credential reference for the + * duration of the call. */ void -change_ruid(p, ruid) - struct proc *p; - uid_t ruid; +change_egid(newcred, egid) + struct ucred *newcred; + gid_t egid; +{ + + newcred->cr_groups[0] = egid; +} + +/* + * change_ruid(): Change a process's real uid. + * Side effects: newcred->cr_ruid will be updated, newcred->cr_ruidinfo + * will be updated, and the old and new cr_ruidinfo proc + * counts will be updated. + * References: newcred must be an exclusive credential reference for the + * duration of the call. + */ +void +change_ruid(newcred, ruid) + struct ucred *newcred; + uid_t ruid; +{ + + (void)chgproccnt(newcred->cr_ruidinfo, -1, 0); + newcred->cr_ruid = ruid; + uifree(newcred->cr_ruidinfo); + newcred->cr_ruidinfo = uifind(ruid); + (void)chgproccnt(newcred->cr_ruidinfo, 1, 0); +} + +/* + * change_rgid(): Change a process's real gid. + * Side effects: newcred->cr_rgid will be updated. + * References: newcred must be an exclusive credential reference for the + * duration of the call. + */ +void +change_rgid(newcred, rgid) + struct ucred *newcred; + gid_t rgid; { - struct pcred *pc; - struct uidinfo *uip; - - pc = p->p_cred; - (void)chgproccnt(pc->p_uidinfo, -1, 0); - uip = pc->p_uidinfo; - /* It is assumed that pcred is not shared between processes */ - pc->p_ruid = ruid; - pc->p_uidinfo = uifind(ruid); - (void)chgproccnt(pc->p_uidinfo, 1, 0); - uifree(uip); + + newcred->cr_rgid = rgid; +} + +/* + * change_svuid(): Change a process's saved uid. + * Side effects: newcred->cr_svuid will be updated. + * References: newcred must be an exclusive credential reference for the + * duration of the call. + */ +void +change_svuid(newcred, svuid) + struct ucred *newcred; + uid_t svuid; +{ + + newcred->cr_svuid = svuid; +} + +/* + * change_svgid(): Change a process's saved gid. + * Side effects: newcred->cr_svgid will be updated. + * References: newcred must be an exclusive credential reference for the + * duration of the call. + */ +void +change_svgid(newcred, svgid) + struct ucred *newcred; + gid_t svgid; +{ + + newcred->cr_svgid = svgid; } |