Home | History | Annotate | Download | only in os
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1676       jpk  * Common Development and Distribution License (the "License").
      6   1676       jpk  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*
     22   9151    Thomas  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0    stevel  * Use is subject to license terms.
     24      0    stevel  */
     25      0    stevel 
     26      0    stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27      0    stevel /*	  All Rights Reserved  	*/
     28      0    stevel 
     29      0    stevel /*
     30      0    stevel  * University Copyright- Copyright (c) 1982, 1986, 1988
     31      0    stevel  * The Regents of the University of California
     32      0    stevel  * All Rights Reserved
     33      0    stevel  *
     34      0    stevel  * University Acknowledgment- Portions of this document are derived from
     35      0    stevel  * software developed by the University of California, Berkeley, and its
     36      0    stevel  * contributors.
     37      0    stevel  */
     38      0    stevel 
     39      0    stevel #include <sys/types.h>
     40      0    stevel #include <sys/sysmacros.h>
     41      0    stevel #include <sys/param.h>
     42      0    stevel #include <sys/systm.h>
     43      0    stevel #include <sys/cred_impl.h>
     44      0    stevel #include <sys/policy.h>
     45      0    stevel #include <sys/vnode.h>
     46      0    stevel #include <sys/errno.h>
     47      0    stevel #include <sys/kmem.h>
     48      0    stevel #include <sys/user.h>
     49      0    stevel #include <sys/proc.h>
     50      0    stevel #include <sys/syscall.h>
     51      0    stevel #include <sys/debug.h>
     52      0    stevel #include <sys/atomic.h>
     53      0    stevel #include <sys/ucred.h>
     54      0    stevel #include <sys/prsystm.h>
     55      0    stevel #include <sys/modctl.h>
     56   4321    casper #include <sys/avl.h>
     57   5331       amw #include <sys/door.h>
     58      0    stevel #include <c2/audit.h>
     59      0    stevel #include <sys/zone.h>
     60   1676       jpk #include <sys/tsol/label.h>
     61   4321    casper #include <sys/sid.h>
     62   4520  nw141292 #include <sys/idmap.h>
     63   6134    casper #include <sys/klpd.h>
     64   5331       amw #include <sys/varargs.h>
     65  11134    Casper #include <util/qsort.h>
     66   4321    casper 
     67   5771  jp151216 
     68   5771  jp151216 /* Ephemeral IDs Zones specific data */
     69   5771  jp151216 typedef struct ephemeral_zsd {
     70   5771  jp151216 	uid_t		min_uid;
     71   5771  jp151216 	uid_t		last_uid;
     72   5771  jp151216 	gid_t		min_gid;
     73   5771  jp151216 	gid_t		last_gid;
     74   4321    casper 	kmutex_t	eph_lock;
     75   5771  jp151216 	cred_t		*eph_nobody;
     76   5771  jp151216 } ephemeral_zsd_t;
     77   5771  jp151216 
     78  11134    Casper /* Supplemental groups list. */
     79  11134    Casper typedef struct credgrp {
     80  11134    Casper 	uint_t		crg_ref;
     81  11134    Casper 	uint_t		crg_ngroups;
     82  11134    Casper 	gid_t		crg_groups[1];
     83  11134    Casper } credgrp_t;
     84  11134    Casper 
     85  11134    Casper static void crgrphold(credgrp_t *);
     86  11134    Casper 
     87  11134    Casper #define	CREDGRPSZ(ngrp)	(sizeof (credgrp_t) + ((ngrp - 1) * sizeof (gid_t)))
     88   5771  jp151216 
     89   5771  jp151216 static kmutex_t		ephemeral_zone_mutex;
     90   5771  jp151216 static zone_key_t	ephemeral_zone_key;
     91      0    stevel 
     92      0    stevel static struct kmem_cache *cred_cache;
     93   5771  jp151216 static size_t		crsize = 0;
     94   5771  jp151216 static int		audoff = 0;
     95   5771  jp151216 uint32_t		ucredsize;
     96   5771  jp151216 cred_t			*kcred;
     97   5771  jp151216 static cred_t		*dummycr;
     98      0    stevel 
     99      0    stevel int rstlink;		/* link(2) restricted to files owned by user? */
    100      0    stevel 
    101      0    stevel static int get_c2audit_load(void);
    102      0    stevel 
    103      0    stevel #define	CR_AUINFO(c)	(auditinfo_addr_t *)((audoff == 0) ? NULL : \
    104      0    stevel 			    ((char *)(c)) + audoff)
    105      0    stevel 
    106   1676       jpk #define	REMOTE_PEER_CRED(c)	((c)->cr_gid == -1)
    107   4321    casper 
    108  11134    Casper #define	BIN_GROUP_SEARCH_CUTOFF	16
    109   4321    casper 
    110   4321    casper static boolean_t hasephids = B_FALSE;
    111   5771  jp151216 
    112   5771  jp151216 static ephemeral_zsd_t *
    113   5771  jp151216 get_ephemeral_zsd(zone_t *zone)
    114   5771  jp151216 {
    115   5771  jp151216 	ephemeral_zsd_t *eph_zsd;
    116   5771  jp151216 
    117   5771  jp151216 	eph_zsd = zone_getspecific(ephemeral_zone_key, zone);
    118   5771  jp151216 	if (eph_zsd != NULL) {
    119   5771  jp151216 		return (eph_zsd);
    120   5771  jp151216 	}
    121   5771  jp151216 
    122   5771  jp151216 	mutex_enter(&ephemeral_zone_mutex);
    123   5771  jp151216 	eph_zsd = zone_getspecific(ephemeral_zone_key, zone);
    124   5771  jp151216 	if (eph_zsd == NULL) {
    125   5771  jp151216 		eph_zsd = kmem_zalloc(sizeof (ephemeral_zsd_t), KM_SLEEP);
    126   5771  jp151216 		eph_zsd->min_uid = MAXUID;
    127   5771  jp151216 		eph_zsd->last_uid = IDMAP_WK__MAX_UID;
    128   5771  jp151216 		eph_zsd->min_gid = MAXUID;
    129   5771  jp151216 		eph_zsd->last_gid = IDMAP_WK__MAX_GID;
    130   5771  jp151216 		mutex_init(&eph_zsd->eph_lock, NULL, MUTEX_DEFAULT, NULL);
    131   5771  jp151216 
    132   5771  jp151216 		/*
    133   5771  jp151216 		 * nobody is used to map SID containing CRs.
    134   5771  jp151216 		 */
    135   5771  jp151216 		eph_zsd->eph_nobody = crdup(zone->zone_kcred);
    136   5771  jp151216 		(void) crsetugid(eph_zsd->eph_nobody, UID_NOBODY, GID_NOBODY);
    137   5771  jp151216 		CR_FLAGS(eph_zsd->eph_nobody) = 0;
    138   5771  jp151216 		eph_zsd->eph_nobody->cr_zone = zone;
    139   5771  jp151216 
    140   5771  jp151216 		(void) zone_setspecific(ephemeral_zone_key, zone, eph_zsd);
    141   5771  jp151216 	}
    142   5771  jp151216 	mutex_exit(&ephemeral_zone_mutex);
    143   5771  jp151216 	return (eph_zsd);
    144   5771  jp151216 }
    145   6134    casper 
    146   9710       Ken static cred_t *crdup_flags(const cred_t *, int);
    147   6134    casper static cred_t *cralloc_flags(int);
    148   5771  jp151216 
    149   5771  jp151216 /*
    150   5771  jp151216  * This function is called when a zone is destroyed
    151   5771  jp151216  */
    152   5771  jp151216 static void
    153   5771  jp151216 /* ARGSUSED */
    154   5771  jp151216 destroy_ephemeral_zsd(zoneid_t zone_id, void *arg)
    155   5771  jp151216 {
    156   5771  jp151216 	ephemeral_zsd_t *eph_zsd = arg;
    157   5771  jp151216 	if (eph_zsd != NULL) {
    158   5771  jp151216 		mutex_destroy(&eph_zsd->eph_lock);
    159   5771  jp151216 		crfree(eph_zsd->eph_nobody);
    160   5771  jp151216 		kmem_free(eph_zsd, sizeof (ephemeral_zsd_t));
    161   5771  jp151216 	}
    162   5771  jp151216 }
    163   5771  jp151216 
    164   5771  jp151216 
    165      0    stevel 
    166      0    stevel /*
    167      0    stevel  * Initialize credentials data structures.
    168      0    stevel  */
    169      0    stevel 
    170      0    stevel void
    171      0    stevel cred_init(void)
    172      0    stevel {
    173      0    stevel 	priv_init();
    174      0    stevel 
    175  11134    Casper 	crsize = sizeof (cred_t);
    176      0    stevel 
    177      0    stevel 	if (get_c2audit_load() > 0) {
    178      0    stevel #ifdef _LP64
    179      0    stevel 		/* assure audit context is 64-bit aligned */
    180      0    stevel 		audoff = (crsize +
    181      0    stevel 		    sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1);
    182      0    stevel #else	/* _LP64 */
    183      0    stevel 		audoff = crsize;
    184      0    stevel #endif	/* _LP64 */
    185      0    stevel 		crsize = audoff + sizeof (auditinfo_addr_t);
    186      0    stevel 		crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1);
    187      0    stevel 	}
    188      0    stevel 
    189      0    stevel 	cred_cache = kmem_cache_create("cred_cache", crsize, 0,
    190   4520  nw141292 	    NULL, NULL, NULL, NULL, NULL, 0);
    191      0    stevel 
    192      0    stevel 	/*
    193   1676       jpk 	 * dummycr is used to copy initial state for creds.
    194   1676       jpk 	 */
    195   1676       jpk 	dummycr = cralloc();
    196   1676       jpk 	bzero(dummycr, crsize);
    197   1676       jpk 	dummycr->cr_ref = 1;
    198   4321    casper 	dummycr->cr_uid = (uid_t)-1;
    199   4321    casper 	dummycr->cr_gid = (gid_t)-1;
    200   4321    casper 	dummycr->cr_ruid = (uid_t)-1;
    201   4321    casper 	dummycr->cr_rgid = (gid_t)-1;
    202   4321    casper 	dummycr->cr_suid = (uid_t)-1;
    203   4321    casper 	dummycr->cr_sgid = (gid_t)-1;
    204   4321    casper 
    205   1676       jpk 
    206   1676       jpk 	/*
    207      0    stevel 	 * kcred is used by anything that needs all privileges; it's
    208      0    stevel 	 * also the template used for crget as it has all the compatible
    209      0    stevel 	 * sets filled in.
    210      0    stevel 	 */
    211      0    stevel 	kcred = cralloc();
    212      0    stevel 
    213      0    stevel 	bzero(kcred, crsize);
    214      0    stevel 	kcred->cr_ref = 1;
    215      0    stevel 
    216      0    stevel 	/* kcred is never freed, so we don't need zone_cred_hold here */
    217      0    stevel 	kcred->cr_zone = &zone0;
    218      0    stevel 
    219      0    stevel 	priv_fillset(&CR_LPRIV(kcred));
    220      0    stevel 	CR_IPRIV(kcred) = *priv_basic;
    221      0    stevel 
    222      0    stevel 	/* Not a basic privilege, if chown is not restricted add it to I0 */
    223      0    stevel 	if (!rstchown)
    224      0    stevel 		priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF);
    225      0    stevel 
    226      0    stevel 	/* Basic privilege, if link is restricted remove it from I0 */
    227      0    stevel 	if (rstlink)
    228      0    stevel 		priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY);
    229      0    stevel 
    230      0    stevel 	CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred);
    231   1676       jpk 
    232   1676       jpk 	CR_FLAGS(kcred) = NET_MAC_AWARE;
    233      0    stevel 
    234      0    stevel 	/*
    235      0    stevel 	 * Set up credentials of p0.
    236      0    stevel 	 */
    237      0    stevel 	ttoproc(curthread)->p_cred = kcred;
    238      0    stevel 	curthread->t_cred = kcred;
    239      0    stevel 
    240   5771  jp151216 	ucredsize = UCRED_SIZE;
    241   4321    casper 
    242   5771  jp151216 	mutex_init(&ephemeral_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
    243   5771  jp151216 	zone_key_create(&ephemeral_zone_key, NULL, NULL, destroy_ephemeral_zsd);
    244      0    stevel }
    245      0    stevel 
    246      0    stevel /*
    247      0    stevel  * Allocate (nearly) uninitialized cred_t.
    248      0    stevel  */
    249   6134    casper static cred_t *
    250   6134    casper cralloc_flags(int flgs)
    251      0    stevel {
    252   6134    casper 	cred_t *cr = kmem_cache_alloc(cred_cache, flgs);
    253   6134    casper 
    254   6134    casper 	if (cr == NULL)
    255   6134    casper 		return (NULL);
    256   6134    casper 
    257      0    stevel 	cr->cr_ref = 1;		/* So we can crfree() */
    258      0    stevel 	cr->cr_zone = NULL;
    259   1676       jpk 	cr->cr_label = NULL;
    260   4321    casper 	cr->cr_ksid = NULL;
    261   6134    casper 	cr->cr_klpd = NULL;
    262  11134    Casper 	cr->cr_grps = NULL;
    263   4321    casper 	return (cr);
    264   6134    casper }
    265   6134    casper 
    266   6134    casper cred_t *
    267   6134    casper cralloc(void)
    268   6134    casper {
    269   6134    casper 	return (cralloc_flags(KM_SLEEP));
    270   4321    casper }
    271   4321    casper 
    272   4321    casper /*
    273   4321    casper  * As cralloc but prepared for ksid change (if appropriate).
    274   4321    casper  */
    275   4321    casper cred_t *
    276   4321    casper cralloc_ksid(void)
    277   4321    casper {
    278   4321    casper 	cred_t *cr = cralloc();
    279   4321    casper 	if (hasephids)
    280   4321    casper 		cr->cr_ksid = kcrsid_alloc();
    281      0    stevel 	return (cr);
    282      0    stevel }
    283      0    stevel 
    284      0    stevel /*
    285      0    stevel  * Allocate a initialized cred structure and crhold() it.
    286      0    stevel  * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0
    287      0    stevel  */
    288      0    stevel cred_t *
    289      0    stevel crget(void)
    290      0    stevel {
    291      0    stevel 	cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP);
    292      0    stevel 
    293      0    stevel 	bcopy(kcred, cr, crsize);
    294      0    stevel 	cr->cr_ref = 1;
    295      0    stevel 	zone_cred_hold(cr->cr_zone);
    296   1676       jpk 	if (cr->cr_label)
    297   1676       jpk 		label_hold(cr->cr_label);
    298   6134    casper 	ASSERT(cr->cr_klpd == NULL);
    299  11134    Casper 	ASSERT(cr->cr_grps == NULL);
    300      0    stevel 	return (cr);
    301      0    stevel }
    302      0    stevel 
    303      0    stevel /*
    304      0    stevel  * Broadcast the cred to all the threads in the process.
    305      0    stevel  * The current thread's credentials can be set right away, but other
    306      0    stevel  * threads must wait until the start of the next system call or trap.
    307      0    stevel  * This avoids changing the cred in the middle of a system call.
    308      0    stevel  *
    309      0    stevel  * The cred has already been held for the process and the thread (2 holds),
    310      0    stevel  * and p->p_cred set.
    311      0    stevel  *
    312      0    stevel  * p->p_crlock shouldn't be held here, since p_lock must be acquired.
    313      0    stevel  */
    314      0    stevel void
    315      0    stevel crset(proc_t *p, cred_t *cr)
    316      0    stevel {
    317      0    stevel 	kthread_id_t	t;
    318      0    stevel 	kthread_id_t	first;
    319      0    stevel 	cred_t *oldcr;
    320      0    stevel 
    321      0    stevel 	ASSERT(p == curproc);	/* assumes p_lwpcnt can't change */
    322      0    stevel 
    323      0    stevel 	/*
    324      0    stevel 	 * DTrace accesses t_cred in probe context.  t_cred must always be
    325      0    stevel 	 * either NULL, or point to a valid, allocated cred structure.
    326      0    stevel 	 */
    327      0    stevel 	t = curthread;
    328      0    stevel 	oldcr = t->t_cred;
    329      0    stevel 	t->t_cred = cr;		/* the cred is held by caller for this thread */
    330      0    stevel 	crfree(oldcr);		/* free the old cred for the thread */
    331      0    stevel 
    332      0    stevel 	/*
    333      0    stevel 	 * Broadcast to other threads, if any.
    334      0    stevel 	 */
    335      0    stevel 	if (p->p_lwpcnt > 1) {
    336      0    stevel 		mutex_enter(&p->p_lock);	/* to keep thread list safe */
    337      0    stevel 		first = curthread;
    338      0    stevel 		for (t = first->t_forw; t != first; t = t->t_forw)
    339      0    stevel 			t->t_pre_sys = 1; /* so syscall will get new cred */
    340      0    stevel 		mutex_exit(&p->p_lock);
    341      0    stevel 	}
    342      0    stevel }
    343      0    stevel 
    344      0    stevel /*
    345      0    stevel  * Put a hold on a cred structure.
    346      0    stevel  */
    347      0    stevel void
    348      0    stevel crhold(cred_t *cr)
    349      0    stevel {
    350      0    stevel 	atomic_add_32(&cr->cr_ref, 1);
    351      0    stevel }
    352      0    stevel 
    353      0    stevel /*
    354      0    stevel  * Release previous hold on a cred structure.  Free it if refcnt == 0.
    355   1676       jpk  * If cred uses label different from zone label, free it.
    356      0    stevel  */
    357      0    stevel void
    358      0    stevel crfree(cred_t *cr)
    359      0    stevel {
    360      0    stevel 	if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) {
    361      0    stevel 		ASSERT(cr != kcred);
    362   1676       jpk 		if (cr->cr_label)
    363   1676       jpk 			label_rele(cr->cr_label);
    364   6134    casper 		if (cr->cr_klpd)
    365   6134    casper 			crklpd_rele(cr->cr_klpd);
    366      0    stevel 		if (cr->cr_zone)
    367      0    stevel 			zone_cred_rele(cr->cr_zone);
    368   4321    casper 		if (cr->cr_ksid)
    369   4321    casper 			kcrsid_rele(cr->cr_ksid);
    370  11134    Casper 		if (cr->cr_grps)
    371  11134    Casper 			crgrprele(cr->cr_grps);
    372  11134    Casper 
    373      0    stevel 		kmem_cache_free(cred_cache, cr);
    374      0    stevel 	}
    375      0    stevel }
    376      0    stevel 
    377      0    stevel /*
    378      0    stevel  * Copy a cred structure to a new one and free the old one.
    379      0    stevel  *	The new cred will have two references.  One for the calling process,
    380      0    stevel  * 	and one for the thread.
    381      0    stevel  */
    382      0    stevel cred_t *
    383      0    stevel crcopy(cred_t *cr)
    384      0    stevel {
    385      0    stevel 	cred_t *newcr;
    386      0    stevel 
    387      0    stevel 	newcr = cralloc();
    388      0    stevel 	bcopy(cr, newcr, crsize);
    389      0    stevel 	if (newcr->cr_zone)
    390      0    stevel 		zone_cred_hold(newcr->cr_zone);
    391   1676       jpk 	if (newcr->cr_label)
    392   6134    casper 		label_hold(newcr->cr_label);
    393   4321    casper 	if (newcr->cr_ksid)
    394   6134    casper 		kcrsid_hold(newcr->cr_ksid);
    395   6134    casper 	if (newcr->cr_klpd)
    396   6134    casper 		crklpd_hold(newcr->cr_klpd);
    397  11134    Casper 	if (newcr->cr_grps)
    398  11134    Casper 		crgrphold(newcr->cr_grps);
    399      0    stevel 	crfree(cr);
    400      0    stevel 	newcr->cr_ref = 2;		/* caller gets two references */
    401      0    stevel 	return (newcr);
    402      0    stevel }
    403      0    stevel 
    404      0    stevel /*
    405      0    stevel  * Copy a cred structure to a new one and free the old one.
    406      0    stevel  *	The new cred will have two references.  One for the calling process,
    407      0    stevel  * 	and one for the thread.
    408      0    stevel  * This variation on crcopy uses a pre-allocated structure for the
    409      0    stevel  * "new" cred.
    410      0    stevel  */
    411      0    stevel void
    412      0    stevel crcopy_to(cred_t *oldcr, cred_t *newcr)
    413      0    stevel {
    414   4321    casper 	credsid_t *nkcr = newcr->cr_ksid;
    415   4321    casper 
    416      0    stevel 	bcopy(oldcr, newcr, crsize);
    417      0    stevel 	if (newcr->cr_zone)
    418      0    stevel 		zone_cred_hold(newcr->cr_zone);
    419   1676       jpk 	if (newcr->cr_label)
    420   1676       jpk 		label_hold(newcr->cr_label);
    421   6134    casper 	if (newcr->cr_klpd)
    422   6134    casper 		crklpd_hold(newcr->cr_klpd);
    423  11134    Casper 	if (newcr->cr_grps)
    424  11134    Casper 		crgrphold(newcr->cr_grps);
    425   4321    casper 	if (nkcr) {
    426   4321    casper 		newcr->cr_ksid = nkcr;
    427   4321    casper 		kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid);
    428   4321    casper 	} else if (newcr->cr_ksid)
    429   4321    casper 		kcrsid_hold(newcr->cr_ksid);
    430      0    stevel 	crfree(oldcr);
    431      0    stevel 	newcr->cr_ref = 2;		/* caller gets two references */
    432      0    stevel }
    433      0    stevel 
    434      0    stevel /*
    435      0    stevel  * Dup a cred struct to a new held one.
    436      0    stevel  *	The old cred is not freed.
    437      0    stevel  */
    438   6134    casper static cred_t *
    439   9710       Ken crdup_flags(const cred_t *cr, int flgs)
    440      0    stevel {
    441      0    stevel 	cred_t *newcr;
    442      0    stevel 
    443   6134    casper 	newcr = cralloc_flags(flgs);
    444   6134    casper 
    445   6134    casper 	if (newcr == NULL)
    446   6134    casper 		return (NULL);
    447   6134    casper 
    448      0    stevel 	bcopy(cr, newcr, crsize);
    449      0    stevel 	if (newcr->cr_zone)
    450      0    stevel 		zone_cred_hold(newcr->cr_zone);
    451   1676       jpk 	if (newcr->cr_label)
    452   1676       jpk 		label_hold(newcr->cr_label);
    453   6134    casper 	if (newcr->cr_klpd)
    454   6134    casper 		crklpd_hold(newcr->cr_klpd);
    455   4321    casper 	if (newcr->cr_ksid)
    456   4321    casper 		kcrsid_hold(newcr->cr_ksid);
    457  11134    Casper 	if (newcr->cr_grps)
    458  11134    Casper 		crgrphold(newcr->cr_grps);
    459      0    stevel 	newcr->cr_ref = 1;
    460      0    stevel 	return (newcr);
    461   6134    casper }
    462   6134    casper 
    463   6134    casper cred_t *
    464   6134    casper crdup(cred_t *cr)
    465   6134    casper {
    466   6134    casper 	return (crdup_flags(cr, KM_SLEEP));
    467      0    stevel }
    468      0    stevel 
    469      0    stevel /*
    470      0    stevel  * Dup a cred struct to a new held one.
    471      0    stevel  *	The old cred is not freed.
    472      0    stevel  * This variation on crdup uses a pre-allocated structure for the
    473      0    stevel  * "new" cred.
    474      0    stevel  */
    475      0    stevel void
    476      0    stevel crdup_to(cred_t *oldcr, cred_t *newcr)
    477      0    stevel {
    478   4321    casper 	credsid_t *nkcr = newcr->cr_ksid;
    479   4321    casper 
    480      0    stevel 	bcopy(oldcr, newcr, crsize);
    481      0    stevel 	if (newcr->cr_zone)
    482      0    stevel 		zone_cred_hold(newcr->cr_zone);
    483   1676       jpk 	if (newcr->cr_label)
    484   1676       jpk 		label_hold(newcr->cr_label);
    485   6134    casper 	if (newcr->cr_klpd)
    486   6134    casper 		crklpd_hold(newcr->cr_klpd);
    487  11134    Casper 	if (newcr->cr_grps)
    488  11134    Casper 		crgrphold(newcr->cr_grps);
    489   4321    casper 	if (nkcr) {
    490   4321    casper 		newcr->cr_ksid = nkcr;
    491   4321    casper 		kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid);
    492   4321    casper 	} else if (newcr->cr_ksid)
    493   4321    casper 		kcrsid_hold(newcr->cr_ksid);
    494      0    stevel 	newcr->cr_ref = 1;
    495      0    stevel }
    496      0    stevel 
    497      0    stevel /*
    498      0    stevel  * Return the (held) credentials for the current running process.
    499      0    stevel  */
    500      0    stevel cred_t *
    501   1676       jpk crgetcred(void)
    502      0    stevel {
    503      0    stevel 	cred_t *cr;
    504      0    stevel 	proc_t *p;
    505      0    stevel 
    506      0    stevel 	p = ttoproc(curthread);
    507      0    stevel 	mutex_enter(&p->p_crlock);
    508      0    stevel 	crhold(cr = p->p_cred);
    509      0    stevel 	mutex_exit(&p->p_crlock);
    510      0    stevel 	return (cr);
    511      0    stevel }
    512      0    stevel 
    513      0    stevel /*
    514      0    stevel  * Backward compatibility check for suser().
    515      0    stevel  * Accounting flag is now set in the policy functions; auditing is
    516      0    stevel  * done through use of privilege in the audit trail.
    517      0    stevel  */
    518      0    stevel int
    519      0    stevel suser(cred_t *cr)
    520      0    stevel {
    521      0    stevel 	return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL)
    522      0    stevel 	    == 0);
    523      0    stevel }
    524      0    stevel 
    525      0    stevel /*
    526      0    stevel  * Determine whether the supplied group id is a member of the group
    527      0    stevel  * described by the supplied credentials.
    528      0    stevel  */
    529      0    stevel int
    530      0    stevel groupmember(gid_t gid, const cred_t *cr)
    531      0    stevel {
    532      0    stevel 	if (gid == cr->cr_gid)
    533      0    stevel 		return (1);
    534      0    stevel 	return (supgroupmember(gid, cr));
    535      0    stevel }
    536      0    stevel 
    537      0    stevel /*
    538      0    stevel  * As groupmember but only check against the supplemental groups.
    539      0    stevel  */
    540      0    stevel int
    541      0    stevel supgroupmember(gid_t gid, const cred_t *cr)
    542      0    stevel {
    543  11134    Casper 	int hi, lo;
    544  11134    Casper 	credgrp_t *grps = cr->cr_grps;
    545      0    stevel 	const gid_t *gp, *endgp;
    546      0    stevel 
    547  11134    Casper 	if (grps == NULL)
    548  11134    Casper 		return (0);
    549  11134    Casper 
    550  11134    Casper 	/* For a small number of groups, use sequentials search. */
    551  11134    Casper 	if (grps->crg_ngroups <= BIN_GROUP_SEARCH_CUTOFF) {
    552  11134    Casper 		endgp = &grps->crg_groups[grps->crg_ngroups];
    553  11134    Casper 		for (gp = grps->crg_groups; gp < endgp; gp++)
    554  11134    Casper 			if (*gp == gid)
    555  11134    Casper 				return (1);
    556  11134    Casper 		return (0);
    557  11134    Casper 	}
    558  11134    Casper 
    559  11134    Casper 	/* We use binary search when we have many groups. */
    560  11134    Casper 	lo = 0;
    561  11134    Casper 	hi = grps->crg_ngroups - 1;
    562  11134    Casper 	gp = grps->crg_groups;
    563  11134    Casper 
    564  11134    Casper 	do {
    565  11134    Casper 		int m = (lo + hi) / 2;
    566  11134    Casper 
    567  11134    Casper 		if (gid > gp[m])
    568  11134    Casper 			lo = m + 1;
    569  11134    Casper 		else if (gid < gp[m])
    570  11134    Casper 			hi = m - 1;
    571  11134    Casper 		else
    572      0    stevel 			return (1);
    573  11134    Casper 	} while (lo <= hi);
    574  11134    Casper 
    575      0    stevel 	return (0);
    576      0    stevel }
    577      0    stevel 
    578      0    stevel /*
    579      0    stevel  * This function is called to check whether the credentials set
    580      0    stevel  * "scrp" has permission to act on credentials set "tcrp".  It enforces the
    581      0    stevel  * permission requirements needed to send a signal to a process.
    582      0    stevel  * The same requirements are imposed by other system calls, however.
    583      0    stevel  *
    584      0    stevel  * The rules are:
    585      0    stevel  * (1) if the credentials are the same, the check succeeds
    586      0    stevel  * (2) if the zone ids don't match, and scrp is not in the global zone or
    587      0    stevel  *     does not have the PRIV_PROC_ZONE privilege, the check fails
    588      0    stevel  * (3) if the real or effective user id of scrp matches the real or saved
    589      0    stevel  *     user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check
    590      0    stevel  *     succeeds
    591      0    stevel  * (4) otherwise, the check fails
    592      0    stevel  */
    593      0    stevel int
    594      0    stevel hasprocperm(const cred_t *tcrp, const cred_t *scrp)
    595      0    stevel {
    596      0    stevel 	if (scrp == tcrp)
    597      0    stevel 		return (1);
    598      0    stevel 	if (scrp->cr_zone != tcrp->cr_zone &&
    599      0    stevel 	    (scrp->cr_zone != global_zone ||
    600      0    stevel 	    secpolicy_proc_zone(scrp) != 0))
    601      0    stevel 		return (0);
    602      0    stevel 	if (scrp->cr_uid == tcrp->cr_ruid ||
    603      0    stevel 	    scrp->cr_ruid == tcrp->cr_ruid ||
    604      0    stevel 	    scrp->cr_uid  == tcrp->cr_suid ||
    605      0    stevel 	    scrp->cr_ruid == tcrp->cr_suid ||
    606      0    stevel 	    !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm"))
    607      0    stevel 		return (1);
    608      0    stevel 	return (0);
    609      0    stevel }
    610      0    stevel 
    611      0    stevel /*
    612      0    stevel  * This interface replaces hasprocperm; it works like hasprocperm but
    613      0    stevel  * additionally returns success if the proc_t's match
    614      0    stevel  * It is the preferred interface for most uses.
    615   6134    casper  * And it will acquire p_crlock itself, so it assert's that it shouldn't
    616      0    stevel  * be held.
    617      0    stevel  */
    618      0    stevel int
    619      0    stevel prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp)
    620      0    stevel {
    621      0    stevel 	int rets;
    622      0    stevel 	cred_t *tcrp;
    623      0    stevel 
    624      0    stevel 	ASSERT(MUTEX_NOT_HELD(&tp->p_crlock));
    625      0    stevel 
    626      0    stevel 	if (tp == sp)
    627      0    stevel 		return (1);
    628      0    stevel 
    629      0    stevel 	if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0)
    630      0    stevel 		return (0);
    631      0    stevel 
    632      0    stevel 	mutex_enter(&tp->p_crlock);
    633   6134    casper 	crhold(tcrp = tp->p_cred);
    634   6134    casper 	mutex_exit(&tp->p_crlock);
    635      0    stevel 	rets = hasprocperm(tcrp, scrp);
    636   6134    casper 	crfree(tcrp);
    637      0    stevel 
    638      0    stevel 	return (rets);
    639      0    stevel }
    640      0    stevel 
    641      0    stevel /*
    642      0    stevel  * This routine is used to compare two credentials to determine if
    643      0    stevel  * they refer to the same "user".  If the pointers are equal, then
    644      0    stevel  * they must refer to the same user.  Otherwise, the contents of
    645      0    stevel  * the credentials are compared to see whether they are equivalent.
    646      0    stevel  *
    647      0    stevel  * This routine returns 0 if the credentials refer to the same user,
    648      0    stevel  * 1 if they do not.
    649      0    stevel  */
    650      0    stevel int
    651      0    stevel crcmp(const cred_t *cr1, const cred_t *cr2)
    652      0    stevel {
    653  11134    Casper 	credgrp_t *grp1, *grp2;
    654      0    stevel 
    655      0    stevel 	if (cr1 == cr2)
    656      0    stevel 		return (0);
    657      0    stevel 
    658      0    stevel 	if (cr1->cr_uid == cr2->cr_uid &&
    659      0    stevel 	    cr1->cr_gid == cr2->cr_gid &&
    660      0    stevel 	    cr1->cr_ruid == cr2->cr_ruid &&
    661      0    stevel 	    cr1->cr_rgid == cr2->cr_rgid &&
    662      0    stevel 	    cr1->cr_zone == cr2->cr_zone &&
    663  11134    Casper 	    ((grp1 = cr1->cr_grps) == (grp2 = cr2->cr_grps) ||
    664  11134    Casper 	    (grp1 != NULL && grp2 != NULL &&
    665  11134    Casper 	    grp1->crg_ngroups == grp2->crg_ngroups &&
    666  11134    Casper 	    bcmp(grp1->crg_groups, grp2->crg_groups,
    667  11134    Casper 	    grp1->crg_ngroups * sizeof (gid_t)) == 0))) {
    668      0    stevel 		return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2)));
    669      0    stevel 	}
    670      0    stevel 	return (1);
    671      0    stevel }
    672      0    stevel 
    673      0    stevel /*
    674      0    stevel  * Read access functions to cred_t.
    675      0    stevel  */
    676      0    stevel uid_t
    677      0    stevel crgetuid(const cred_t *cr)
    678      0    stevel {
    679      0    stevel 	return (cr->cr_uid);
    680      0    stevel }
    681      0    stevel 
    682      0    stevel uid_t
    683      0    stevel crgetruid(const cred_t *cr)
    684      0    stevel {
    685      0    stevel 	return (cr->cr_ruid);
    686      0    stevel }
    687      0    stevel 
    688      0    stevel uid_t
    689      0    stevel crgetsuid(const cred_t *cr)
    690      0    stevel {
    691      0    stevel 	return (cr->cr_suid);
    692      0    stevel }
    693      0    stevel 
    694      0    stevel gid_t
    695      0    stevel crgetgid(const cred_t *cr)
    696      0    stevel {
    697      0    stevel 	return (cr->cr_gid);
    698      0    stevel }
    699      0    stevel 
    700      0    stevel gid_t
    701      0    stevel crgetrgid(const cred_t *cr)
    702      0    stevel {
    703      0    stevel 	return (cr->cr_rgid);
    704      0    stevel }
    705      0    stevel 
    706      0    stevel gid_t
    707      0    stevel crgetsgid(const cred_t *cr)
    708      0    stevel {
    709      0    stevel 	return (cr->cr_sgid);
    710      0    stevel }
    711      0    stevel 
    712      0    stevel const auditinfo_addr_t *
    713      0    stevel crgetauinfo(const cred_t *cr)
    714      0    stevel {
    715      0    stevel 	return ((const auditinfo_addr_t *)CR_AUINFO(cr));
    716      0    stevel }
    717      0    stevel 
    718      0    stevel auditinfo_addr_t *
    719      0    stevel crgetauinfo_modifiable(cred_t *cr)
    720      0    stevel {
    721      0    stevel 	return (CR_AUINFO(cr));
    722      0    stevel }
    723      0    stevel 
    724      0    stevel zoneid_t
    725      0    stevel crgetzoneid(const cred_t *cr)
    726      0    stevel {
    727   1676       jpk 	return (cr->cr_zone == NULL ?
    728   1676       jpk 	    (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) :
    729   1676       jpk 	    cr->cr_zone->zone_id);
    730      0    stevel }
    731      0    stevel 
    732      0    stevel projid_t
    733      0    stevel crgetprojid(const cred_t *cr)
    734      0    stevel {
    735      0    stevel 	return (cr->cr_projid);
    736   1676       jpk }
    737   1676       jpk 
    738   1676       jpk zone_t *
    739   1676       jpk crgetzone(const cred_t *cr)
    740   1676       jpk {
    741   1676       jpk 	return (cr->cr_zone);
    742   1676       jpk }
    743   1676       jpk 
    744   1676       jpk struct ts_label_s *
    745   1676       jpk crgetlabel(const cred_t *cr)
    746   1676       jpk {
    747   1676       jpk 	return (cr->cr_label ?
    748   1676       jpk 	    cr->cr_label :
    749   1676       jpk 	    (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL));
    750   1676       jpk }
    751   1676       jpk 
    752   1676       jpk boolean_t
    753   1676       jpk crisremote(const cred_t *cr)
    754   1676       jpk {
    755   1676       jpk 	return (REMOTE_PEER_CRED(cr));
    756      0    stevel }
    757      0    stevel 
    758   5771  jp151216 #define	BADUID(x, zn)	((x) != -1 && !VALID_UID((x), (zn)))
    759   5771  jp151216 #define	BADGID(x, zn)	((x) != -1 && !VALID_GID((x), (zn)))
    760      0    stevel 
    761      0    stevel int
    762      0    stevel crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s)
    763      0    stevel {
    764   5771  jp151216 	zone_t	*zone = crgetzone(cr);
    765   5771  jp151216 
    766      0    stevel 	ASSERT(cr->cr_ref <= 2);
    767      0    stevel 
    768   5771  jp151216 	if (BADUID(r, zone) || BADUID(e, zone) || BADUID(s, zone))
    769      0    stevel 		return (-1);
    770      0    stevel 
    771      0    stevel 	if (r != -1)
    772      0    stevel 		cr->cr_ruid = r;
    773      0    stevel 	if (e != -1)
    774      0    stevel 		cr->cr_uid = e;
    775      0    stevel 	if (s != -1)
    776      0    stevel 		cr->cr_suid = s;
    777      0    stevel 
    778      0    stevel 	return (0);
    779      0    stevel }
    780      0    stevel 
    781      0    stevel int
    782      0    stevel crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s)
    783      0    stevel {
    784   5771  jp151216 	zone_t	*zone = crgetzone(cr);
    785   5771  jp151216 
    786      0    stevel 	ASSERT(cr->cr_ref <= 2);
    787      0    stevel 
    788   5771  jp151216 	if (BADGID(r, zone) || BADGID(e, zone) || BADGID(s, zone))
    789      0    stevel 		return (-1);
    790      0    stevel 
    791      0    stevel 	if (r != -1)
    792      0    stevel 		cr->cr_rgid = r;
    793      0    stevel 	if (e != -1)
    794      0    stevel 		cr->cr_gid = e;
    795      0    stevel 	if (s != -1)
    796      0    stevel 		cr->cr_sgid = s;
    797      0    stevel 
    798      0    stevel 	return (0);
    799      0    stevel }
    800      0    stevel 
    801      0    stevel int
    802      0    stevel crsetugid(cred_t *cr, uid_t uid, gid_t gid)
    803      0    stevel {
    804   5771  jp151216 	zone_t	*zone = crgetzone(cr);
    805   5771  jp151216 
    806      0    stevel 	ASSERT(cr->cr_ref <= 2);
    807      0    stevel 
    808   5771  jp151216 	if (!VALID_UID(uid, zone) || !VALID_GID(gid, zone))
    809      0    stevel 		return (-1);
    810      0    stevel 
    811      0    stevel 	cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid;
    812      0    stevel 	cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid;
    813      0    stevel 
    814      0    stevel 	return (0);
    815      0    stevel }
    816      0    stevel 
    817  11134    Casper static int
    818  11134    Casper gidcmp(const void *v1, const void *v2)
    819  11134    Casper {
    820  11134    Casper 	gid_t g1 = *(gid_t *)v1;
    821  11134    Casper 	gid_t g2 = *(gid_t *)v2;
    822  11134    Casper 
    823  11134    Casper 	if (g1 < g2)
    824  11134    Casper 		return (-1);
    825  11134    Casper 	else if (g1 > g2)
    826  11134    Casper 		return (1);
    827  11134    Casper 	else
    828  11134    Casper 		return (0);
    829  11134    Casper }
    830  11134    Casper 
    831      0    stevel int
    832      0    stevel crsetgroups(cred_t *cr, int n, gid_t *grp)
    833      0    stevel {
    834      0    stevel 	ASSERT(cr->cr_ref <= 2);
    835      0    stevel 
    836      0    stevel 	if (n > ngroups_max || n < 0)
    837      0    stevel 		return (-1);
    838      0    stevel 
    839  11134    Casper 	if (cr->cr_grps != NULL)
    840  11134    Casper 		crgrprele(cr->cr_grps);
    841      0    stevel 
    842  11134    Casper 	if (n > 0) {
    843  11134    Casper 		cr->cr_grps = kmem_alloc(CREDGRPSZ(n), KM_SLEEP);
    844  11134    Casper 		bcopy(grp, cr->cr_grps->crg_groups, n * sizeof (gid_t));
    845  11134    Casper 		cr->cr_grps->crg_ref = 1;
    846  11134    Casper 		cr->cr_grps->crg_ngroups = n;
    847  11134    Casper 		qsort(cr->cr_grps->crg_groups, n, sizeof (gid_t), gidcmp);
    848  11134    Casper 	} else {
    849  11134    Casper 		cr->cr_grps = NULL;
    850  11134    Casper 	}
    851      0    stevel 
    852      0    stevel 	return (0);
    853      0    stevel }
    854      0    stevel 
    855      0    stevel void
    856      0    stevel crsetprojid(cred_t *cr, projid_t projid)
    857      0    stevel {
    858      0    stevel 	ASSERT(projid >= 0 && projid <= MAXPROJID);
    859      0    stevel 	cr->cr_projid = projid;
    860      0    stevel }
    861      0    stevel 
    862      0    stevel /*
    863  11134    Casper  * This routine returns the pointer to the first element of the crg_groups
    864      0    stevel  * array.  It can move around in an implementation defined way.
    865  11134    Casper  * Note that when we have no grouplist, we return one element but the
    866  11134    Casper  * caller should never reference it.
    867      0    stevel  */
    868      0    stevel const gid_t *
    869      0    stevel crgetgroups(const cred_t *cr)
    870      0    stevel {
    871  11134    Casper 	return (cr->cr_grps == NULL ? &cr->cr_gid : cr->cr_grps->crg_groups);
    872      0    stevel }
    873      0    stevel 
    874      0    stevel int
    875      0    stevel crgetngroups(const cred_t *cr)
    876      0    stevel {
    877  11134    Casper 	return (cr->cr_grps == NULL ? 0 : cr->cr_grps->crg_ngroups);
    878      0    stevel }
    879      0    stevel 
    880      0    stevel void
    881      0    stevel cred2prcred(const cred_t *cr, prcred_t *pcrp)
    882      0    stevel {
    883      0    stevel 	pcrp->pr_euid = cr->cr_uid;
    884      0    stevel 	pcrp->pr_ruid = cr->cr_ruid;
    885      0    stevel 	pcrp->pr_suid = cr->cr_suid;
    886      0    stevel 	pcrp->pr_egid = cr->cr_gid;
    887      0    stevel 	pcrp->pr_rgid = cr->cr_rgid;
    888      0    stevel 	pcrp->pr_sgid = cr->cr_sgid;
    889  11134    Casper 	pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */
    890  11134    Casper 	pcrp->pr_ngroups = cr->cr_grps == NULL ? 0 : cr->cr_grps->crg_ngroups;
    891      0    stevel 
    892      0    stevel 	if (pcrp->pr_ngroups != 0)
    893  11134    Casper 		bcopy(cr->cr_grps->crg_groups, pcrp->pr_groups,
    894  11134    Casper 		    sizeof (gid_t) * pcrp->pr_ngroups);
    895      0    stevel }
    896      0    stevel 
    897      0    stevel static int
    898   1676       jpk cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr)
    899      0    stevel {
    900      0    stevel 	auditinfo_addr_t	*ai;
    901      0    stevel 	au_tid_addr_t	tid;
    902      0    stevel 
    903   1676       jpk 	if (secpolicy_audit_getattr(rcr) != 0)
    904      0    stevel 		return (-1);
    905      0    stevel 
    906      0    stevel 	ai = CR_AUINFO(cr);	/* caller makes sure this is non-NULL */
    907      0    stevel 	tid = ai->ai_termid;
    908      0    stevel 
    909      0    stevel 	ainfo->ai_auid = ai->ai_auid;
    910      0    stevel 	ainfo->ai_mask = ai->ai_mask;
    911      0    stevel 	ainfo->ai_asid = ai->ai_asid;
    912      0    stevel 
    913      0    stevel 	ainfo->ai_termid.at_type = tid.at_type;
    914      0    stevel 	bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t));
    915      0    stevel 
    916      0    stevel 	ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port);
    917      0    stevel 	ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port);
    918      0    stevel 
    919      0    stevel 	return (0);
    920      0    stevel }
    921      0    stevel 
    922   1676       jpk void
    923   1676       jpk cred2uclabel(const cred_t *cr, bslabel_t *labelp)
    924   1676       jpk {
    925   1676       jpk 	ts_label_t	*tslp;
    926   1676       jpk 
    927   1676       jpk 	if ((tslp = crgetlabel(cr)) != NULL)
    928   1676       jpk 		bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t));
    929   1676       jpk }
    930   1676       jpk 
    931      0    stevel /*
    932      0    stevel  * Convert a credential into a "ucred".  Allow the caller to specify
    933      0    stevel  * and aligned buffer, e.g., in an mblk, so we don't have to allocate
    934      0    stevel  * memory and copy it twice.
    935   1676       jpk  *
    936   1676       jpk  * This function may call cred2ucaud(), which calls CRED(). Since this
    937   1676       jpk  * can be called from an interrupt thread, receiver's cred (rcr) is needed
    938   1676       jpk  * to determine whether audit info should be included.
    939      0    stevel  */
    940      0    stevel struct ucred_s *
    941   1676       jpk cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr)
    942      0    stevel {
    943      0    stevel 	struct ucred_s *uc;
    944  11134    Casper 	uint32_t realsz = ucredminsize(cr);
    945  11134    Casper 	ts_label_t *tslp = is_system_labeled() ? crgetlabel(cr) : NULL;
    946      0    stevel 
    947      0    stevel 	/* The structure isn't always completely filled in, so zero it */
    948      0    stevel 	if (buf == NULL) {
    949  11134    Casper 		uc = kmem_zalloc(realsz, KM_SLEEP);
    950      0    stevel 	} else {
    951  11134    Casper 		bzero(buf, realsz);
    952      0    stevel 		uc = buf;
    953      0    stevel 	}
    954  11134    Casper 	uc->uc_size = realsz;
    955      0    stevel 	uc->uc_pid = pid;
    956      0    stevel 	uc->uc_projid = cr->cr_projid;
    957      0    stevel 	uc->uc_zoneid = crgetzoneid(cr);
    958      0    stevel 
    959   1676       jpk 	if (REMOTE_PEER_CRED(cr)) {
    960   1676       jpk 		/*
    961  11134    Casper 		 * Other than label, the rest of cred info about a
    962  11134    Casper 		 * remote peer isn't available. Copy the label directly
    963  11134    Casper 		 * after the header where we generally copy the prcred.
    964  11134    Casper 		 * That's why we use sizeof (struct ucred_s).  The other
    965  11134    Casper 		 * offset fields are initialized to 0.
    966   1676       jpk 		 */
    967  11134    Casper 		uc->uc_labeloff = tslp == NULL ? 0 : sizeof (struct ucred_s);
    968   1676       jpk 	} else {
    969  11134    Casper 		uc->uc_credoff = UCRED_CRED_OFF;
    970  11134    Casper 		uc->uc_privoff = UCRED_PRIV_OFF;
    971  11134    Casper 		uc->uc_audoff = UCRED_AUD_OFF;
    972  11134    Casper 		uc->uc_labeloff = tslp == NULL ? 0 : UCRED_LABEL_OFF;
    973  11134    Casper 
    974   1676       jpk 		cred2prcred(cr, UCCRED(uc));
    975   1676       jpk 		cred2prpriv(cr, UCPRIV(uc));
    976  11134    Casper 
    977   1676       jpk 		if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0)
    978   1676       jpk 			uc->uc_audoff = 0;
    979  11134    Casper 	}
    980  11134    Casper 	if (tslp != NULL)
    981  11134    Casper 		bcopy(&tslp->tsl_label, UCLABEL(uc), sizeof (bslabel_t));
    982  11134    Casper 
    983  11134    Casper 	return (uc);
    984  11134    Casper }
    985  11134    Casper 
    986  11134    Casper /*
    987  11134    Casper  * Don't allocate the non-needed group entries.  Note: this function
    988  11134    Casper  * must match the code in cred2ucred; they must agree about the
    989  11134    Casper  * minimal size of the ucred.
    990  11134    Casper  */
    991  11134    Casper uint32_t
    992  11134    Casper ucredminsize(const cred_t *cr)
    993  11134    Casper {
    994  11134    Casper 	int ndiff;
    995  11134    Casper 
    996  11134    Casper 	if (cr == NULL)
    997  11134    Casper 		return (ucredsize);
    998  11134    Casper 
    999  11134    Casper 	if (REMOTE_PEER_CRED(cr)) {
   1000  11134    Casper 		if (is_system_labeled())
   1001  11134    Casper 			return (sizeof (struct ucred_s) + sizeof (bslabel_t));
   1002  11134    Casper 		else
   1003  11134    Casper 			return (sizeof (struct ucred_s));
   1004   1676       jpk 	}
   1005      0    stevel 
   1006  11134    Casper 	if (cr->cr_grps == NULL)
   1007  11134    Casper 		ndiff = ngroups_max - 1;	/* Needs one for prcred_t */
   1008  11134    Casper 	else
   1009  11134    Casper 		ndiff = ngroups_max - cr->cr_grps->crg_ngroups;
   1010  11134    Casper 
   1011  11134    Casper 	return (ucredsize - ndiff * sizeof (gid_t));
   1012      0    stevel }
   1013      0    stevel 
   1014      0    stevel /*
   1015      0    stevel  * Get the "ucred" of a process.
   1016      0    stevel  */
   1017      0    stevel struct ucred_s *
   1018      0    stevel pgetucred(proc_t *p)
   1019      0    stevel {
   1020      0    stevel 	cred_t *cr;
   1021      0    stevel 	struct ucred_s *uc;
   1022      0    stevel 
   1023      0    stevel 	mutex_enter(&p->p_crlock);
   1024      0    stevel 	cr = p->p_cred;
   1025      0    stevel 	crhold(cr);
   1026      0    stevel 	mutex_exit(&p->p_crlock);
   1027      0    stevel 
   1028   1676       jpk 	uc = cred2ucred(cr, p->p_pid, NULL, CRED());
   1029      0    stevel 	crfree(cr);
   1030      0    stevel 
   1031      0    stevel 	return (uc);
   1032      0    stevel }
   1033      0    stevel 
   1034      0    stevel /*
   1035      0    stevel  * If the reply status is NFSERR_EACCES, it may be because we are
   1036      0    stevel  * root (no root net access).  Check the real uid, if it isn't root
   1037      0    stevel  * make that the uid instead and retry the call.
   1038      0    stevel  * Private interface for NFS.
   1039      0    stevel  */
   1040      0    stevel cred_t *
   1041      0    stevel crnetadjust(cred_t *cr)
   1042      0    stevel {
   1043      0    stevel 	if (cr->cr_uid == 0 && cr->cr_ruid != 0) {
   1044      0    stevel 		cr = crdup(cr);
   1045      0    stevel 		cr->cr_uid = cr->cr_ruid;
   1046      0    stevel 		return (cr);
   1047      0    stevel 	}
   1048      0    stevel 	return (NULL);
   1049      0    stevel }
   1050      0    stevel 
   1051      0    stevel /*
   1052      0    stevel  * The reference count is of interest when you want to check
   1053      0    stevel  * whether it is ok to modify the credential in place.
   1054      0    stevel  */
   1055      0    stevel uint_t
   1056      0    stevel crgetref(const cred_t *cr)
   1057      0    stevel {
   1058      0    stevel 	return (cr->cr_ref);
   1059      0    stevel }
   1060      0    stevel 
   1061      0    stevel static int
   1062      0    stevel get_c2audit_load(void)
   1063      0    stevel {
   1064      0    stevel 	static int	gotit = 0;
   1065      0    stevel 	static int	c2audit_load;
   1066      0    stevel 	u_longlong_t	audit_load_val;
   1067      0    stevel 
   1068      0    stevel 	if (gotit)
   1069      0    stevel 		return (c2audit_load);
   1070      0    stevel 	audit_load_val = 0;		/* set default value once */
   1071      0    stevel 	(void) mod_sysvar("c2audit", "audit_load", &audit_load_val);
   1072      0    stevel 	c2audit_load = (int)audit_load_val;
   1073      0    stevel 	gotit++;
   1074      0    stevel 	return (c2audit_load);
   1075      0    stevel }
   1076      0    stevel 
   1077      0    stevel int
   1078      0    stevel get_audit_ucrsize(void)
   1079      0    stevel {
   1080      0    stevel 	return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0);
   1081      0    stevel }
   1082      0    stevel 
   1083      0    stevel /*
   1084      0    stevel  * Set zone pointer in credential to indicated value.  First adds a
   1085      0    stevel  * hold for the new zone, then drops the hold on previous zone (if any).
   1086      0    stevel  * This is done in this order in case the old and new zones are the
   1087      0    stevel  * same.
   1088      0    stevel  */
   1089      0    stevel void
   1090      0    stevel crsetzone(cred_t *cr, zone_t *zptr)
   1091      0    stevel {
   1092      0    stevel 	zone_t *oldzptr = cr->cr_zone;
   1093      0    stevel 
   1094      0    stevel 	ASSERT(cr != kcred);
   1095      0    stevel 	ASSERT(cr->cr_ref <= 2);
   1096      0    stevel 	cr->cr_zone = zptr;
   1097      0    stevel 	zone_cred_hold(zptr);
   1098      0    stevel 	if (oldzptr)
   1099      0    stevel 		zone_cred_rele(oldzptr);
   1100      0    stevel }
   1101   1676       jpk 
   1102   1676       jpk /*
   1103   1676       jpk  * Create a new cred based on the supplied label
   1104   1676       jpk  */
   1105   1676       jpk cred_t *
   1106   1676       jpk newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags)
   1107   1676       jpk {
   1108   1676       jpk 	ts_label_t *lbl = labelalloc(blabel, doi, flags);
   1109   1676       jpk 	cred_t *cr = NULL;
   1110   1676       jpk 
   1111   1676       jpk 	if (lbl != NULL) {
   1112   6134    casper 		if ((cr = crdup_flags(dummycr, flags)) != NULL) {
   1113   1676       jpk 			cr->cr_label = lbl;
   1114   1676       jpk 		} else {
   1115   1676       jpk 			label_rele(lbl);
   1116   1676       jpk 		}
   1117   1676       jpk 	}
   1118   1676       jpk 
   1119   1676       jpk 	return (cr);
   1120   1676       jpk }
   1121   1676       jpk 
   1122   1676       jpk /*
   1123   1676       jpk  * Derive a new cred from the existing cred, but with a different label.
   1124   1676       jpk  * To be used when a cred is being shared, but the label needs to be changed
   1125   1676       jpk  * by a caller without affecting other users
   1126   1676       jpk  */
   1127   1676       jpk cred_t *
   1128   9710       Ken copycred_from_tslabel(const cred_t *cr, ts_label_t *label, int flags)
   1129   9710       Ken {
   1130   9710       Ken 	cred_t *newcr = NULL;
   1131   9710       Ken 
   1132   9710       Ken 	if ((newcr = crdup_flags(cr, flags)) != NULL) {
   1133   9710       Ken 		if (newcr->cr_label != NULL)
   1134   9710       Ken 			label_rele(newcr->cr_label);
   1135   9710       Ken 		label_hold(label);
   1136   9710       Ken 		newcr->cr_label = label;
   1137   9710       Ken 	}
   1138   9710       Ken 
   1139   9710       Ken 	return (newcr);
   1140   9710       Ken }
   1141   9710       Ken 
   1142   9710       Ken /*
   1143   9710       Ken  * Derive a new cred from the existing cred, but with a different label.
   1144   9710       Ken  */
   1145   9710       Ken cred_t *
   1146   9710       Ken copycred_from_bslabel(const cred_t *cr, bslabel_t *blabel,
   1147   9710       Ken     uint32_t doi, int flags)
   1148   1676       jpk {
   1149   1676       jpk 	ts_label_t *lbl = labelalloc(blabel, doi, flags);
   1150   9710       Ken 	cred_t  *newcr = NULL;
   1151   1676       jpk 
   1152   1676       jpk 	if (lbl != NULL) {
   1153   9710       Ken 		newcr = copycred_from_tslabel(cr, lbl, flags);
   1154   9710       Ken 		label_rele(lbl);
   1155   1676       jpk 	}
   1156   1676       jpk 
   1157   1676       jpk 	return (newcr);
   1158   1676       jpk }
   1159   1676       jpk 
   1160   1676       jpk /*
   1161   1676       jpk  * This function returns a pointer to the kcred-equivalent in the current zone.
   1162   1676       jpk  */
   1163   1676       jpk cred_t *
   1164   1676       jpk zone_kcred(void)
   1165   1676       jpk {
   1166   1676       jpk 	zone_t *zone;
   1167   1676       jpk 
   1168   1676       jpk 	if ((zone = CRED()->cr_zone) != NULL)
   1169   1676       jpk 		return (zone->zone_kcred);
   1170   1676       jpk 	else
   1171   1676       jpk 		return (kcred);
   1172   1676       jpk }
   1173   4321    casper 
   1174   4321    casper boolean_t
   1175   5771  jp151216 valid_ephemeral_uid(zone_t *zone, uid_t id)
   1176   4321    casper {
   1177   5771  jp151216 	ephemeral_zsd_t *eph_zsd;
   1178   5908  jp151216 	if (id <= IDMAP_WK__MAX_UID)
   1179   5771  jp151216 		return (B_TRUE);
   1180   5771  jp151216 
   1181   5771  jp151216 	eph_zsd = get_ephemeral_zsd(zone);
   1182   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1183   4321    casper 	membar_consumer();
   1184   5771  jp151216 	return (id > eph_zsd->min_uid && id <= eph_zsd->last_uid);
   1185   4321    casper }
   1186   4321    casper 
   1187   4321    casper boolean_t
   1188   5771  jp151216 valid_ephemeral_gid(zone_t *zone, gid_t id)
   1189   4321    casper {
   1190   5771  jp151216 	ephemeral_zsd_t *eph_zsd;
   1191   5908  jp151216 	if (id <= IDMAP_WK__MAX_GID)
   1192   5771  jp151216 		return (B_TRUE);
   1193   5771  jp151216 
   1194   5771  jp151216 	eph_zsd = get_ephemeral_zsd(zone);
   1195   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1196   4321    casper 	membar_consumer();
   1197   5771  jp151216 	return (id > eph_zsd->min_gid && id <= eph_zsd->last_gid);
   1198   4321    casper }
   1199   4321    casper 
   1200   4321    casper int
   1201   5771  jp151216 eph_uid_alloc(zone_t *zone, int flags, uid_t *start, int count)
   1202   4321    casper {
   1203   5771  jp151216 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
   1204   5771  jp151216 
   1205   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1206   5771  jp151216 
   1207   5771  jp151216 	mutex_enter(&eph_zsd->eph_lock);
   1208   4321    casper 
   1209   4321    casper 	/* Test for unsigned integer wrap around */
   1210   5771  jp151216 	if (eph_zsd->last_uid + count < eph_zsd->last_uid) {
   1211   5771  jp151216 		mutex_exit(&eph_zsd->eph_lock);
   1212   4321    casper 		return (-1);
   1213   4321    casper 	}
   1214   4321    casper 
   1215   4321    casper 	/* first call or idmap crashed and state corrupted */
   1216   4321    casper 	if (flags != 0)
   1217   5771  jp151216 		eph_zsd->min_uid = eph_zsd->last_uid;
   1218   4321    casper 
   1219   4321    casper 	hasephids = B_TRUE;
   1220   5771  jp151216 	*start = eph_zsd->last_uid + 1;
   1221   5771  jp151216 	atomic_add_32(&eph_zsd->last_uid, count);
   1222   5771  jp151216 	mutex_exit(&eph_zsd->eph_lock);
   1223   4321    casper 	return (0);
   1224   4321    casper }
   1225   4321    casper 
   1226   4321    casper int
   1227   5771  jp151216 eph_gid_alloc(zone_t *zone, int flags, gid_t *start, int count)
   1228   4321    casper {
   1229   5771  jp151216 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
   1230   5771  jp151216 
   1231   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1232   5771  jp151216 
   1233   5771  jp151216 	mutex_enter(&eph_zsd->eph_lock);
   1234   4321    casper 
   1235   4321    casper 	/* Test for unsigned integer wrap around */
   1236   5771  jp151216 	if (eph_zsd->last_gid + count < eph_zsd->last_gid) {
   1237   5771  jp151216 		mutex_exit(&eph_zsd->eph_lock);
   1238   4321    casper 		return (-1);
   1239   4321    casper 	}
   1240   4321    casper 
   1241   4321    casper 	/* first call or idmap crashed and state corrupted */
   1242   4321    casper 	if (flags != 0)
   1243   5771  jp151216 		eph_zsd->min_gid = eph_zsd->last_gid;
   1244   4321    casper 
   1245   4321    casper 	hasephids = B_TRUE;
   1246   5771  jp151216 	*start = eph_zsd->last_gid + 1;
   1247   5771  jp151216 	atomic_add_32(&eph_zsd->last_gid, count);
   1248   5771  jp151216 	mutex_exit(&eph_zsd->eph_lock);
   1249   4321    casper 	return (0);
   1250   5771  jp151216 }
   1251   5771  jp151216 
   1252   5771  jp151216 /*
   1253   5771  jp151216  * IMPORTANT.The two functions get_ephemeral_data() and set_ephemeral_data()
   1254   5771  jp151216  * are project private functions that are for use of the test system only and
   1255   5771  jp151216  * are not to be used for other purposes.
   1256   5771  jp151216  */
   1257   5771  jp151216 
   1258   5771  jp151216 void
   1259   5771  jp151216 get_ephemeral_data(zone_t *zone, uid_t *min_uid, uid_t *last_uid,
   1260   5771  jp151216 	gid_t *min_gid, gid_t *last_gid)
   1261   5771  jp151216 {
   1262   5771  jp151216 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
   1263   5771  jp151216 
   1264   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1265   5771  jp151216 
   1266   5771  jp151216 	mutex_enter(&eph_zsd->eph_lock);
   1267   5771  jp151216 
   1268   5771  jp151216 	*min_uid = eph_zsd->min_uid;
   1269   5771  jp151216 	*last_uid = eph_zsd->last_uid;
   1270   5771  jp151216 	*min_gid = eph_zsd->min_gid;
   1271   5771  jp151216 	*last_gid = eph_zsd->last_gid;
   1272   5771  jp151216 
   1273   5771  jp151216 	mutex_exit(&eph_zsd->eph_lock);
   1274   5771  jp151216 }
   1275   5771  jp151216 
   1276   5771  jp151216 
   1277   5771  jp151216 void
   1278   5771  jp151216 set_ephemeral_data(zone_t *zone, uid_t min_uid, uid_t last_uid,
   1279   5771  jp151216 	gid_t min_gid, gid_t last_gid)
   1280   5771  jp151216 {
   1281   5771  jp151216 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
   1282   5771  jp151216 
   1283   5771  jp151216 	ASSERT(eph_zsd != NULL);
   1284   5771  jp151216 
   1285   5771  jp151216 	mutex_enter(&eph_zsd->eph_lock);
   1286   5771  jp151216 
   1287   5771  jp151216 	if (min_uid != 0)
   1288   5771  jp151216 		eph_zsd->min_uid = min_uid;
   1289   5771  jp151216 	if (last_uid != 0)
   1290   5771  jp151216 		eph_zsd->last_uid = last_uid;
   1291   5771  jp151216 	if (min_gid != 0)
   1292   5771  jp151216 		eph_zsd->min_gid = min_gid;
   1293   5771  jp151216 	if (last_gid != 0)
   1294   5771  jp151216 		eph_zsd->last_gid = last_gid;
   1295   5771  jp151216 
   1296   5771  jp151216 	mutex_exit(&eph_zsd->eph_lock);
   1297   4321    casper }
   1298   4321    casper 
   1299   4321    casper /*
   1300   5331       amw  * If the credential user SID or group SID is mapped to an ephemeral
   1301   5331       amw  * ID, map the credential to nobody.
   1302   4321    casper  */
   1303   4321    casper cred_t *
   1304   4321    casper crgetmapped(const cred_t *cr)
   1305   4321    casper {
   1306   5771  jp151216 	ephemeral_zsd_t *eph_zsd;
   1307   4406    casper 	/*
   1308   4406    casper 	 * Someone incorrectly passed a NULL cred to a vnode operation
   1309   4406    casper 	 * either on purpose or by calling CRED() in interrupt context.
   1310   4406    casper 	 */
   1311   4406    casper 	if (cr == NULL)
   1312   4406    casper 		return (NULL);
   1313   4406    casper 
   1314   4321    casper 	if (cr->cr_ksid != NULL) {
   1315   5771  jp151216 		if (cr->cr_ksid->kr_sidx[KSID_USER].ks_id > MAXUID) {
   1316   5771  jp151216 			eph_zsd = get_ephemeral_zsd(crgetzone(cr));
   1317   5771  jp151216 			return (eph_zsd->eph_nobody);
   1318   5771  jp151216 		}
   1319   4321    casper 
   1320   5771  jp151216 		if (cr->cr_ksid->kr_sidx[KSID_GROUP].ks_id > MAXUID) {
   1321   5771  jp151216 			eph_zsd = get_ephemeral_zsd(crgetzone(cr));
   1322   5771  jp151216 			return (eph_zsd->eph_nobody);
   1323   5771  jp151216 		}
   1324   4321    casper 	}
   1325   4321    casper 
   1326   4321    casper 	return ((cred_t *)cr);
   1327   4321    casper }
   1328   4321    casper 
   1329   4321    casper /* index should be in range for a ksidindex_t */
   1330   4321    casper void
   1331   4321    casper crsetsid(cred_t *cr, ksid_t *ksp, int index)
   1332   4321    casper {
   1333   4321    casper 	ASSERT(cr->cr_ref <= 2);
   1334   4321    casper 	ASSERT(index >= 0 && index < KSID_COUNT);
   1335   4321    casper 	if (cr->cr_ksid == NULL && ksp == NULL)
   1336   4321    casper 		return;
   1337   4321    casper 	cr->cr_ksid = kcrsid_setsid(cr->cr_ksid, ksp, index);
   1338   4321    casper }
   1339   4321    casper 
   1340   4321    casper void
   1341   4321    casper crsetsidlist(cred_t *cr, ksidlist_t *ksl)
   1342   4321    casper {
   1343   4321    casper 	ASSERT(cr->cr_ref <= 2);
   1344   4321    casper 	if (cr->cr_ksid == NULL && ksl == NULL)
   1345   4321    casper 		return;
   1346   4321    casper 	cr->cr_ksid = kcrsid_setsidlist(cr->cr_ksid, ksl);
   1347   4321    casper }
   1348   4321    casper 
   1349   4321    casper ksid_t *
   1350   4321    casper crgetsid(const cred_t *cr, int i)
   1351   4321    casper {
   1352   4321    casper 	ASSERT(i >= 0 && i < KSID_COUNT);
   1353   4321    casper 	if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidx[i].ks_domain)
   1354   4321    casper 		return ((ksid_t *)&cr->cr_ksid->kr_sidx[i]);
   1355   4321    casper 	return (NULL);
   1356   4321    casper }
   1357   4321    casper 
   1358   4321    casper ksidlist_t *
   1359   4321    casper crgetsidlist(const cred_t *cr)
   1360   4321    casper {
   1361   5331       amw 	if (cr->cr_ksid != NULL)
   1362   4923    casper 		return (cr->cr_ksid->kr_sidlist);
   1363   4321    casper 	return (NULL);
   1364   4321    casper }
   1365   5331       amw 
   1366   5331       amw /*
   1367   5331       amw  * Interface to set the effective and permitted privileges for
   1368   5331       amw  * a credential; this interface does no security checks and is
   1369   5331       amw  * intended for kernel (file)servers creating credentials with
   1370   5331       amw  * specific privileges.
   1371   5331       amw  */
   1372   5331       amw int
   1373   5331       amw crsetpriv(cred_t *cr, ...)
   1374   5331       amw {
   1375   5331       amw 	va_list ap;
   1376   5331       amw 	const char *privnm;
   1377   5331       amw 
   1378   5331       amw 	ASSERT(cr->cr_ref <= 2);
   1379   5331       amw 
   1380   5331       amw 	priv_set_PA(cr);
   1381   5331       amw 
   1382   5331       amw 	va_start(ap, cr);
   1383   5331       amw 
   1384   5331       amw 	while ((privnm = va_arg(ap, const char *)) != NULL) {
   1385   5331       amw 		int priv = priv_getbyname(privnm, 0);
   1386   5331       amw 		if (priv < 0)
   1387   5331       amw 			return (-1);
   1388   5331       amw 
   1389   5331       amw 		priv_addset(&CR_PPRIV(cr), priv);
   1390   5331       amw 		priv_addset(&CR_EPRIV(cr), priv);
   1391   5331       amw 	}
   1392   5331       amw 	priv_adjust_PA(cr);
   1393   5331       amw 	va_end(ap);
   1394   5331       amw 	return (0);
   1395   5331       amw }
   1396   6134    casper 
   1397   9151    Thomas /*
   1398   9151    Thomas  * Interface to effectively set the PRIV_ALL for
   1399   9151    Thomas  * a credential; this interface does no security checks and is
   1400   9151    Thomas  * intended for kernel (file)servers to extend the user credentials
   1401   9151    Thomas  * to be ALL, like either kcred or zcred.
   1402   9151    Thomas  */
   1403   9151    Thomas void
   1404   9151    Thomas crset_zone_privall(cred_t *cr)
   1405   9151    Thomas {
   1406   9151    Thomas 	zone_t	*zone = crgetzone(cr);
   1407   9151    Thomas 
   1408   9151    Thomas 	priv_fillset(&CR_LPRIV(cr));
   1409   9151    Thomas 	CR_EPRIV(cr) = CR_PPRIV(cr) = CR_IPRIV(cr) = CR_LPRIV(cr);
   1410   9151    Thomas 	priv_intersect(zone->zone_privset, &CR_LPRIV(cr));
   1411   9151    Thomas 	priv_intersect(zone->zone_privset, &CR_EPRIV(cr));
   1412   9151    Thomas 	priv_intersect(zone->zone_privset, &CR_IPRIV(cr));
   1413   9151    Thomas 	priv_intersect(zone->zone_privset, &CR_PPRIV(cr));
   1414   9151    Thomas }
   1415   9151    Thomas 
   1416   6134    casper struct credklpd *
   1417   6134    casper crgetcrklpd(const cred_t *cr)
   1418   6134    casper {
   1419   6134    casper 	return (cr->cr_klpd);
   1420   6134    casper }
   1421   6134    casper 
   1422   6134    casper void
   1423   6134    casper crsetcrklpd(cred_t *cr, struct credklpd *crklpd)
   1424   6134    casper {
   1425   6134    casper 	ASSERT(cr->cr_ref <= 2);
   1426   6134    casper 
   1427   6134    casper 	if (cr->cr_klpd != NULL)
   1428   6134    casper 		crklpd_rele(cr->cr_klpd);
   1429   6134    casper 	cr->cr_klpd = crklpd;
   1430   6134    casper }
   1431  11134    Casper 
   1432  11134    Casper credgrp_t *
   1433  11134    Casper crgrpcopyin(int n, gid_t *gidset)
   1434  11134    Casper {
   1435  11134    Casper 	credgrp_t *mem;
   1436  11134    Casper 	size_t sz = CREDGRPSZ(n);
   1437  11134    Casper 
   1438  11134    Casper 	ASSERT(n > 0);
   1439  11134    Casper 
   1440  11134    Casper 	mem = kmem_alloc(sz, KM_SLEEP);
   1441  11134    Casper 
   1442  11134    Casper 	if (copyin(gidset, mem->crg_groups, sizeof (gid_t) * n)) {
   1443  11134    Casper 		kmem_free(mem, sz);
   1444  11134    Casper 		return (NULL);
   1445  11134    Casper 	}
   1446  11134    Casper 	mem->crg_ref = 1;
   1447  11134    Casper 	mem->crg_ngroups = n;
   1448  11134    Casper 	return (mem);
   1449  11134    Casper }
   1450  11134    Casper 
   1451  11134    Casper const gid_t *
   1452  11134    Casper crgetggroups(const credgrp_t *grps)
   1453  11134    Casper {
   1454  11134    Casper 	return (grps->crg_groups);
   1455  11134    Casper }
   1456  11134    Casper 
   1457  11134    Casper void
   1458  11134    Casper crsetcredgrp(cred_t *cr, credgrp_t *grps)
   1459  11134    Casper {
   1460  11134    Casper 	ASSERT(cr->cr_ref <= 2);
   1461  11134    Casper 
   1462  11134    Casper 	if (cr->cr_grps != NULL)
   1463  11134    Casper 		crgrprele(cr->cr_grps);
   1464  11134    Casper 
   1465  11134    Casper 	cr->cr_grps = grps;
   1466  11134    Casper }
   1467  11134    Casper 
   1468  11134    Casper void
   1469  11134    Casper crgrprele(credgrp_t *grps)
   1470  11134    Casper {
   1471  11134    Casper 	if (atomic_add_32_nv(&grps->crg_ref, -1) == 0)
   1472  11134    Casper 		kmem_free(grps, CREDGRPSZ(grps->crg_ngroups));
   1473  11134    Casper }
   1474  11134    Casper 
   1475  11134    Casper static void
   1476  11134    Casper crgrphold(credgrp_t *grps)
   1477  11134    Casper {
   1478  11134    Casper 	atomic_add_32(&grps->crg_ref, 1);
   1479  11134    Casper }
   1480