diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-10-30 20:02:59 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-10-30 20:02:59 +0000 |
commit | a815f9179b6356b872c98792178860f0c06a7554 (patch) | |
tree | 450792b54b08a71c29153b64fd51ebfb307572ca /sys/kern | |
parent | 5b3d505b4e254da05bc3ffa547a6e9f65798bf3d (diff) |
Implement setresuid(2), getresuid(2), setresgid(2), getresgid(2), based
partly on the Linux emul code and FreeBSD versions.
We need these for Linux, FreeBSD, and HP-UX emulation.
Also change sys_setreuid() and sys_setregid() to use uid_t and gid_t
respectively.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_prot.c | 208 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 14 |
2 files changed, 218 insertions, 4 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 45ddf7f7c31..69b0fc2d62e 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_prot.c,v 1.21 2002/10/15 01:27:31 nordin Exp $ */ +/* $OpenBSD: kern_prot.c,v 1.22 2002/10/30 20:02:58 millert Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* @@ -326,6 +326,212 @@ sys_setpgid(curp, v, retval) /* ARGSUSED */ int +sys_getresuid(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_getresuid_args /* { + syscallarg(uid_t *) ruid; + syscallarg(uid_t *) euid; + syscallarg(uid_t *) suid; + } */ *uap = v; + struct pcred *pc = p->p_cred; + uid_t *ruid, *euid, *suid; + int error1 = 0, error2 = 0, error3 = 0; + + ruid = SCARG(uap, ruid); + euid = SCARG(uap, euid); + suid = SCARG(uap, suid); + + if (ruid != NULL) + error1 = copyout(&pc->p_ruid, ruid, sizeof(*ruid)); + if (euid != NULL) + error2 = copyout(&pc->pc_ucred->cr_uid, euid, sizeof(*euid)); + if (suid != NULL) + error3 = copyout(&pc->p_svuid, suid, sizeof(*suid)); + + return (error1 ? error1 : error2 ? error2 : error3); +} + +/* ARGSUSED */ +int +sys_setresuid(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_setresuid_args /* { + syscallarg(uid_t) ruid; + syscallarg(uid_t) euid; + syscallarg(uid_t) suid; + } */ *uap = v; + struct pcred *pc = p->p_cred; + uid_t ruid, euid, suid; + int error; + + ruid = SCARG(uap, ruid); + euid = SCARG(uap, euid); + suid = SCARG(uap, suid); + + if ((ruid == -1 || ruid == pc->p_ruid) && + (euid == -1 || euid == pc->pc_ucred->cr_uid) && + (suid == -1 || suid == pc->p_svuid)) + return (0); /* no change */ + + /* + * Any of the real, effective, and saved uids may be changed + * to the current value of one of the three (root is not limited). + */ + if (ruid != (uid_t)-1 && + ruid != pc->p_ruid && + ruid != pc->pc_ucred->cr_uid && + ruid != pc->p_svuid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + if (euid != (uid_t)-1 && + euid != pc->p_ruid && + euid != pc->pc_ucred->cr_uid && + euid != pc->p_svuid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + if (suid != (uid_t)-1 && + suid != pc->p_ruid && + suid != pc->pc_ucred->cr_uid && + suid != pc->p_svuid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + /* + * Note that unlike the other set*uid() calls, each + * uid type is set independently of the others. + */ + if (ruid != (uid_t)-1 && ruid != pc->p_ruid) { + /* + * Transfer proc count to new user. + */ + (void)chgproccnt(pc->p_ruid, -1); + (void)chgproccnt(ruid, 1); + pc->p_ruid = ruid; + } + if (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid) { + /* + * Copy credentials so other references do not see our changes. + */ + pc->pc_ucred = crcopy(pc->pc_ucred); + pc->pc_ucred->cr_uid = euid; + } + if (suid != (uid_t)-1 && suid != pc->p_svuid) + pc->p_svuid = suid; + + p->p_flag |= P_SUGID; + return (0); +} + +/* ARGSUSED */ +int +sys_getresgid(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_getresgid_args /* { + syscallarg(gid_t *) rgid; + syscallarg(gid_t *) egid; + syscallarg(gid_t *) sgid; + } */ *uap = v; + struct pcred *pc = p->p_cred; + gid_t *rgid, *egid, *sgid; + int error1 = 0, error2 = 0, error3 = 0; + + rgid = SCARG(uap, rgid); + egid = SCARG(uap, egid); + sgid = SCARG(uap, sgid); + + if (rgid != NULL) + error1 = copyout(&pc->p_rgid, rgid, sizeof(*rgid)); + if (egid != NULL) + error2 = copyout(&pc->pc_ucred->cr_gid, egid, sizeof(*egid)); + if (sgid != NULL) + error3 = copyout(&pc->p_svgid, sgid, sizeof(*sgid)); + + return (error1 ? error1 : error2 ? error2 : error3); +} + +/* ARGSUSED */ +int +sys_setresgid(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_setresgid_args /* { + syscallarg(gid_t) rgid; + syscallarg(gid_t) egid; + syscallarg(gid_t) sgid; + } */ *uap = v; + struct pcred *pc = p->p_cred; + gid_t rgid, egid, sgid; + int error; + + rgid = SCARG(uap, rgid); + egid = SCARG(uap, egid); + sgid = SCARG(uap, sgid); + + if ((rgid == -1 || rgid == pc->p_rgid) && + (egid == -1 || egid == pc->pc_ucred->cr_gid) && + (sgid == -1 || sgid == pc->p_svgid)) + return (0); /* no change */ + + /* + * Any of the real, effective, and saved gids may be changed + * to the current value of one of the three (root is not limited). + */ + if (rgid != (gid_t)-1 && + rgid != pc->p_rgid && + rgid != pc->pc_ucred->cr_gid && + rgid != pc->p_svgid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + if (egid != (gid_t)-1 && + egid != pc->p_rgid && + egid != pc->pc_ucred->cr_gid && + egid != pc->p_svgid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + if (sgid != (gid_t)-1 && + sgid != pc->p_rgid && + sgid != pc->pc_ucred->cr_gid && + sgid != pc->p_svgid && + (error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); + + /* + * Note that unlike the other set*gid() calls, each + * gid type is set independently of the others. + */ + if (rgid != (gid_t)-1) + pc->p_rgid = rgid; + if (egid != (gid_t)-1) { + /* + * Copy credentials so other references do not see our changes. + */ + pc->pc_ucred = crcopy(pc->pc_ucred); + pc->pc_ucred->cr_gid = egid; + } + if (sgid != (gid_t)-1) + pc->p_svgid = sgid; + + p->p_flag |= P_SUGID; + return (0); +} + +/* ARGSUSED */ +int sys_setuid(p, v, retval) struct proc *p; void *v; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 8cc3c18b4df..4fd3d529f45 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.50 2002/07/06 19:14:20 nordin Exp $ +; $OpenBSD: syscalls.master,v 1.51 2002/10/30 20:02:58 millert Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -238,8 +238,8 @@ 125 COMPAT_43 { int sys_recvfrom(int s, caddr_t buf, size_t len, \ int flags, caddr_t from, int *fromlenaddr); } \ orecvfrom -126 COMPAT_43 { int sys_setreuid(int ruid, int euid); } osetreuid -127 COMPAT_43 { int sys_setregid(int rgid, int egid); } osetregid +126 COMPAT_43 { int sys_setreuid(uid_t ruid, uid_t euid); } osetreuid +127 COMPAT_43 { int sys_setregid(gid_t rgid, gid_t egid); } osetregid 128 STD { int sys_rename(const char *from, const char *to); } 129 COMPAT_43 { int sys_truncate(const char *path, long length); } \ otruncate @@ -562,3 +562,11 @@ 279 UNIMPL sys_extattr_get_fd 280 UNIMPL sys_extattr_delete_fd #endif +281 STD { int sys_getresuid(uid_t *ruid, uid_t *euid, \ + uid_t *suid); } +282 STD { int sys_setresuid(uid_t ruid, uid_t euid, \ + uid_t suid); } +283 STD { int sys_getresgid(gid_t *rgid, gid_t *egid, \ + gid_t *sgid); } +284 STD { int sys_setresgid(gid_t rgid, gid_t egid, \ + gid_t sgid); } |