diff options
author | casper <none@none> | 2007-05-25 05:43:42 -0700 |
---|---|---|
committer | casper <none@none> | 2007-05-25 05:43:42 -0700 |
commit | f48205be61a214698b763ff550ab9e657525104c (patch) | |
tree | bc63168b8468284765bb770eb48473b7a0bf980e /usr/src/uts/common/syscall | |
parent | 7387092aa96cd872b317dfab3fee34a96c681f3e (diff) | |
download | illumos-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.c | 11 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/gid.c | 72 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/groups.c | 26 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/ppriv.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/sidsys.c | 299 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/sysconfig.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/uid.c | 71 |
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)); } |