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 | |
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')
50 files changed, 1428 insertions, 187 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index fd75841cbf..f5593ec93a 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -251,6 +251,8 @@ GENUNIX_OBJS += \ rw.o \ rwstlock.o \ sad_conf.o \ + sid.o \ + sidsys.o \ sched.o \ schedctl.o \ seg_dev.o \ diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c index bc1de2eefd..3105ac16a6 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -865,8 +865,8 @@ lxpr_read_pid_status(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" - "Uid:\t%d\t%d\t%d\t%d\n" - "Gid:\t%d\t%d\t%d\t%d\n" + "Uid:\t%u\t%u\t%u\t%u\n" + "Gid:\t%u\t%u\t%u\t%u\n" "FDSize:\t%d\n" "Groups:\t", up->u_comm, @@ -883,7 +883,7 @@ lxpr_read_pid_status(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) groups = crgetgroups(cr); for (i = 0; i < ngroups; i++) { lxpr_uiobuf_printf(uiobuf, - "%d ", + "%u ", groups[i]); } crfree(cr); @@ -987,12 +987,12 @@ lxpr_read_pid_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf) * Set Linux defaults if we're the zone's init process */ if (pid == curproc->p_zone->zone_proc_initpid) { - pid = 1; /* PID for init */ - ppid = 0; /* parent PID for init is 0 */ - pgpid = 0; /* process group for init is 0 */ - psgid = -1; /* credential GID for init is -1 */ - spid = 0; /* session id for init is 0 */ - psdev = 0; /* session device for init is 0 */ + pid = 1; /* PID for init */ + ppid = 0; /* parent PID for init is 0 */ + pgpid = 0; /* process group for init is 0 */ + psgid = (gid_t)-1; /* credential GID for init is -1 */ + spid = 0; /* session id for init is 0 */ + psdev = 0; /* session device for init is 0 */ } else { /* * Make sure not to reference parent PIDs that reside outside diff --git a/usr/src/uts/common/c2/audit.h b/usr/src/uts/common/c2/audit.h index 29ef7efc38..765374d848 100644 --- a/usr/src/uts/common/c2/audit.h +++ b/usr/src/uts/common/c2/audit.h @@ -62,7 +62,7 @@ extern "C" { * The user id -2 is never audited - in fact, a setauid(AU_NOAUDITID) * will turn off auditing. */ -#define AU_NOAUDITID -2 +#define AU_NOAUDITID ((au_id_t)-2) /* * success/failure bits for asynchronous events diff --git a/usr/src/uts/common/c2/audit_event.c b/usr/src/uts/common/c2/audit_event.c index 8dd5e62bfa..bdf5e1cb1c 100644 --- a/usr/src/uts/common/c2/audit_event.c +++ b/usr/src/uts/common/c2/audit_event.c @@ -351,7 +351,7 @@ aui_null, AUE_NULL, aus_null, /* 73 (loadable) was notused */ auf_null, 0, aui_null, AUE_NULL, aus_null, /* 74 (loadable) was notused */ auf_null, 0, -aui_null, AUE_NULL, aus_null, /* 75 issetugid */ +aui_null, AUE_NULL, aus_null, /* 75 sidsys */ /* was sigret (SunOS) */ auf_null, 0, aui_fsat, AUE_FSAT, aus_fsat, /* 76 fsat */ diff --git a/usr/src/uts/common/fs/cachefs/cachefs_log.c b/usr/src/uts/common/fs/cachefs/cachefs_log.c index 0fe25933d0..8d0103cd39 100644 --- a/usr/src/uts/common/fs/cachefs/cachefs_log.c +++ b/usr/src/uts/common/fs/cachefs/cachefs_log.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -866,7 +865,7 @@ cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_longlong_t(xdrs, &rec->offset)) || (! xdr_u_int(xdrs, &rec->len))) return (FALSE); @@ -914,7 +913,7 @@ cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || (! xdr_int(xdrs, &rec->eof))) return (FALSE); @@ -961,7 +960,7 @@ cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_int(xdrs, &rec->length))) return (FALSE); @@ -1006,7 +1005,7 @@ cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); @@ -1050,7 +1049,7 @@ cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); @@ -1095,7 +1094,7 @@ cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_longlong_t(xdrs, &rec->size))) return (FALSE); @@ -1142,7 +1141,7 @@ cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) || (! xdr_u_int(xdrs, &rec->len))) return (FALSE); @@ -1188,7 +1187,7 @@ cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); @@ -1234,7 +1233,7 @@ cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); @@ -1279,7 +1278,7 @@ cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) || (! xdr_int(xdrs, &rec->removed)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); @@ -1325,7 +1324,7 @@ cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_int(xdrs, &rec->size))) return (FALSE); @@ -1550,7 +1549,7 @@ cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid)) || + (! xdr_u_int(xdrs, &rec->uid)) || (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) || (! xdr_u_int(xdrs, &rec->len))) return (FALSE); @@ -1596,7 +1595,7 @@ cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec) (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) || (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) || (! xdr_ino64(xdrs, &rec->fileno)) || - (! xdr_int(xdrs, &rec->uid))) + (! xdr_u_int(xdrs, &rec->uid))) return (FALSE); return (TRUE); diff --git a/usr/src/uts/common/fs/dev/sdev_ptsops.c b/usr/src/uts/common/fs/dev/sdev_ptsops.c index 64493f6402..4ee3a52857 100644 --- a/usr/src/uts/common/fs/dev/sdev_ptsops.c +++ b/usr/src/uts/common/fs/dev/sdev_ptsops.c @@ -146,8 +146,6 @@ devpts_validate(struct sdev_node *dv) ASSERT(dv->sdev_attr); if (dv->sdev_attr->va_uid != uid || dv->sdev_attr->va_gid != gid) { - ASSERT(uid >= 0); - ASSERT(gid >= 0); dv->sdev_attr->va_uid = uid; dv->sdev_attr->va_gid = gid; gethrestime(&now); @@ -208,8 +206,6 @@ devpts_create_rvp(struct sdev_node *ddv, char *nm, */ *vap = devpts_vattr; vap->va_rdev = makedevice(maj, min); - ASSERT(uid >= 0); - ASSERT(gid >= 0); vap->va_uid = uid; vap->va_gid = gid; gethrestime(&now); diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c index e52ecd4182..0fe058556d 100644 --- a/usr/src/uts/common/fs/fs_subr.c +++ b/usr/src/uts/common/fs/fs_subr.c @@ -23,7 +23,7 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -543,12 +543,12 @@ cred_t *cr; aclentp->a_type = OTHER_OBJ; /* Other */ aclentp->a_perm = vattr.va_mode & 0007; - aclentp->a_id = -1; /* Really undefined */ + aclentp->a_id = (gid_t)-1; /* Really undefined */ aclentp++; aclentp->a_type = CLASS_OBJ; /* Class */ aclentp->a_perm = (ushort_t)(0007); - aclentp->a_id = -1; /* Really undefined */ + aclentp->a_id = (gid_t)-1; /* Really undefined */ } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) { vsecattr->vsa_aclcnt = 6; vsecattr->vsa_aclentp = kmem_zalloc(6 * sizeof (ace_t), diff --git a/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c b/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c index eb70bb78e9..5044c86b22 100644 --- a/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c +++ b/usr/src/uts/common/fs/nfs/nfs_acl_xdr.c @@ -56,7 +56,7 @@ bool_t xdr_uid(XDR *xdrs, uid32_t *objp) { - if (!xdr_int(xdrs, objp)) + if (!xdr_u_int(xdrs, objp)) return (FALSE); return (TRUE); } diff --git a/usr/src/uts/common/fs/proc/prcontrol.c b/usr/src/uts/common/fs/proc/prcontrol.c index 19e5f4b604..9bbf929b5f 100644 --- a/usr/src/uts/common/fs/proc/prcontrol.c +++ b/usr/src/uts/common/fs/proc/prcontrol.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2137,12 +2137,12 @@ pr_scred(proc_t *p, prcred_t *prcred, cred_t *cr, boolean_t dogrps) uid_t oldruid; int error; - if ((uint_t)prcred->pr_euid > MAXUID || - (uint_t)prcred->pr_ruid > MAXUID || - (uint_t)prcred->pr_suid > MAXUID || - (uint_t)prcred->pr_egid > MAXUID || - (uint_t)prcred->pr_rgid > MAXUID || - (uint_t)prcred->pr_sgid > MAXUID) + if (!VALID_UID(prcred->pr_euid) || + !VALID_UID(prcred->pr_ruid) || + !VALID_UID(prcred->pr_suid) || + !VALID_GID(prcred->pr_egid) || + !VALID_GID(prcred->pr_rgid) || + !VALID_GID(prcred->pr_sgid)) return (EINVAL); if (dogrps) { @@ -2153,7 +2153,7 @@ pr_scred(proc_t *p, prcred_t *prcred, cred_t *cr, boolean_t dogrps) return (EINVAL); for (i = 0; i < ngrp; i++) { - if ((uint_t)prcred->pr_groups[i] > MAXUID) + if (!VALID_GID(prcred->pr_groups[i])) return (EINVAL); } } diff --git a/usr/src/uts/common/fs/proc/prvfsops.c b/usr/src/uts/common/fs/proc/prvfsops.c index 35d829facd..1ff5993983 100644 --- a/usr/src/uts/common/fs/proc/prvfsops.c +++ b/usr/src/uts/common/fs/proc/prvfsops.c @@ -72,7 +72,7 @@ static vfsdef_t vfw = { VFSDEF_VERSION, "proc", prinit, - VSW_HASPROTO|VSW_STATS, + VSW_HASPROTO|VSW_STATS|VSW_XID, &proc_mntopts }; diff --git a/usr/src/uts/common/fs/ufs/quota.c b/usr/src/uts/common/fs/ufs/quota.c index 0dbaecc0b8..674635fda6 100644 --- a/usr/src/uts/common/fs/ufs/quota.c +++ b/usr/src/uts/common/fs/ufs/quota.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -259,15 +258,7 @@ loop: * Large Files: i_size need to be accessed atomically now. */ rw_enter(&qip->i_contents, RW_READER); - if (uid >= 0 && dqoff(uid) >= 0 && dqoff(uid) < qip->i_size) { - /* - * This could almost be a static comparison with UID_MAX, - * but we keep the ASSERT here to document the restriction - * inherent in this simplistic database. - */ - ASSERT((u_offset_t)uid < - UFS_MAXOFFSET_T / sizeof (struct dqblk)); - + if (uid <= MAXUID && dqoff(uid) >= 0 && dqoff(uid) < qip->i_size) { /* * Read quota info off disk. */ diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index eeba3e23e2..c00879da35 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -1570,6 +1570,9 @@ domount(char *fsname, struct mounta *uap, vnode_t *vp, struct cred *credp, vfsp->vfs_fstypevsp = get_fstype_vopstats(vfsp, vswp); } + if (vswp->vsw_flag & VSW_XID) + vfsp->vfs_flag |= VFS_XID; + vfs_unlock(vfsp); } mount_completed(); diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 5b796d6f8a..7129cfead9 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -150,6 +150,16 @@ int vopstats_enabled = 1; } /* + * If the filesystem does not support XIDs map credential + * If the vfsp is NULL, perhaps we should also map? + */ +#define VOPXID_MAP_CR(vp, cr) { \ + vfs_t *vfsp = (vp)->v_vfsp; \ + if (vfsp != NULL && (vfsp->vfs_flag & VFS_XID) == 0) \ + cr = crgetmapped(cr); \ + } + +/* * Convert stat(2) formats to vnode types and vice versa. (Knows about * numerical order of S_IFMT and vnode types.) */ @@ -670,6 +680,8 @@ vn_rdwr( if (len < 0) return (EIO); + VOPXID_MAP_CR(vp, cr); + iov.iov_base = base; iov.iov_len = len; uio.uio_iov = &iov; @@ -2718,6 +2730,8 @@ fop_open( atomic_add_32(&((*vpp)->v_wrcnt), 1); } + VOPXID_MAP_CR(vp, cr); + ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr); if (ret) { @@ -2766,6 +2780,8 @@ fop_close( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr); VOPSTATS_UPDATE(vp, close); /* @@ -2796,6 +2812,8 @@ fop_read( int err; ssize_t resid_start = uiop->uio_resid; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct); VOPSTATS_UPDATE_IO(vp, read, read_bytes, (resid_start - uiop->uio_resid)); @@ -2813,6 +2831,8 @@ fop_write( int err; ssize_t resid_start = uiop->uio_resid; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct); VOPSTATS_UPDATE_IO(vp, write, write_bytes, (resid_start - uiop->uio_resid)); @@ -2830,6 +2850,8 @@ fop_ioctl( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp); VOPSTATS_UPDATE(vp, ioctl); return (err); @@ -2844,6 +2866,8 @@ fop_setfl( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr); VOPSTATS_UPDATE(vp, setfl); return (err); @@ -2858,6 +2882,8 @@ fop_getattr( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr); VOPSTATS_UPDATE(vp, getattr); return (err); @@ -2873,6 +2899,8 @@ fop_setattr( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct); VOPSTATS_UPDATE(vp, setattr); return (err); @@ -2887,6 +2915,8 @@ fop_access( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr); VOPSTATS_UPDATE(vp, access); return (err); @@ -2904,6 +2934,8 @@ fop_lookup( { int ret; + VOPXID_MAP_CR(dvp, cr); + ret = (*(dvp)->v_op->vop_lookup)(dvp, nm, vpp, pnp, flags, rdir, cr); if (ret == 0 && *vpp) { VOPSTATS_UPDATE(*vpp, lookup); @@ -2928,6 +2960,8 @@ fop_create( { int ret; + VOPXID_MAP_CR(dvp, cr); + ret = (*(dvp)->v_op->vop_create) (dvp, name, vap, excl, mode, vpp, cr, flag); if (ret == 0 && *vpp) { @@ -2948,6 +2982,8 @@ fop_remove( { int err; + VOPXID_MAP_CR(dvp, cr); + err = (*(dvp)->v_op->vop_remove)(dvp, nm, cr); VOPSTATS_UPDATE(dvp, remove); return (err); @@ -2962,6 +2998,8 @@ fop_link( { int err; + VOPXID_MAP_CR(tdvp, cr); + err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr); VOPSTATS_UPDATE(tdvp, link); return (err); @@ -2977,6 +3015,8 @@ fop_rename( { int err; + VOPXID_MAP_CR(tdvp, cr); + err = (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr); VOPSTATS_UPDATE(sdvp, rename); return (err); @@ -2992,6 +3032,8 @@ fop_mkdir( { int ret; + VOPXID_MAP_CR(dvp, cr); + ret = (*(dvp)->v_op->vop_mkdir)(dvp, dirname, vap, vpp, cr); if (ret == 0 && *vpp) { VOPSTATS_UPDATE(*vpp, mkdir); @@ -3013,6 +3055,8 @@ fop_rmdir( { int err; + VOPXID_MAP_CR(dvp, cr); + err = (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr); VOPSTATS_UPDATE(dvp, rmdir); return (err); @@ -3028,6 +3072,8 @@ fop_readdir( int err; ssize_t resid_start = uiop->uio_resid; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp); VOPSTATS_UPDATE_IO(vp, readdir, readdir_bytes, (resid_start - uiop->uio_resid)); @@ -3044,6 +3090,8 @@ fop_symlink( { int err; + VOPXID_MAP_CR(dvp, cr); + err = (*(dvp)->v_op->vop_symlink) (dvp, linkname, vap, target, cr); VOPSTATS_UPDATE(dvp, symlink); return (err); @@ -3057,6 +3105,8 @@ fop_readlink( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_readlink)(vp, uiop, cr); VOPSTATS_UPDATE(vp, readlink); return (err); @@ -3070,6 +3120,8 @@ fop_fsync( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_fsync)(vp, syncflag, cr); VOPSTATS_UPDATE(vp, fsync); return (err); @@ -3082,6 +3134,9 @@ fop_inactive( { /* Need to update stats before vop call since we may lose the vnode */ VOPSTATS_UPDATE(vp, inactive); + + VOPXID_MAP_CR(vp, cr); + (*(vp)->v_op->vop_inactive)(vp, cr); } @@ -3157,6 +3212,8 @@ fop_frlock( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_frlock) (vp, cmd, bfp, flag, offset, flk_cbp, cr); VOPSTATS_UPDATE(vp, frlock); @@ -3175,6 +3232,8 @@ fop_space( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct); VOPSTATS_UPDATE(vp, space); return (err); @@ -3207,6 +3266,8 @@ fop_getpage( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_getpage) (vp, off, len, protp, plarr, plsz, seg, addr, rw, cr); VOPSTATS_UPDATE(vp, getpage); @@ -3223,6 +3284,8 @@ fop_putpage( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr); VOPSTATS_UPDATE(vp, putpage); return (err); @@ -3242,6 +3305,8 @@ fop_map( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_map) (vp, off, as, addrp, len, prot, maxprot, flags, cr); VOPSTATS_UPDATE(vp, map); @@ -3263,6 +3328,8 @@ fop_addmap( int error; u_longlong_t delta; + VOPXID_MAP_CR(vp, cr); + error = (*(vp)->v_op->vop_addmap) (vp, off, as, addr, len, prot, maxprot, flags, cr); @@ -3309,6 +3376,9 @@ fop_delmap( { int error; u_longlong_t delta; + + VOPXID_MAP_CR(vp, cr); + error = (*(vp)->v_op->vop_delmap) (vp, off, as, addr, len, prot, maxprot, flags, cr); @@ -3385,6 +3455,8 @@ fop_pathconf( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr); VOPSTATS_UPDATE(vp, pathconf); return (err); @@ -3401,6 +3473,8 @@ fop_pageio( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr); VOPSTATS_UPDATE(vp, pageio); return (err); @@ -3428,6 +3502,9 @@ fop_dispose( { /* Must do stats first since it's possible to lose the vnode */ VOPSTATS_UPDATE(vp, dispose); + + VOPXID_MAP_CR(vp, cr); + (*(vp)->v_op->vop_dispose)(vp, pp, flag, dn, cr); } @@ -3440,6 +3517,8 @@ fop_setsecattr( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr); VOPSTATS_UPDATE(vp, setsecattr); return (err); @@ -3454,6 +3533,8 @@ fop_getsecattr( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr); VOPSTATS_UPDATE(vp, getsecattr); return (err); @@ -3469,6 +3550,8 @@ fop_shrlock( { int err; + VOPXID_MAP_CR(vp, cr); + err = (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr); VOPSTATS_UPDATE(vp, shrlock); return (err); diff --git a/usr/src/uts/common/fs/zfs/zfs_acl.c b/usr/src/uts/common/fs/zfs/zfs_acl.c index 89eec4e0aa..5eeed0bb88 100644 --- a/usr/src/uts/common/fs/zfs/zfs_acl.c +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c @@ -343,16 +343,16 @@ zfs_acl_valid(znode_t *zp, ace_t *uace, int aclcnt, int *inherit) switch (acep->a_flags & ACE_TYPE_FLAGS) { case ACE_OWNER: - acep->a_who = -1; + acep->a_who = (uid_t)-1; break; case (ACE_IDENTIFIER_GROUP | ACE_GROUP): case ACE_IDENTIFIER_GROUP: if (acep->a_flags & ACE_GROUP) { - acep->a_who = -1; + acep->a_who = (uid_t)-1; } break; case ACE_EVERYONE: - acep->a_who = -1; + acep->a_who = (uid_t)-1; break; } diff --git a/usr/src/uts/common/io/ptm.c b/usr/src/uts/common/io/ptm.c index aaa4886069..8909fb516a 100644 --- a/usr/src/uts/common/io/ptm.c +++ b/usr/src/uts/common/io/ptm.c @@ -572,7 +572,8 @@ ptmwput(queue_t *qp, mblk_t *mp) ptop = (pt_own_t *)mp->b_cont->b_rptr; - if (ptop->pto_ruid < 0 || ptop->pto_rgid < 0) { + if (!VALID_UID(ptop->pto_ruid) || + !VALID_GID(ptop->pto_rgid)) { miocnak(qp, mp, 0, EINVAL); break; } diff --git a/usr/src/uts/common/io/ptms_conf.c b/usr/src/uts/common/io/ptms_conf.c index b1b48f748b..841826860f 100644 --- a/usr/src/uts/common/io/ptms_conf.c +++ b/usr/src/uts/common/io/ptms_conf.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. */ @@ -463,8 +463,8 @@ ptms_minor_valid(minor_t dminor, uid_t *ruid, gid_t *rgid) ASSERT(ruid); ASSERT(rgid); - *ruid = -1; - *rgid = -1; + *ruid = (uid_t)-1; + *rgid = (gid_t)-1; /* * /dev/pts/0 is not used, but some applications may check it, so create diff --git a/usr/src/uts/common/ipp/flowacct/flowacct.c b/usr/src/uts/common/ipp/flowacct/flowacct.c index c319a746d9..dfffdb05e9 100644 --- a/usr/src/uts/common/ipp/flowacct/flowacct.c +++ b/usr/src/uts/common/ipp/flowacct/flowacct.c @@ -219,7 +219,7 @@ flowacct_find_ids(mblk_t *mp, header_t *header) header->uid = crgetuid(cr); header->projid = crgetprojid(cr); } else { - header->uid = -1; + header->uid = (uid_t)-1; header->projid = -1; } } diff --git a/usr/src/uts/common/ipp/ipgpc/classifier.c b/usr/src/uts/common/ipp/ipgpc/classifier.c index a0d011968c..4f329c9d1b 100644 --- a/usr/src/uts/common/ipp/ipgpc/classifier.c +++ b/usr/src/uts/common/ipp/ipgpc/classifier.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. */ @@ -614,7 +614,7 @@ find_ids(ipgpc_packet_t *packet, mblk_t *mp) packet->uid = crgetuid(cr); packet->projid = crgetprojid(cr); } else { - packet->uid = -1; + packet->uid = (uid_t)-1; packet->projid = -1; } } diff --git a/usr/src/uts/common/ipp/ipgpc/filters.c b/usr/src/uts/common/ipp/ipgpc/filters.c index 7103817bcd..2add8eba6a 100644 --- a/usr/src/uts/common/ipp/ipgpc/filters.c +++ b/usr/src/uts/common/ipp/ipgpc/filters.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 2002-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -632,8 +631,8 @@ ipgpc_parse_filter(ipgpc_filter_t *filter, nvlist_t *nvlp) } /* parse uid */ - if (nvlist_lookup_int32(nvlp, IPGPC_UID, &filter->uid) != 0) { - filter->uid = IPGPC_WILDCARD; + if (nvlist_lookup_uint32(nvlp, IPGPC_UID, &filter->uid) != 0) { + filter->uid = (uid_t)IPGPC_WILDCARD; } /* parse projid */ @@ -2337,7 +2336,7 @@ build_filter_nvlist(nvlist_t **nvlpp, ipgpc_filter_t *in_filter, /* add uid */ if (in_filter->uid != IPGPC_WILDCARD) { - if ((rc = nvlist_add_int32(nvlp, IPGPC_UID, in_filter->uid)) + if ((rc = nvlist_add_uint32(nvlp, IPGPC_UID, in_filter->uid)) != 0) { return (rc); } diff --git a/usr/src/uts/common/os/core.c b/usr/src/uts/common/os/core.c index e833022e2b..8faf69db54 100644 --- a/usr/src/uts/common/os/core.c +++ b/usr/src/uts/common/os/core.c @@ -490,10 +490,10 @@ expand_string(const char *pat, char *fp, int size, cred_t *cr) (void) sprintf((s = buf), "%d", p->p_pid); break; case 'u': /* effective uid */ - (void) sprintf((s = buf), "%d", crgetuid(p->p_cred)); + (void) sprintf((s = buf), "%u", crgetuid(p->p_cred)); break; case 'g': /* effective gid */ - (void) sprintf((s = buf), "%d", crgetgid(p->p_cred)); + (void) sprintf((s = buf), "%u", crgetgid(p->p_cred)); break; case 'f': /* exec'd filename */ s = PTOU(p)->u_comm; diff --git a/usr/src/uts/common/os/cred.c b/usr/src/uts/common/os/cred.c index e6452fe4f2..4ebda51792 100644 --- a/usr/src/uts/common/os/cred.c +++ b/usr/src/uts/common/os/cred.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. */ @@ -55,9 +55,18 @@ #include <sys/ucred.h> #include <sys/prsystm.h> #include <sys/modctl.h> +#include <sys/avl.h> #include <c2/audit.h> #include <sys/zone.h> #include <sys/tsol/label.h> +#include <sys/sid.h> + +typedef struct ephidmap_data { + uid_t min_uid, last_uid; + gid_t min_gid, last_gid; + cred_t *nobody; + kmutex_t eph_lock; +} ephidmap_data_t; static struct kmem_cache *cred_cache; static size_t crsize = 0; @@ -76,6 +85,16 @@ static int get_c2audit_load(void); #define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1) /* + * XXX: should be per-zone. + * Start with an invalid value for atomic increments. + */ +static ephidmap_data_t ephemeral_data = { + MAXUID, MAXUID, MAXUID, MAXUID +}; + +static boolean_t hasephids = B_FALSE; + +/* * Initialize credentials data structures. */ @@ -111,12 +130,13 @@ cred_init(void) dummycr = cralloc(); bzero(dummycr, crsize); dummycr->cr_ref = 1; - dummycr->cr_uid = -1; - dummycr->cr_gid = -1; - dummycr->cr_ruid = -1; - dummycr->cr_rgid = -1; - dummycr->cr_suid = -1; - dummycr->cr_sgid = -1; + dummycr->cr_uid = (uid_t)-1; + dummycr->cr_gid = (gid_t)-1; + dummycr->cr_ruid = (uid_t)-1; + dummycr->cr_rgid = (gid_t)-1; + dummycr->cr_suid = (uid_t)-1; + dummycr->cr_sgid = (gid_t)-1; + /* * kcred is used by anything that needs all privileges; it's @@ -152,6 +172,13 @@ cred_init(void) ttoproc(curthread)->p_cred = kcred; curthread->t_cred = kcred; + /* + * nobody is used to map SID containing CRs. + */ + ephemeral_data.nobody = crdup(kcred); + (void) crsetugid(ephemeral_data.nobody, UID_NOBODY, GID_NOBODY); + CR_FLAGS(kcred) = 0; + ucredsize = UCRED_SIZE; } @@ -165,6 +192,19 @@ cralloc(void) cr->cr_ref = 1; /* So we can crfree() */ cr->cr_zone = NULL; cr->cr_label = NULL; + cr->cr_ksid = NULL; + return (cr); +} + +/* + * As cralloc but prepared for ksid change (if appropriate). + */ +cred_t * +cralloc_ksid(void) +{ + cred_t *cr = cralloc(); + if (hasephids) + cr->cr_ksid = kcrsid_alloc(); return (cr); } @@ -248,6 +288,8 @@ crfree(cred_t *cr) label_rele(cr->cr_label); if (cr->cr_zone) zone_cred_rele(cr->cr_zone); + if (cr->cr_ksid) + kcrsid_rele(cr->cr_ksid); kmem_cache_free(cred_cache, cr); } } @@ -268,6 +310,8 @@ crcopy(cred_t *cr) zone_cred_hold(newcr->cr_zone); if (newcr->cr_label) label_hold(cr->cr_label); + if (newcr->cr_ksid) + kcrsid_hold(cr->cr_ksid); crfree(cr); newcr->cr_ref = 2; /* caller gets two references */ return (newcr); @@ -283,11 +327,18 @@ crcopy(cred_t *cr) void crcopy_to(cred_t *oldcr, cred_t *newcr) { + credsid_t *nkcr = newcr->cr_ksid; + bcopy(oldcr, newcr, crsize); if (newcr->cr_zone) zone_cred_hold(newcr->cr_zone); if (newcr->cr_label) label_hold(newcr->cr_label); + if (nkcr) { + newcr->cr_ksid = nkcr; + kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid); + } else if (newcr->cr_ksid) + kcrsid_hold(newcr->cr_ksid); crfree(oldcr); newcr->cr_ref = 2; /* caller gets two references */ } @@ -307,6 +358,8 @@ crdup(cred_t *cr) zone_cred_hold(newcr->cr_zone); if (newcr->cr_label) label_hold(newcr->cr_label); + if (newcr->cr_ksid) + kcrsid_hold(newcr->cr_ksid); newcr->cr_ref = 1; return (newcr); } @@ -320,11 +373,18 @@ crdup(cred_t *cr) void crdup_to(cred_t *oldcr, cred_t *newcr) { + credsid_t *nkcr = newcr->cr_ksid; + bcopy(oldcr, newcr, crsize); if (newcr->cr_zone) zone_cred_hold(newcr->cr_zone); if (newcr->cr_label) label_hold(newcr->cr_label); + if (nkcr) { + newcr->cr_ksid = nkcr; + kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid); + } else if (newcr->cr_ksid) + kcrsid_hold(newcr->cr_ksid); newcr->cr_ref = 1; } @@ -559,14 +619,15 @@ crisremote(const cred_t *cr) return (REMOTE_PEER_CRED(cr)); } -#define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID) +#define BADUID(x) ((x) != -1 && !VALID_UID(x)) +#define BADGID(x) ((x) != -1 && !VALID_GID(x)) int crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) { ASSERT(cr->cr_ref <= 2); - if (BADID(r) || BADID(e) || BADID(s)) + if (BADUID(r) || BADUID(e) || BADUID(s)) return (-1); if (r != -1) @@ -584,7 +645,7 @@ crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) { ASSERT(cr->cr_ref <= 2); - if (BADID(r) || BADID(e) || BADID(s)) + if (BADGID(r) || BADGID(e) || BADGID(s)) return (-1); if (r != -1) @@ -602,7 +663,7 @@ crsetugid(cred_t *cr, uid_t uid, gid_t gid) { ASSERT(cr->cr_ref <= 2); - if (uid < 0 || uid > MAXUID || gid < 0 || gid > MAXUID) + if (!VALID_UID(uid) || !VALID_GID(gid)) return (-1); cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; @@ -904,3 +965,120 @@ zone_kcred(void) else return (kcred); } + +boolean_t +valid_ephemeral_uid(uid_t id) +{ + membar_consumer(); + return (id > ephemeral_data.min_uid && id <= ephemeral_data.last_uid); +} + +boolean_t +valid_ephemeral_gid(gid_t id) +{ + membar_consumer(); + return (id > ephemeral_data.min_gid && id <= ephemeral_data.last_gid); +} + +int +eph_uid_alloc(int flags, uid_t *start, int count) +{ + mutex_enter(&ephemeral_data.eph_lock); + + /* Test for unsigned integer wrap around */ + if (ephemeral_data.last_uid + count < ephemeral_data.last_uid) { + mutex_exit(&ephemeral_data.eph_lock); + return (-1); + } + + /* first call or idmap crashed and state corrupted */ + if (flags != 0) + ephemeral_data.min_uid = ephemeral_data.last_uid; + + hasephids = B_TRUE; + *start = ephemeral_data.last_uid + 1; + atomic_add_32(&ephemeral_data.last_uid, count); + mutex_exit(&ephemeral_data.eph_lock); + return (0); +} + +int +eph_gid_alloc(int flags, gid_t *start, int count) +{ + mutex_enter(&ephemeral_data.eph_lock); + + /* Test for unsigned integer wrap around */ + if (ephemeral_data.last_gid + count < ephemeral_data.last_gid) { + mutex_exit(&ephemeral_data.eph_lock); + return (-1); + } + + /* first call or idmap crashed and state corrupted */ + if (flags != 0) + ephemeral_data.min_gid = ephemeral_data.last_gid; + + hasephids = B_TRUE; + *start = ephemeral_data.last_gid + 1; + atomic_add_32(&ephemeral_data.last_gid, count); + mutex_exit(&ephemeral_data.eph_lock); + return (0); +} + +/* + * If the credential contains any ephemeral IDs, map the credential + * to nobody. + */ +cred_t * +crgetmapped(const cred_t *cr) +{ + if (cr->cr_ksid != NULL) { + int i; + + for (i = 0; i < KSID_COUNT; i++) + if (cr->cr_ksid->kr_sidx[i].ks_id > MAXUID) + return (ephemeral_data.nobody); + if (cr->cr_ksid->kr_sidlist != NULL && + cr->cr_ksid->kr_sidlist->ksl_neid > 0) { + return (ephemeral_data.nobody); + } + } + + return ((cred_t *)cr); +} + +/* index should be in range for a ksidindex_t */ +void +crsetsid(cred_t *cr, ksid_t *ksp, int index) +{ + ASSERT(cr->cr_ref <= 2); + ASSERT(index >= 0 && index < KSID_COUNT); + if (cr->cr_ksid == NULL && ksp == NULL) + return; + cr->cr_ksid = kcrsid_setsid(cr->cr_ksid, ksp, index); +} + +void +crsetsidlist(cred_t *cr, ksidlist_t *ksl) +{ + ASSERT(cr->cr_ref <= 2); + if (cr->cr_ksid == NULL && ksl == NULL) + return; + cr->cr_ksid = kcrsid_setsidlist(cr->cr_ksid, ksl); +} + +ksid_t * +crgetsid(const cred_t *cr, int i) +{ + ASSERT(i >= 0 && i < KSID_COUNT); + if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidx[i].ks_domain) + return ((ksid_t *)&cr->cr_ksid->kr_sidx[i]); + return (NULL); +} + +ksidlist_t * +crgetsidlist(const cred_t *cr) +{ + if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidlist != NULL) + return ((ksidlist_t *)&cr->cr_ksid->kr_sidlist); + return (NULL); +} diff --git a/usr/src/uts/common/os/ipc.c b/usr/src/uts/common/os/ipc.c index 0094652f15..367089e686 100644 --- a/usr/src/uts/common/os/ipc.c +++ b/usr/src/uts/common/os/ipc.c @@ -529,7 +529,7 @@ ipcperm_set(ipc_service_t *service, struct cred *cr, if (secpolicy_ipc_owner(cr, kperm) != 0) return (EPERM); - if ((uid < 0) || (uid > MAXUID) || (gid < 0) || (gid > MAXUID)) + if (!VALID_UID(uid) || !VALID_GID(gid)) return (EINVAL); kperm->ipc_uid = uid; @@ -568,8 +568,7 @@ ipcperm_set64(ipc_service_t *service, struct cred *cr, if (secpolicy_ipc_owner(cr, kperm) != 0) return (EPERM); - if ((perm64->ipcx_uid < 0) || (perm64->ipcx_uid > MAXUID) || - (perm64->ipcx_gid < 0) || (perm64->ipcx_gid > MAXUID)) + if (!VALID_UID(perm64->ipcx_uid) || !VALID_GID(perm64->ipcx_gid)) return (EINVAL); kperm->ipc_uid = perm64->ipcx_uid; diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c index 4acbaae74f..31108c215b 100644 --- a/usr/src/uts/common/os/modctl.c +++ b/usr/src/uts/common/os/modctl.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. */ @@ -1537,12 +1537,12 @@ process_minorperm(int cmd, nvlist_t *nvl) nvp = nvlist_next_nvpair(nvl, nvp); ASSERT(strcmp(nvpair_name(nvp), "uid") == 0); if (mp) - (void) nvpair_value_int32(nvp, &mp->mp_uid); + (void) nvpair_value_uint32(nvp, &mp->mp_uid); /* gid */ nvp = nvlist_next_nvpair(nvl, nvp); ASSERT(strcmp(nvpair_name(nvp), "gid") == 0); if (mp) { - (void) nvpair_value_int32(nvp, &mp->mp_gid); + (void) nvpair_value_uint32(nvp, &mp->mp_gid); if (cmd == MODREMMINORPERM) { rem_minorperm(major, name, mp, is_clone); diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c index 5800e1e96f..7025453518 100644 --- a/usr/src/uts/common/os/policy.c +++ b/usr/src/uts/common/os/policy.c @@ -1885,3 +1885,15 @@ secpolicy_zfs(const cred_t *cr) { return (PRIV_POLICY(cr, PRIV_SYS_MOUNT, B_FALSE, EPERM, NULL)); } + +/* + * secpolicy_idmap + * + * Determine if the calling process has permissions to register an SID + * mapping daemon and allocate ephemeral IDs. + */ +int +secpolicy_idmap(const cred_t *cr) +{ + return (PRIV_POLICY(cr, PRIV_ALL, B_FALSE, EPERM, NULL)); +} diff --git a/usr/src/uts/common/os/sid.c b/usr/src/uts/common/os/sid.c new file mode 100644 index 0000000000..d5bef7def5 --- /dev/null +++ b/usr/src/uts/common/os/sid.c @@ -0,0 +1,395 @@ +/* + * 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 manipulation (stubs). + */ + +#include <sys/atomic.h> +#include <sys/avl.h> +#include <sys/cmn_err.h> +#include <sys/kmem.h> +#include <sys/mutex.h> +#include <sys/sid.h> +#include <sys/sysmacros.h> +#include <sys/systm.h> + +static kmutex_t sid_lock; +static avl_tree_t sid_tree; +static boolean_t sid_inited = B_FALSE; + +static ksiddomain_t +*ksid_enterdomain(const char *dom) +{ + size_t len = strlen(dom) + 1; + ksiddomain_t *res; + + ASSERT(MUTEX_HELD(&sid_lock)); + res = kmem_alloc(sizeof (ksiddomain_t), KM_SLEEP); + res->kd_len = (uint_t)len; + res->kd_name = kmem_alloc(len, KM_SLEEP); + bcopy(dom, res->kd_name, len); + + res->kd_ref = 1; + + avl_add(&sid_tree, res); + + return (res); +} + +void +ksid_hold(ksid_t *ks) +{ + if (ks->ks_domain != NULL) + ksiddomain_hold(ks->ks_domain); +} + +void +ksid_rele(ksid_t *ks) +{ + if (ks->ks_domain != NULL) + ksiddomain_rele(ks->ks_domain); +} + +void +ksiddomain_hold(ksiddomain_t *kd) +{ + atomic_add_32(&kd->kd_ref, 1); +} + +void +ksiddomain_rele(ksiddomain_t *kd) +{ + if (atomic_add_32_nv(&kd->kd_ref, -1) == 0) { + /* + * The kd reference can only be incremented from 0 when + * the sid_lock is held; so we lock and then check need to + * check for 0 again. + */ + mutex_enter(&sid_lock); + if (kd->kd_ref == 0) { + avl_remove(&sid_tree, kd); + kmem_free(kd->kd_name, kd->kd_len); + kmem_free(kd, sizeof (*kd)); + } + mutex_exit(&sid_lock); + } +} + +void +ksidlist_hold(ksidlist_t *ksl) +{ + atomic_add_32(&ksl->ksl_ref, 1); +} + +void +ksidlist_rele(ksidlist_t *ksl) +{ + if (atomic_add_32_nv(&ksl->ksl_ref, -1) == 0) { + int i; + + for (i = 0; i < ksl->ksl_nsid; i++) + ksid_rele(&ksl->ksl_sids[i]); + + kmem_free(ksl, KSIDLIST_MEM(ksl->ksl_nsid)); + } +} + +static int +ksid_cmp(const void *a, const void *b) +{ + const ksiddomain_t *ap = a; + const ksiddomain_t *bp = b; + int res; + + res = strcmp(ap->kd_name, bp->kd_name); + if (res > 0) + return (1); + if (res != 0) + return (-1); + return (0); +} + +/* + * Lookup the named domain in the AVL tree. + * If no entry is found, add the domain to the AVL tree. + * The domain is returned held and needs to be released + * when done. + */ +ksiddomain_t +*ksid_lookupdomain(const char *dom) +{ + ksiddomain_t *res; + ksiddomain_t tmpl; + + mutex_enter(&sid_lock); + + if (!sid_inited) { + avl_create(&sid_tree, ksid_cmp, sizeof (ksiddomain_t), + offsetof(ksiddomain_t, kd_link)); + + res = ksid_enterdomain(dom); + sid_inited = B_TRUE; + mutex_exit(&sid_lock); + return (res); + } + + tmpl.kd_name = (char *)dom; + + res = avl_find(&sid_tree, &tmpl, NULL); + if (res == NULL) { + res = ksid_enterdomain(dom); + } else { + ksiddomain_hold(res); + } + + mutex_exit(&sid_lock); + return (res); +} + +const char * +ksid_getdomain(ksid_t *ks) +{ + return (ks->ks_domain->kd_name); +} + +uint_t +ksid_getrid(ksid_t *ks) +{ + return (ks->ks_rid); +} + +int +ksid_lookup(uid_t id, ksid_t *res) +{ + uid_t tmp; + + if (idmap_call_byid(id, res) == -1) + return (-1); + + tmp = idmap_call_bysid(res); + if (tmp != id) + cmn_err(CE_WARN, "The idmapper has gone bonkers"); + res->ks_id = id; + + return (0); +} + +credsid_t * +kcrsid_alloc(void) +{ + credsid_t *kcr = kmem_zalloc(sizeof (*kcr), KM_SLEEP); + kcr->kr_ref = 1; + return (kcr); +} + +/* + * Returns a credsid_t with a refcount of 1. + */ +static credsid_t * +kcrsid_dup(credsid_t *org) +{ + credsid_t *new; + ksid_index_t ki; + + if (org == NULL) + return (kcrsid_alloc()); + if (org->kr_ref == 1) + return (org); + new = kcrsid_alloc(); + + /* Copy, then update reference counts */ + *new = *org; + new->kr_ref = 1; + for (ki = 0; ki < KSID_COUNT; ki++) + ksid_hold(&new->kr_sidx[ki]); + + if (new->kr_sidlist != NULL) + ksidlist_hold(new->kr_sidlist); + + kcrsid_rele(org); + return (new); +} + +void +kcrsid_hold(credsid_t *kcr) +{ + atomic_add_32(&kcr->kr_ref, 1); +} + +void +kcrsid_rele(credsid_t *kcr) +{ + if (atomic_add_32_nv(&kcr->kr_ref, -1) == 0) { + ksid_index_t i; + + for (i = 0; i < KSID_COUNT; i++) + ksid_rele(&kcr->kr_sidx[i]); + + if (kcr->kr_sidlist != NULL) + ksidlist_rele(kcr->kr_sidlist); + + kmem_free(kcr, sizeof (*kcr)); + } +} + +/* + * Copy the SID credential into a previously allocated piece of memory. + */ +void +kcrsidcopy_to(const credsid_t *okcr, credsid_t *nkcr) +{ + int i; + + ASSERT(nkcr->kr_ref == 1); + + if (okcr == NULL) + return; + *nkcr = *okcr; + for (i = 0; i < KSID_COUNT; i++) + ksid_hold(&nkcr->kr_sidx[i]); + if (nkcr->kr_sidlist != NULL) + ksidlist_hold(nkcr->kr_sidlist); + nkcr->kr_ref = 1; +} + +static int +kcrsid_sidcount(const credsid_t *kcr) +{ + int cnt = 0; + int i; + + if (kcr == NULL) + return (0); + + for (i = 0; i < KSID_COUNT; i++) + if (kcr->kr_sidx[i].ks_domain != NULL) + cnt++; + + if (kcr->kr_sidlist != NULL) + cnt += kcr->kr_sidlist->ksl_nsid; + return (cnt); +} + +/* + * Argument needs to be a ksid_t with a properly held ks_domain reference. + */ +credsid_t * +kcrsid_setsid(credsid_t *okcr, ksid_t *ksp, ksid_index_t i) +{ + int ocnt = kcrsid_sidcount(okcr); + credsid_t *nkcr; + + /* + * Unset the particular ksid; if there are no other SIDs or if this + * is the last SID, remove the auxilary data structure. + */ + if (ksp == NULL) { + if (ocnt == 0 || + (ocnt == 1 && okcr->kr_sidx[i].ks_domain != NULL)) { + if (okcr != NULL) + kcrsid_rele(okcr); + return (NULL); + } + } + nkcr = kcrsid_dup(okcr); + ksid_rele(&nkcr->kr_sidx[i]); + if (ksp == NULL) + bzero(&nkcr->kr_sidx[i], sizeof (ksid_t)); + else + nkcr->kr_sidx[i] = *ksp; + + return (nkcr); +} + +/* + * Argument needs to be a ksidlist_t with properly held ks_domain references + * and a reference count taking the new reference into account. + */ +credsid_t * +kcrsid_setsidlist(credsid_t *okcr, ksidlist_t *ksl) +{ + int ocnt = kcrsid_sidcount(okcr); + credsid_t *nkcr; + + /* + * Unset the sidlist; if there are no further SIDs, remove the + * auxilary data structure. + */ + if (ksl == NULL) { + if (ocnt == 0 || (okcr->kr_sidlist != NULL && + ocnt == okcr->kr_sidlist->ksl_nsid)) { + if (okcr != NULL) + kcrsid_rele(okcr); + return (NULL); + } + } + nkcr = kcrsid_dup(okcr); + if (nkcr->kr_sidlist != NULL) + ksidlist_rele(nkcr->kr_sidlist); + + nkcr->kr_sidlist = ksl; + return (nkcr); +} + +ksidlist_t * +kcrsid_gidstosids(int ngrp, gid_t *grp) +{ + int i; + ksidlist_t *list; + int cnt; + + if (ngrp == 0) + return (NULL); + + cnt = 0; + list = kmem_zalloc(KSIDLIST_MEM(ngrp), KM_SLEEP); + + list->ksl_nsid = ngrp; + list->ksl_ref = 1; + + for (i = 0; i < ngrp; i++) { + if (grp[i] > MAXUID) { + list->ksl_neid++; + if (ksid_lookup(grp[i], &list->ksl_sids[i]) != 0) { + while (--i >= 0) + ksid_rele(&list->ksl_sids[i]); + cnt = 0; + break; + } + cnt++; + } else { + list->ksl_sids[i].ks_id = grp[i]; + } + } + if (cnt == 0) { + kmem_free(list, KSIDLIST_MEM(ngrp)); + return (NULL); + } + return (list); +} diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c index 233de3b873..7b767297f3 100644 --- a/usr/src/uts/common/os/sysent.c +++ b/usr/src/uts/common/os/sysent.c @@ -84,7 +84,6 @@ int gtty(); int hrtsys(); #endif /* __i386 || __amd64 */ int ioctl(); -int issetugid(); int kill(); int labelsys(); int link(); @@ -110,6 +109,7 @@ int setgid(); int setpgrp(); int setuid(); uintptr_t shmsys(); +uint64_t sidsys(); int ssig(); int sigprocmask(); int sigsuspend(); @@ -521,7 +521,7 @@ struct sysent sysent[NSYSCALL] = /* 72 */ SYSENT_LOADABLE(), /* exacct */ /* 73 */ SYSENT_CI("getpagesizes", getpagesizes, 2), /* 74 */ SYSENT_CI("rctlsys", rctlsys, 6), - /* 75 */ SYSENT_CI("issetugid", issetugid, 0), + /* 75 */ SYSENT_2CI("sidsys", sidsys, 4), /* 76 */ IF_LP64( SYSENT_CI("fsat", fsat64, 6), SYSENT_CI("fsat", fsat32, 6)), @@ -922,7 +922,7 @@ struct sysent sysent32[NSYSCALL] = /* 72 */ SYSENT_LOADABLE32(), /* exacct */ /* 73 */ SYSENT_CI("getpagesizes", getpagesizes32, 2), /* 74 */ SYSENT_CI("rctlsys", rctlsys, 6), - /* 75 */ SYSENT_CI("issetugid", issetugid, 0), + /* 75 */ SYSENT_2CI("sidsys", sidsys, 4), /* 76 */ SYSENT_CI("fsat", fsat32, 6), /* 77 */ SYSENT_CI("lwp_park", syslwp_park, 3), /* 78 */ SYSENT_CI("sendfilev", sendfilev, 5), diff --git a/usr/src/uts/common/rpc/auth.h b/usr/src/uts/common/rpc/auth.h index 3e11b15819..ab82e7799f 100644 --- a/usr/src/uts/common/rpc/auth.h +++ b/usr/src/uts/common/rpc/auth.h @@ -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. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -365,7 +364,7 @@ extern AUTH *authdes_seccreate(); */ #ifdef _KERNEL -extern enum clnt_stat netname2user(char *, uid_t *, gid_t *, int *, int *); +extern enum clnt_stat netname2user(char *, uid_t *, gid_t *, int *, gid_t *); #endif #ifdef __STDC__ extern int getnetname(char *); diff --git a/usr/src/uts/common/rpc/sec/key_call.c b/usr/src/uts/common/rpc/sec/key_call.c index 88866edbb0..382924bffe 100644 --- a/usr/src/uts/common/rpc/sec/key_call.c +++ b/usr/src/uts/common/rpc/sec/key_call.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 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -199,7 +198,7 @@ key_getnetname(netname, cr) } enum clnt_stat -netname2user(char *name, uid_t *uid, gid_t *gid, int *len, int *groups) +netname2user(char *name, uid_t *uid, gid_t *gid, int *len, gid_t *groups) { struct getcredres res; enum clnt_stat stat; diff --git a/usr/src/uts/common/rpc/sec/svcauthdes.c b/usr/src/uts/common/rpc/sec/svcauthdes.c index 4c8b23a3f4..67cd471c4b 100644 --- a/usr/src/uts/common/rpc/sec/svcauthdes.c +++ b/usr/src/uts/common/rpc/sec/svcauthdes.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 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -417,7 +416,7 @@ struct bsdcred { gid_t gid; /* cached gid */ short valid; /* valid creds */ short grouplen; /* length of cached groups */ - int groups[NGROUPS_UMAX]; /* cached groups */ + gid_t groups[NGROUPS_UMAX]; /* cached groups */ }; /* diff --git a/usr/src/uts/common/rpc/sec_gss/rpcsec_gss.c b/usr/src/uts/common/rpc/sec_gss/rpcsec_gss.c index 9b93b5b505..e9495d7137 100644 --- a/usr/src/uts/common/rpc/sec_gss/rpcsec_gss.c +++ b/usr/src/uts/common/rpc/sec_gss/rpcsec_gss.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 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -109,7 +108,7 @@ typedef struct _rpc_gss_data { /* The table size must be a power of two. */ #define GSSAUTH_TABLESIZE 16 #define HASH(keynum, uid_num) \ - ((((intptr_t)(keynum)) ^ (uid_num)) & (GSSAUTH_TABLESIZE - 1)) + ((((intptr_t)(keynum)) ^ ((int)uid_num)) & (GSSAUTH_TABLESIZE - 1)) /* * gss auth cache entry. diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index c6a74fea30..184473fe4d 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -438,6 +438,7 @@ CHKHDRS= \ share.h \ shm.h \ shm_impl.h \ + sid.h \ siginfo.h \ signal.h \ sleepq.h \ diff --git a/usr/src/uts/common/sys/cred.h b/usr/src/uts/common/sys/cred.h index c1400b83d7..29e9a6ddeb 100644 --- a/usr/src/uts/common/sys/cred.h +++ b/usr/src/uts/common/sys/cred.h @@ -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. */ @@ -55,6 +55,8 @@ typedef struct cred cred_t; struct proc; /* cred.h is included in proc.h */ struct prcred; +struct ksid; +struct ksidlist; struct auditinfo_addr; /* cred.h is included in audit.h */ @@ -68,6 +70,7 @@ extern void cred_init(void); extern void crhold(cred_t *); extern void crfree(cred_t *); extern cred_t *cralloc(void); /* all but ref uninitialized */ +extern cred_t *cralloc_ksid(void); /* cralloc() + ksid alloc'ed */ extern cred_t *crget(void); /* initialized */ extern cred_t *crcopy(cred_t *); extern void crcopy_to(cred_t *, cred_t *); @@ -91,6 +94,8 @@ extern gid_t crgetsgid(const cred_t *); extern zoneid_t crgetzoneid(const cred_t *); extern projid_t crgetprojid(const cred_t *); +extern cred_t *crgetmapped(const cred_t *); + extern const struct auditinfo_addr *crgetauinfo(const cred_t *); extern struct auditinfo_addr *crgetauinfo_modifiable(cred_t *); @@ -145,6 +150,26 @@ struct ts_label_s; extern struct ts_label_s *crgetlabel(const cred_t *); extern boolean_t crisremote(const cred_t *); +/* + * Private interfaces for ephemeral uids. + */ +#define VALID_UID(id) \ + ((id) <= MAXUID || valid_ephemeral_uid((id))) +#define VALID_GID(id) \ + ((id) <= MAXUID || valid_ephemeral_gid((id))) + +extern boolean_t valid_ephemeral_uid(uid_t); +extern boolean_t valid_ephemeral_gid(gid_t); + +extern int eph_uid_alloc(int, uid_t *, int); +extern int eph_gid_alloc(int, gid_t *, int); + +extern void crsetsid(cred_t *, struct ksid *, int); +extern void crsetsidlist(cred_t *, struct ksidlist *); + +extern struct ksid *crgetsid(const cred_t *, int); +extern struct ksidlist *crgetsidlist(const cred_t *); + #endif /* _KERNEL */ #ifdef __cplusplus diff --git a/usr/src/uts/common/sys/cred_impl.h b/usr/src/uts/common/sys/cred_impl.h index ef31b60922..c2272de9a5 100644 --- a/usr/src/uts/common/sys/cred_impl.h +++ b/usr/src/uts/common/sys/cred_impl.h @@ -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. */ @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/cred.h> #include <sys/priv_impl.h> +#include <sys/sid.h> #ifdef __cplusplus extern "C" { @@ -78,6 +79,7 @@ struct cred { projid_t cr_projid; /* project */ struct zone *cr_zone; /* pointer to per-zone structure */ struct ts_label_s *cr_label; /* pointer to the effective label */ + credsid_t *cr_ksid; /* pointer to SIDs */ gid_t cr_groups[1]; /* cr_groups size not fixed */ /* audit info is defined dynamically */ /* and valid only when audit enabled */ diff --git a/usr/src/uts/common/sys/param.h b/usr/src/uts/common/sys/param.h index cb7ab43c2f..d73d4cf8be 100644 --- a/usr/src/uts/common/sys/param.h +++ b/usr/src/uts/common/sys/param.h @@ -87,6 +87,7 @@ extern "C" { #ifdef _KERNEL #define MAX_TASKID 999999 #define MAX_MAXPID 999999 +#define MAXEPHUID 0xfffffffcu /* max ephemeral user id */ #endif #ifdef DEBUG @@ -99,9 +100,12 @@ extern "C" { #endif #define MAXUID 2147483647 /* max user id */ + #define MAXPROJID MAXUID /* max project id */ #define MAXLINK 32767 /* max links */ +#define MINEPHUID 0x80000000u /* min ephemeral user id */ + #define NMOUNT 40 /* est. of # mountable fs for quota calc */ #define CANBSIZ 256 /* max size of typewriter line */ @@ -464,6 +468,7 @@ extern long _sysconf(int); /* System Private interface to sysconf() */ #define PAGEOFFSET (PAGESIZE - 1) #define PAGEMASK (~PAGEOFFSET) #define MAXPID ((pid_t)_sysconf(_SC_MAXPID)) +#define MAXEPHUID ((uid_t)_sysconf(_SC_EPHID_MAX)) #ifdef __cplusplus } diff --git a/usr/src/uts/common/sys/policy.h b/usr/src/uts/common/sys/policy.h index 89636cf86d..4bea4a5c0c 100644 --- a/usr/src/uts/common/sys/policy.h +++ b/usr/src/uts/common/sys/policy.h @@ -95,6 +95,7 @@ int secpolicy_fs_config(const cred_t *, const struct vfs *); int secpolicy_fs_linkdir(const cred_t *, const struct vfs *); int secpolicy_fs_minfree(const cred_t *, const struct vfs *); int secpolicy_fs_quota(const cred_t *, const struct vfs *); +int secpolicy_idmap(const cred_t *); int secpolicy_ip(const cred_t *, int, boolean_t); int secpolicy_ip_config(const cred_t *, boolean_t); int secpolicy_ipc_access(const cred_t *, const struct kipc_perm *, mode_t); diff --git a/usr/src/uts/common/sys/priv.h b/usr/src/uts/common/sys/priv.h index ffab3a7648..08c58ef679 100644 --- a/usr/src/uts/common/sys/priv.h +++ b/usr/src/uts/common/sys/priv.h @@ -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. */ @@ -81,6 +81,7 @@ typedef enum priv_op { #define PRIVSYS_GETIMPLINFO 2 #define PRIVSYS_SETPFLAGS 3 #define PRIVSYS_GETPFLAGS 4 +#define PRIVSYS_ISSETUGID 5 /* * Maximum length of a user defined privilege name. diff --git a/usr/src/uts/common/sys/sid.h b/usr/src/uts/common/sys/sid.h new file mode 100644 index 0000000000..8a2605f484 --- /dev/null +++ b/usr/src/uts/common/sys/sid.h @@ -0,0 +1,150 @@ +/* + * 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. + */ + +#ifndef _SYS_SID_H +#define _SYS_SID_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/avl.h> + +/* + * Kernel SID data structure and functions. + */ +#ifdef __cplusplus +extern "C" { +#endif + +/* sidsys subcodes */ +#define SIDSYS_ALLOC_IDS 0 +/* Flags for ALLOC_IDS */ +#define SID_EXTEND_RANGE 0 +#define SID_NEW_RANGE 1 + +#define SIDSYS_IDMAP_REG 1 +#define SIDSYS_IDMAP_UNREG 2 + +#define SIDSYS_SID2ID 0 +#define SIDSYS_ID2SID 1 + +typedef struct domsid { + uint_t ds_rid; + char ds_dom[1]; +} domsid_t; + +typedef struct sidmap_call { + int sc_type; + union sc_val_u { + uid_t sc_id; + domsid_t sc_sid; + } sc_val; +} sidmap_call_t; + + +#ifdef _KERNEL +/* Domains are stored in AVL trees so we can share them among SIDs */ +typedef struct ksiddomain { + uint_t kd_ref; + uint_t kd_len; + char *kd_name; /* Domain part of SID */ + avl_node_t kd_link; +} ksiddomain_t; + +typedef struct ksid { + uid_t ks_id; /* Cache of (ephemeral) uid */ + uint32_t ks_rid; /* Rid part of the name */ + uint32_t ks_attr; /* Attribute */ + ksiddomain_t *ks_domain; /* Domain descsriptor */ +} ksid_t; + +typedef enum ksid_index { + KSID_USER, + KSID_GROUP, + KSID_OWNER, + KSID_COUNT /* Must be last */ +} ksid_index_t; + +/* + * As no memory may be allocated for credentials while holding p_crlock, + * all sub data structures need to be ref counted. + */ + +typedef struct ksidlist { + uint_t ksl_ref; + uint_t ksl_nsid; + uint_t ksl_neid; /* Number of ids which are ephemeral */ + ksid_t ksl_sids[1]; /* Allocate ksl_nsid times */ +} ksidlist_t; + +#define KSIDLIST_MEM(n) (sizeof (ksidlist_t) + ((n) - 1) * sizeof (ksid_t)) + +typedef struct credsid { + uint_t kr_ref; /* Reference count */ + ksid_t kr_sidx[KSID_COUNT]; /* User, group, default owner */ + ksidlist_t *kr_sidlist; /* List of SIDS */ +} credsid_t; + +const char *ksid_getdomain(ksid_t *); +uint_t ksid_getrid(ksid_t *); + +int ksid_lookup(uid_t, ksid_t *); +void ksid_rele(ksid_t *); + +credsid_t *kcrsid_alloc(void); + +credsid_t *kcrsid_setsid(credsid_t *, ksid_t *, ksid_index_t); +credsid_t *kcrsid_setsidlist(credsid_t *, ksidlist_t *); + +void kcrsid_rele(credsid_t *); +void kcrsid_hold(credsid_t *); +void kcrsidcopy_to(const credsid_t *okcr, credsid_t *nkcr); + +void ksiddomain_rele(ksiddomain_t *); +void ksiddomain_hold(ksiddomain_t *); +void ksidlist_rele(ksidlist_t *); +void ksidlist_hold(ksidlist_t *); + +ksiddomain_t *ksid_lookupdomain(const char *); + +ksidlist_t *kcrsid_gidstosids(int, gid_t *); + +int idmap_call_byid(uid_t, ksid_t *); +uid_t idmap_call_bysid(ksid_t *); + +#else + +int allocids(int, int, uid_t *, int, gid_t *); +int idmap_reg(int); +int idmap_unreg(int); + +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SID_H */ diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h index 55a6760b1e..4feaf1998e 100644 --- a/usr/src/uts/common/sys/syscall.h +++ b/usr/src/uts/common/sys/syscall.h @@ -203,7 +203,13 @@ extern "C" { * rctllist(...) :: rctlsys(2, ...) * rctlctl(...) :: rctlsys(3, ...) */ -#define SYS_issetugid 75 +#define SYS_sidsys 75 + /* + * subcodes: + * allocids(...) :: sidsys(0, ...) + * idmap_reg(...) :: sidsys(1, ...) + * idmap_unreg(...) :: sidsys(2, ...) + */ #define SYS_fsat 76 /* * subcodes: @@ -240,6 +246,7 @@ extern "C" { * getimplinfo(...) :: privsys(2, ...) * setpflags(...) :: privsys(3, ...) * getpflags(...) :: privsys(4, ...) + * issetugid(); :: privsys(5) */ #define SYS_ucredsys 83 /* diff --git a/usr/src/uts/common/sys/sysconfig.h b/usr/src/uts/common/sys/sysconfig.h index 56524eb5f6..1bbcdcfe98 100644 --- a/usr/src/uts/common/sys/sysconfig.h +++ b/usr/src/uts/common/sys/sysconfig.h @@ -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. @@ -24,7 +23,7 @@ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -102,6 +101,8 @@ extern int mach_sysconfig(int); /* UNIX 03 names */ #define _CONFIG_SYMLOOP_MAX 46 /* maximum # of symlinks in pathname */ +#define _CONFIG_EPHID_MAX 47 /* maximum ephemeral uid */ + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/types.h b/usr/src/uts/common/sys/types.h index ac5de5d5c0..3ff5497cef 100644 --- a/usr/src/uts/common/sys/types.h +++ b/usr/src/uts/common/sys/types.h @@ -365,11 +365,7 @@ typedef ulong_t mode_t; /* (historical version) */ #ifndef _UID_T #define _UID_T -#if defined(_LP64) || defined(_I32LPx) -typedef int uid_t; /* UID type */ -#else -typedef long uid_t; /* (historical version) */ -#endif +typedef unsigned int uid_t; /* UID type */ #endif /* _UID_T */ typedef uid_t gid_t; /* GID type */ diff --git a/usr/src/uts/common/sys/types32.h b/usr/src/uts/common/sys/types32.h index 527e5a7938..daa27eaf76 100644 --- a/usr/src/uts/common/sys/types32.h +++ b/usr/src/uts/common/sys/types32.h @@ -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,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1997-1998 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #ifndef _SYS_TYPES32_H @@ -58,8 +57,8 @@ typedef uint32_t major32_t; typedef uint32_t minor32_t; typedef int32_t key32_t; typedef uint32_t mode32_t; -typedef int32_t uid32_t; -typedef int32_t gid32_t; +typedef uint32_t uid32_t; +typedef uint32_t gid32_t; typedef uint32_t nlink32_t; typedef uint32_t dev32_t; typedef int32_t pid32_t; diff --git a/usr/src/uts/common/sys/unistd.h b/usr/src/uts/common/sys/unistd.h index fa770b803e..92d0798426 100644 --- a/usr/src/uts/common/sys/unistd.h +++ b/usr/src/uts/common/sys/unistd.h @@ -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. @@ -26,7 +25,7 @@ */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -211,6 +210,7 @@ extern "C" { #define _SC_STACK_PROT 515 /* default stack protection */ #define _SC_NPROCESSORS_MAX 516 /* maximum # of processors */ #define _SC_CPUID_MAX 517 /* maximum CPU id */ +#define _SC_EPHID_MAX 518 /* maximum ephemeral id */ /* * POSIX.1c (pthreads) names. These values are defined above diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h index 0834cf1f84..114ce97811 100644 --- a/usr/src/uts/common/sys/vfs.h +++ b/usr/src/uts/common/sys/vfs.h @@ -269,6 +269,7 @@ typedef struct vfs { #define VFS_NODEVICES 0x800 /* device-special files disallowed */ #define VFS_NOEXEC 0x1000 /* executables disallowed */ #define VFS_STATS 0x2000 /* file system can collect stats */ +#define VFS_XID 0x4000 /* file system supports extended ids */ #define VFS_NORESOURCE "unspecified_resource" #define VFS_NOMNTPT "unspecified_mountpoint" @@ -405,6 +406,7 @@ enum { #define VSW_NOTZONESAFE 0x08 /* zone_enter(2) should fail for these files */ #define VSW_VOLATILEDEV 0x10 /* vfs_dev can change each time fs is mounted */ #define VSW_STATS 0x20 /* file system can collect stats */ +#define VSW_XID 0x40 /* file system supports extended ids */ #define VSW_INSTALLED 0x8000 /* this vsw is associated with a file system */ 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)); } |