summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-10-30 20:02:59 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-10-30 20:02:59 +0000
commita815f9179b6356b872c98792178860f0c06a7554 (patch)
tree450792b54b08a71c29153b64fd51ebfb307572ca /sys/kern
parent5b3d505b4e254da05bc3ffa547a6e9f65798bf3d (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.c208
-rw-r--r--sys/kern/syscalls.master14
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); }