summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/syscall
diff options
context:
space:
mode:
authorcasper <none@none>2007-05-25 05:43:42 -0700
committercasper <none@none>2007-05-25 05:43:42 -0700
commitf48205be61a214698b763ff550ab9e657525104c (patch)
treebc63168b8468284765bb770eb48473b7a0bf980e /usr/src/uts/common/syscall
parent7387092aa96cd872b317dfab3fee34a96c681f3e (diff)
downloadillumos-joyent-f48205be61a214698b763ff550ab9e657525104c.tar.gz
PSARC 2007/064 Unified POSIX and Windows Credentials for Solaris
4994017 data structure sharing between rpcbind and libnsl leads to accidents 6549510 Need the ability to store SIDs in the Solaris cred_t 6549515 PSARC 2007/064: uid_t and gid_t to become unsigned
Diffstat (limited to 'usr/src/uts/common/syscall')
-rw-r--r--usr/src/uts/common/syscall/chown.c11
-rw-r--r--usr/src/uts/common/syscall/gid.c72
-rw-r--r--usr/src/uts/common/syscall/groups.c26
-rw-r--r--usr/src/uts/common/syscall/ppriv.c5
-rw-r--r--usr/src/uts/common/syscall/sidsys.c299
-rw-r--r--usr/src/uts/common/syscall/sysconfig.c5
-rw-r--r--usr/src/uts/common/syscall/uid.c71
7 files changed, 443 insertions, 46 deletions
diff --git a/usr/src/uts/common/syscall/chown.c b/usr/src/uts/common/syscall/chown.c
index 7dc7fc663e..d32e16b5c5 100644
--- a/usr/src/uts/common/syscall/chown.c
+++ b/usr/src/uts/common/syscall/chown.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,8 +70,10 @@ cfchownat(int fd, char *name, int nmflag, uid_t uid, gid_t gid, int flags)
int error = 0;
char startchar;
- if (uid < -1 || uid > MAXUID || gid < -1 || gid > MAXUID)
+ if (uid != (uid_t)-1 && !VALID_UID(uid) ||
+ gid != (gid_t)-1 && !VALID_GID(gid)) {
return (set_errno(EINVAL));
+ }
vattr.va_uid = uid;
vattr.va_gid = gid;
vattr.va_mask = 0;
diff --git a/usr/src/uts/common/syscall/gid.c b/usr/src/uts/common/syscall/gid.c
index 1cd5a4fd24..388225b600 100644
--- a/usr/src/uts/common/syscall/gid.c
+++ b/usr/src/uts/common/syscall/gid.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1994,2001-2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,19 +43,28 @@
int
setgid(gid_t gid)
{
- register proc_t *p;
+ proc_t *p;
int error;
int do_nocd = 0;
cred_t *cr, *newcr;
+ ksid_t ksid, *ksp;
- if (gid < 0 || gid > MAXUID)
+ if (!VALID_GID(gid))
return (set_errno(EINVAL));
+ if (gid > MAXUID) {
+ if (ksid_lookup(gid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
+
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
cr = p->p_cred;
@@ -67,6 +75,7 @@ setgid(gid_t gid)
crcopy_to(cr, newcr);
p->p_cred = newcr;
newcr->cr_gid = gid;
+ crsetsid(newcr, ksp, KSID_GROUP);
} else if ((error = secpolicy_allow_setid(cr, -1, B_FALSE)) == 0) {
/*
* A privileged process that makes itself look like a
@@ -81,8 +90,13 @@ setgid(gid_t gid)
newcr->cr_gid = gid;
newcr->cr_rgid = gid;
newcr->cr_sgid = gid;
- } else
+ crsetsid(newcr, ksp, KSID_GROUP);
+ } else {
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
+
+ }
mutex_exit(&p->p_crlock);
@@ -113,19 +127,27 @@ getgid(void)
int
setegid(gid_t gid)
{
- register proc_t *p;
- register cred_t *cr, *newcr;
+ proc_t *p;
+ cred_t *cr, *newcr;
int error = EPERM;
int do_nocd = 0;
+ ksid_t ksid, *ksp;
- if (gid < 0 || gid > MAXUID)
+ if (!VALID_GID(gid))
return (set_errno(EINVAL));
+ if (gid > MAXUID) {
+ if (ksid_lookup(gid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
cr = p->p_cred;
@@ -141,8 +163,12 @@ setegid(gid_t gid)
crcopy_to(cr, newcr);
p->p_cred = newcr;
newcr->cr_gid = gid;
- } else
+ crsetsid(newcr, ksp, KSID_GROUP);
+ } else {
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
+ }
mutex_exit(&p->p_crlock);
@@ -172,16 +198,24 @@ setregid(gid_t rgid, gid_t egid)
int error = EPERM;
int do_nocd = 0;
cred_t *cr, *newcr;
+ ksid_t ksid, *ksp;
- if ((rgid != -1 && (rgid < 0 || rgid > MAXUID)) ||
- (egid != -1 && (egid < 0 || egid > MAXUID)))
+ if ((rgid != -1 && !VALID_GID(rgid)) ||
+ (egid != -1 && !VALID_GID(egid)))
return (set_errno(EINVAL));
+ if (egid != -1 && egid > MAXUID) {
+ if (ksid_lookup(egid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
@@ -196,8 +230,10 @@ setregid(gid_t rgid, gid_t egid)
crcopy_to(cr, newcr);
p->p_cred = newcr;
- if (egid != -1)
+ if (egid != -1) {
newcr->cr_gid = egid;
+ crsetsid(newcr, ksp, KSID_GROUP);
+ }
if (rgid != -1)
newcr->cr_rgid = rgid;
/*
@@ -231,5 +267,7 @@ setregid(gid_t rgid, gid_t egid)
return (0);
}
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
return (set_errno(error));
}
diff --git a/usr/src/uts/common/syscall/groups.c b/usr/src/uts/common/syscall/groups.c
index 88e3777afd..b9a6c23441 100644
--- a/usr/src/uts/common/syscall/groups.c
+++ b/usr/src/uts/common/syscall/groups.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
*/
/*
* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
- * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,6 +47,8 @@ setgroups(int gidsetsize, gid_t *gidset)
int n = gidsetsize;
gid_t *groups = NULL;
int error;
+ int scnt = 0;
+ ksidlist_t *ksl = NULL;
/* Perform the cheapest tests before grabbing p_crlock */
if (n > ngroups_max || n < 0)
@@ -62,18 +63,28 @@ setgroups(int gidsetsize, gid_t *gidset)
}
for (i = 0; i < n; i++) {
- if (groups[i] < 0 || groups[i] > MAXUID) {
+ if (!VALID_GID(groups[i])) {
+ kmem_free(groups, n * sizeof (gid_t));
+ return (set_errno(EINVAL));
+ }
+ if (groups[i] > MAXUID)
+ scnt++;
+ }
+ if (scnt > 0) {
+ ksl = kcrsid_gidstosids(n, groups);
+ if (ksl == NULL) {
kmem_free(groups, n * sizeof (gid_t));
return (set_errno(EINVAL));
}
}
}
+
/*
* Need to pre-allocate the new cred structure before acquiring
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
cr = p->p_cred;
@@ -82,11 +93,14 @@ setgroups(int gidsetsize, gid_t *gidset)
mutex_exit(&p->p_crlock);
if (groups != NULL)
kmem_free(groups, n * sizeof (gid_t));
+ if (ksl != NULL)
+ ksidlist_rele(ksl);
crfree(newcr);
return (set_errno(error));
}
crdup_to(cr, newcr);
+ crsetsidlist(newcr, ksl);
if (n != 0) {
bcopy(groups, newcr->cr_groups, n * sizeof (gid_t));
diff --git a/usr/src/uts/common/syscall/ppriv.c b/usr/src/uts/common/syscall/ppriv.c
index a817bcaec1..e4e04b32a4 100644
--- a/usr/src/uts/common/syscall/ppriv.c
+++ b/usr/src/uts/common/syscall/ppriv.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -336,6 +336,7 @@ int
privsys(int code, priv_op_t op, priv_ptype_t type, void *buf, size_t bufsize)
{
int retv;
+ extern int issetugid(void);
switch (code) {
case PRIVSYS_SETPPRIV:
@@ -354,6 +355,8 @@ privsys(int code, priv_op_t op, priv_ptype_t type, void *buf, size_t bufsize)
case PRIVSYS_GETPFLAGS:
retv = (int)getpflags((uint_t)op, CRED());
return (retv == -1 ? set_errno(EINVAL) : retv);
+ case PRIVSYS_ISSETUGID:
+ return (issetugid());
}
return (set_errno(EINVAL));
}
diff --git a/usr/src/uts/common/syscall/sidsys.c b/usr/src/uts/common/syscall/sidsys.c
new file mode 100644
index 0000000000..bcb749cadc
--- /dev/null
+++ b/usr/src/uts/common/syscall/sidsys.c
@@ -0,0 +1,299 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * SID system call.
+ */
+
+#include <sys/sid.h>
+#include <sys/cred.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/policy.h>
+#include <sys/door.h>
+
+static kmutex_t idmap_mutex;
+
+typedef struct idmap_reg {
+ door_handle_t idmap_door;
+ int idmap_flags;
+ int idmap_ref;
+} idmap_reg_t;
+
+static idmap_reg_t *idmap_ptr;
+
+static int idmap_unreg_dh(door_handle_t);
+
+static void
+idmap_freeone(idmap_reg_t *p)
+{
+ ASSERT(p->idmap_ref == 0);
+ ASSERT(MUTEX_HELD(&idmap_mutex));
+
+ door_ki_rele(p->idmap_door);
+ if (idmap_ptr == p)
+ idmap_ptr = NULL;
+
+ kmem_free(p, sizeof (*p));
+}
+
+static int
+idmap_do_call(sidmap_call_t *callp, size_t callsz, void **resp, size_t *respsz)
+{
+ door_arg_t da;
+ idmap_reg_t *p;
+ int ret;
+ int dres;
+
+ mutex_enter(&idmap_mutex);
+ p = idmap_ptr;
+ if (p != NULL) {
+ p->idmap_ref++;
+ } else {
+ mutex_exit(&idmap_mutex);
+ return (-1);
+ }
+ mutex_exit(&idmap_mutex);
+
+ da.data_ptr = (char *)callp;
+ da.data_size = callsz;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = *resp;
+ da.rsize = *respsz;
+
+ while ((dres = door_ki_upcall(p->idmap_door, &da)) != 0) {
+ switch (dres) {
+ case EINTR:
+ case EAGAIN:
+ delay(1);
+ continue;
+ case EINVAL:
+ case EBADF:
+ (void) idmap_unreg_dh(p->idmap_door);
+ /* FALLTHROUGH */
+ default:
+ ret = -1;
+ goto out;
+ }
+ }
+ *resp = da.rbuf;
+ *respsz = da.rsize;
+ ret = 0;
+out:
+ mutex_enter(&idmap_mutex);
+ if (--p->idmap_ref == 0)
+ idmap_freeone(p);
+ mutex_exit(&idmap_mutex);
+ return (ret);
+}
+
+/*
+ * Current code only attempts to map ids to sids.
+ */
+int
+idmap_call_byid(uid_t id, ksid_t *ksid)
+{
+ sidmap_call_t call;
+ domsid_t res, *resp = &res;
+ size_t respsz = sizeof (res);
+
+ call.sc_type = SIDSYS_ID2SID;
+ call.sc_val.sc_id = id;
+
+ if (idmap_do_call(&call, sizeof (call), (void **)&resp, &respsz) != 0)
+ return (-1);
+
+ ksid->ks_domain = ksid_lookupdomain(resp->ds_dom);
+ ksid->ks_rid = resp->ds_rid;
+
+ /* Larger SID return value; this usually happens */
+ if (resp != &res)
+ kmem_free(resp, respsz);
+
+ return (0);
+}
+
+uid_t
+idmap_call_bysid(ksid_t *ksid)
+{
+ ksiddomain_t *domp = ksid->ks_domain;
+ sidmap_call_t *callp;
+ uid_t res = (uid_t)-1;
+ uid_t *resp = &res;
+ size_t callsz;
+ size_t respsz = sizeof (res);
+
+ callsz = sizeof (sidmap_call_t) + domp->kd_len;
+
+ callp = kmem_alloc(callsz, KM_SLEEP);
+ callp->sc_type = SIDSYS_SID2ID;
+ bcopy(domp->kd_name, callp->sc_val.sc_sid.ds_dom, domp->kd_len);
+ callp->sc_val.sc_sid.ds_rid = ksid->ks_rid;
+
+ if (idmap_do_call(callp, callsz, (void **)&resp, &respsz) != 0)
+ goto out;
+
+ /* Should never happen; the original buffer should be large enough */
+ if (resp != &res) {
+ kmem_free(resp, respsz);
+ goto out;
+ }
+
+ if (respsz != sizeof (uid_t))
+ res = (uid_t)-1;
+
+out:
+ kmem_free(callp, callsz);
+ return (res);
+}
+
+static int
+idmap_reg(int did)
+{
+ door_handle_t dh;
+ idmap_reg_t *idmp;
+ int err;
+
+ if ((err = secpolicy_idmap(CRED())) != 0)
+ return (set_errno(err));
+
+ dh = door_ki_lookup(did);
+
+ if (dh == NULL)
+ return (set_errno(EBADF));
+
+ idmp = kmem_alloc(sizeof (*idmp), KM_SLEEP);
+
+ idmp->idmap_door = dh;
+ mutex_enter(&idmap_mutex);
+ if (idmap_ptr != NULL) {
+ if (--idmap_ptr->idmap_ref == 0)
+ idmap_freeone(idmap_ptr);
+ }
+ idmp->idmap_flags = 0;
+ idmp->idmap_ref = 1;
+ idmap_ptr = idmp;
+ mutex_exit(&idmap_mutex);
+ return (0);
+}
+
+static int
+idmap_unreg_dh(door_handle_t dh)
+{
+ mutex_enter(&idmap_mutex);
+ if (idmap_ptr == NULL || idmap_ptr->idmap_door != dh) {
+ mutex_exit(&idmap_mutex);
+ return (EINVAL);
+ }
+
+ if (idmap_ptr->idmap_flags != 0) {
+ mutex_exit(&idmap_mutex);
+ return (EAGAIN);
+ }
+ idmap_ptr->idmap_flags = 1;
+ if (--idmap_ptr->idmap_ref == 0)
+ idmap_freeone(idmap_ptr);
+ mutex_exit(&idmap_mutex);
+ return (0);
+}
+
+static int
+idmap_unreg(int did)
+{
+ door_handle_t dh = door_ki_lookup(did);
+ int res;
+
+ if (dh == NULL)
+ return (set_errno(EINVAL));
+
+ res = idmap_unreg_dh(dh);
+ door_ki_rele(dh);
+
+ if (res != 0)
+ return (set_errno(res));
+ return (0);
+}
+
+static boolean_t
+its_my_door(void)
+{
+ mutex_enter(&idmap_mutex);
+ if (idmap_ptr != NULL) {
+ struct door_info info;
+ int err = door_ki_info(idmap_ptr->idmap_door, &info);
+ if (err == 0 && info.di_target == curproc->p_pid) {
+ mutex_exit(&idmap_mutex);
+ return (B_TRUE);
+ }
+ }
+ mutex_exit(&idmap_mutex);
+ return (B_FALSE);
+}
+
+static uint64_t
+allocids(int flag, int nuids, int ngids)
+{
+ rval_t r;
+ uid_t su = 0;
+ gid_t sg = 0;
+ int err;
+
+ if (!its_my_door())
+ return (set_errno(EPERM));
+
+ if (nuids < 0 || ngids < 0)
+ return (set_errno(EINVAL));
+
+ if (flag != 0 || nuids > 0)
+ err = eph_uid_alloc(flag, &su, nuids);
+ if (err == 0 && (flag != 0 || ngids > 0))
+ err = eph_gid_alloc(flag, &sg, ngids);
+
+ if (err != 0)
+ return (set_errno(EOVERFLOW));
+
+ r.r_val1 = su;
+ r.r_val2 = sg;
+ return (r.r_vals);
+}
+
+uint64_t
+sidsys(int op, int flag, int nuids, int ngids)
+{
+ switch (op) {
+ case SIDSYS_ALLOC_IDS:
+ return (allocids(flag, nuids, ngids));
+ case SIDSYS_IDMAP_REG:
+ return (idmap_reg(flag));
+ case SIDSYS_IDMAP_UNREG:
+ return (idmap_unreg(flag));
+ default:
+ return (set_errno(EINVAL));
+ }
+}
diff --git a/usr/src/uts/common/syscall/sysconfig.c b/usr/src/uts/common/syscall/sysconfig.c
index 02c756dcb6..5db23fee7b 100644
--- a/usr/src/uts/common/syscall/sysconfig.c
+++ b/usr/src/uts/common/syscall/sysconfig.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -164,6 +164,9 @@ sysconfig(int which)
case _CONFIG_CPUID_MAX:
return (max_cpuid);
+ case _CONFIG_EPHID_MAX:
+ return (MAXEPHUID);
+
case _CONFIG_SYMLOOP_MAX:
return (MAXSYMLINKS);
}
diff --git a/usr/src/uts/common/syscall/uid.c b/usr/src/uts/common/syscall/uid.c
index 65bcabcaf0..24e1e92f82 100644
--- a/usr/src/uts/common/syscall/uid.c
+++ b/usr/src/uts/common/syscall/uid.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,26 +41,35 @@
#include <sys/debug.h>
#include <sys/policy.h>
#include <sys/zone.h>
+#include <sys/sid.h>
int
setuid(uid_t uid)
{
- register proc_t *p;
+ proc_t *p;
int error;
int do_nocd = 0;
int uidchge = 0;
cred_t *cr, *newcr;
uid_t oldruid = uid;
zoneid_t zoneid = getzoneid();
+ ksid_t ksid, *ksp;
- if (uid < 0 || uid > MAXUID)
+ if (!VALID_UID(uid))
return (set_errno(EINVAL));
+ if (uid > MAXUID) {
+ if (ksid_lookup(uid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
@@ -75,6 +83,7 @@ retry:
crcopy_to(cr, newcr);
p->p_cred = newcr;
newcr->cr_uid = uid;
+ crsetsid(newcr, ksp, KSID_USER);
} else if ((error = secpolicy_allow_setid(cr, uid, B_FALSE)) == 0) {
if (!uidchge && uid != cr->cr_ruid) {
/*
@@ -111,9 +120,13 @@ retry:
newcr->cr_ruid = uid;
newcr->cr_suid = uid;
newcr->cr_uid = uid;
+ crsetsid(newcr, ksp, KSID_USER);
ASSERT(uid != oldruid ? uidchge : 1);
- } else
+ } else {
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
+ }
mutex_exit(&p->p_crlock);
@@ -155,19 +168,28 @@ getuid(void)
int
seteuid(uid_t uid)
{
- register proc_t *p;
+ proc_t *p;
int error = EPERM;
int do_nocd = 0;
cred_t *cr, *newcr;
+ ksid_t ksid, *ksp;
- if (uid < 0 || uid > MAXUID)
+ if (!VALID_UID(uid))
return (set_errno(EINVAL));
+ if (uid > MAXUID) {
+ if (ksid_lookup(uid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
+
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
mutex_enter(&p->p_crlock);
cr = p->p_cred;
@@ -185,8 +207,12 @@ seteuid(uid_t uid)
crcopy_to(cr, newcr);
p->p_cred = newcr;
newcr->cr_uid = uid;
- } else
+ crsetsid(newcr, ksp, KSID_USER);
+ } else {
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
+ }
mutex_exit(&p->p_crlock);
@@ -219,16 +245,25 @@ setreuid(uid_t ruid, uid_t euid)
uid_t oldruid = ruid;
cred_t *cr, *newcr;
zoneid_t zoneid = getzoneid();
+ ksid_t ksid, *ksp;
- if ((ruid != -1 && (ruid < 0 || ruid > MAXUID)) ||
- (euid != -1 && (euid < 0 || euid > MAXUID)))
+ if ((ruid != -1 && !VALID_UID(ruid)) ||
+ (euid != -1 && !VALID_UID(euid)))
return (set_errno(EINVAL));
+ if (euid != -1 && euid > MAXUID) {
+ if (ksid_lookup(euid, &ksid) != 0)
+ return (set_errno(EINVAL));
+ ksp = &ksid;
+ } else {
+ ksp = NULL;
+ }
+
/*
* Need to pre-allocate the new cred structure before grabbing
* the p_crlock mutex.
*/
- newcr = cralloc();
+ newcr = cralloc_ksid();
p = ttoproc(curthread);
@@ -269,8 +304,10 @@ retry:
crcopy_to(cr, newcr);
p->p_cred = newcr;
- if (euid != -1)
+ if (euid != -1) {
newcr->cr_uid = euid;
+ crsetsid(newcr, ksp, KSID_USER);
+ }
if (ruid != -1) {
oldruid = newcr->cr_ruid;
newcr->cr_ruid = ruid;
@@ -319,5 +356,7 @@ retry:
return (0);
}
crfree(newcr);
+ if (ksp != NULL)
+ ksid_rele(ksp);
return (set_errno(error));
}