10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1676Sjpk * Common Development and Distribution License (the "License"). 6*1676Sjpk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 270Sstevel@tonic-gate /* All Rights Reserved */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 310Sstevel@tonic-gate * The Regents of the University of California 320Sstevel@tonic-gate * All Rights Reserved 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 350Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 360Sstevel@tonic-gate * contributors. 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include <sys/types.h> 420Sstevel@tonic-gate #include <sys/sysmacros.h> 430Sstevel@tonic-gate #include <sys/param.h> 440Sstevel@tonic-gate #include <sys/systm.h> 450Sstevel@tonic-gate #include <sys/cred_impl.h> 460Sstevel@tonic-gate #include <sys/policy.h> 470Sstevel@tonic-gate #include <sys/vnode.h> 480Sstevel@tonic-gate #include <sys/errno.h> 490Sstevel@tonic-gate #include <sys/kmem.h> 500Sstevel@tonic-gate #include <sys/user.h> 510Sstevel@tonic-gate #include <sys/proc.h> 520Sstevel@tonic-gate #include <sys/syscall.h> 530Sstevel@tonic-gate #include <sys/debug.h> 540Sstevel@tonic-gate #include <sys/atomic.h> 550Sstevel@tonic-gate #include <sys/ucred.h> 560Sstevel@tonic-gate #include <sys/prsystm.h> 570Sstevel@tonic-gate #include <sys/modctl.h> 580Sstevel@tonic-gate #include <c2/audit.h> 590Sstevel@tonic-gate #include <sys/zone.h> 60*1676Sjpk #include <sys/tsol/label.h> 610Sstevel@tonic-gate 620Sstevel@tonic-gate static struct kmem_cache *cred_cache; 630Sstevel@tonic-gate static size_t crsize = 0; 640Sstevel@tonic-gate static int audoff = 0; 650Sstevel@tonic-gate uint32_t ucredsize; 660Sstevel@tonic-gate cred_t *kcred; 67*1676Sjpk static cred_t *dummycr; 680Sstevel@tonic-gate 690Sstevel@tonic-gate int rstlink; /* link(2) restricted to files owned by user? */ 700Sstevel@tonic-gate 710Sstevel@tonic-gate static int get_c2audit_load(void); 720Sstevel@tonic-gate 730Sstevel@tonic-gate #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \ 740Sstevel@tonic-gate ((char *)(c)) + audoff) 750Sstevel@tonic-gate 76*1676Sjpk #define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1) 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* 790Sstevel@tonic-gate * Initialize credentials data structures. 800Sstevel@tonic-gate */ 810Sstevel@tonic-gate 820Sstevel@tonic-gate void 830Sstevel@tonic-gate cred_init(void) 840Sstevel@tonic-gate { 850Sstevel@tonic-gate priv_init(); 860Sstevel@tonic-gate 870Sstevel@tonic-gate crsize = sizeof (cred_t) + sizeof (gid_t) * (ngroups_max - 1); 880Sstevel@tonic-gate /* 890Sstevel@tonic-gate * Make sure it's word-aligned. 900Sstevel@tonic-gate */ 910Sstevel@tonic-gate crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 920Sstevel@tonic-gate 930Sstevel@tonic-gate if (get_c2audit_load() > 0) { 940Sstevel@tonic-gate #ifdef _LP64 950Sstevel@tonic-gate /* assure audit context is 64-bit aligned */ 960Sstevel@tonic-gate audoff = (crsize + 970Sstevel@tonic-gate sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1); 980Sstevel@tonic-gate #else /* _LP64 */ 990Sstevel@tonic-gate audoff = crsize; 1000Sstevel@tonic-gate #endif /* _LP64 */ 1010Sstevel@tonic-gate crsize = audoff + sizeof (auditinfo_addr_t); 1020Sstevel@tonic-gate crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate cred_cache = kmem_cache_create("cred_cache", crsize, 0, 1060Sstevel@tonic-gate NULL, NULL, NULL, NULL, NULL, 0); 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* 109*1676Sjpk * dummycr is used to copy initial state for creds. 110*1676Sjpk */ 111*1676Sjpk dummycr = cralloc(); 112*1676Sjpk bzero(dummycr, crsize); 113*1676Sjpk dummycr->cr_ref = 1; 114*1676Sjpk dummycr->cr_uid = -1; 115*1676Sjpk dummycr->cr_gid = -1; 116*1676Sjpk dummycr->cr_ruid = -1; 117*1676Sjpk dummycr->cr_rgid = -1; 118*1676Sjpk dummycr->cr_suid = -1; 119*1676Sjpk dummycr->cr_sgid = -1; 120*1676Sjpk 121*1676Sjpk /* 1220Sstevel@tonic-gate * kcred is used by anything that needs all privileges; it's 1230Sstevel@tonic-gate * also the template used for crget as it has all the compatible 1240Sstevel@tonic-gate * sets filled in. 1250Sstevel@tonic-gate */ 1260Sstevel@tonic-gate kcred = cralloc(); 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate bzero(kcred, crsize); 1290Sstevel@tonic-gate kcred->cr_ref = 1; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* kcred is never freed, so we don't need zone_cred_hold here */ 1320Sstevel@tonic-gate kcred->cr_zone = &zone0; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate priv_fillset(&CR_LPRIV(kcred)); 1350Sstevel@tonic-gate CR_IPRIV(kcred) = *priv_basic; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate /* Not a basic privilege, if chown is not restricted add it to I0 */ 1380Sstevel@tonic-gate if (!rstchown) 1390Sstevel@tonic-gate priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* Basic privilege, if link is restricted remove it from I0 */ 1420Sstevel@tonic-gate if (rstlink) 1430Sstevel@tonic-gate priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred); 146*1676Sjpk 147*1676Sjpk CR_FLAGS(kcred) = NET_MAC_AWARE; 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * Set up credentials of p0. 1510Sstevel@tonic-gate */ 1520Sstevel@tonic-gate ttoproc(curthread)->p_cred = kcred; 1530Sstevel@tonic-gate curthread->t_cred = kcred; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate ucredsize = UCRED_SIZE; 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * Allocate (nearly) uninitialized cred_t. 1600Sstevel@tonic-gate */ 1610Sstevel@tonic-gate cred_t * 1620Sstevel@tonic-gate cralloc(void) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 1650Sstevel@tonic-gate cr->cr_ref = 1; /* So we can crfree() */ 1660Sstevel@tonic-gate cr->cr_zone = NULL; 167*1676Sjpk cr->cr_label = NULL; 1680Sstevel@tonic-gate return (cr); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * Allocate a initialized cred structure and crhold() it. 1730Sstevel@tonic-gate * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate cred_t * 1760Sstevel@tonic-gate crget(void) 1770Sstevel@tonic-gate { 1780Sstevel@tonic-gate cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 1790Sstevel@tonic-gate 1800Sstevel@tonic-gate bcopy(kcred, cr, crsize); 1810Sstevel@tonic-gate cr->cr_ref = 1; 1820Sstevel@tonic-gate zone_cred_hold(cr->cr_zone); 183*1676Sjpk if (cr->cr_label) 184*1676Sjpk label_hold(cr->cr_label); 1850Sstevel@tonic-gate return (cr); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * Broadcast the cred to all the threads in the process. 1900Sstevel@tonic-gate * The current thread's credentials can be set right away, but other 1910Sstevel@tonic-gate * threads must wait until the start of the next system call or trap. 1920Sstevel@tonic-gate * This avoids changing the cred in the middle of a system call. 1930Sstevel@tonic-gate * 1940Sstevel@tonic-gate * The cred has already been held for the process and the thread (2 holds), 1950Sstevel@tonic-gate * and p->p_cred set. 1960Sstevel@tonic-gate * 1970Sstevel@tonic-gate * p->p_crlock shouldn't be held here, since p_lock must be acquired. 1980Sstevel@tonic-gate */ 1990Sstevel@tonic-gate void 2000Sstevel@tonic-gate crset(proc_t *p, cred_t *cr) 2010Sstevel@tonic-gate { 2020Sstevel@tonic-gate kthread_id_t t; 2030Sstevel@tonic-gate kthread_id_t first; 2040Sstevel@tonic-gate cred_t *oldcr; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate ASSERT(p == curproc); /* assumes p_lwpcnt can't change */ 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate /* 2090Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred must always be 2100Sstevel@tonic-gate * either NULL, or point to a valid, allocated cred structure. 2110Sstevel@tonic-gate */ 2120Sstevel@tonic-gate t = curthread; 2130Sstevel@tonic-gate oldcr = t->t_cred; 2140Sstevel@tonic-gate t->t_cred = cr; /* the cred is held by caller for this thread */ 2150Sstevel@tonic-gate crfree(oldcr); /* free the old cred for the thread */ 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* 2180Sstevel@tonic-gate * Broadcast to other threads, if any. 2190Sstevel@tonic-gate */ 2200Sstevel@tonic-gate if (p->p_lwpcnt > 1) { 2210Sstevel@tonic-gate mutex_enter(&p->p_lock); /* to keep thread list safe */ 2220Sstevel@tonic-gate first = curthread; 2230Sstevel@tonic-gate for (t = first->t_forw; t != first; t = t->t_forw) 2240Sstevel@tonic-gate t->t_pre_sys = 1; /* so syscall will get new cred */ 2250Sstevel@tonic-gate mutex_exit(&p->p_lock); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* 2300Sstevel@tonic-gate * Put a hold on a cred structure. 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate void 2330Sstevel@tonic-gate crhold(cred_t *cr) 2340Sstevel@tonic-gate { 2350Sstevel@tonic-gate atomic_add_32(&cr->cr_ref, 1); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* 2390Sstevel@tonic-gate * Release previous hold on a cred structure. Free it if refcnt == 0. 240*1676Sjpk * If cred uses label different from zone label, free it. 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate void 2430Sstevel@tonic-gate crfree(cred_t *cr) 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) { 2460Sstevel@tonic-gate ASSERT(cr != kcred); 247*1676Sjpk if (cr->cr_label) 248*1676Sjpk label_rele(cr->cr_label); 2490Sstevel@tonic-gate if (cr->cr_zone) 2500Sstevel@tonic-gate zone_cred_rele(cr->cr_zone); 2510Sstevel@tonic-gate kmem_cache_free(cred_cache, cr); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* 2560Sstevel@tonic-gate * Copy a cred structure to a new one and free the old one. 2570Sstevel@tonic-gate * The new cred will have two references. One for the calling process, 2580Sstevel@tonic-gate * and one for the thread. 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate cred_t * 2610Sstevel@tonic-gate crcopy(cred_t *cr) 2620Sstevel@tonic-gate { 2630Sstevel@tonic-gate cred_t *newcr; 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate newcr = cralloc(); 2660Sstevel@tonic-gate bcopy(cr, newcr, crsize); 2670Sstevel@tonic-gate if (newcr->cr_zone) 2680Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 269*1676Sjpk if (newcr->cr_label) 270*1676Sjpk label_hold(cr->cr_label); 2710Sstevel@tonic-gate crfree(cr); 2720Sstevel@tonic-gate newcr->cr_ref = 2; /* caller gets two references */ 2730Sstevel@tonic-gate return (newcr); 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate /* 2770Sstevel@tonic-gate * Copy a cred structure to a new one and free the old one. 2780Sstevel@tonic-gate * The new cred will have two references. One for the calling process, 2790Sstevel@tonic-gate * and one for the thread. 2800Sstevel@tonic-gate * This variation on crcopy uses a pre-allocated structure for the 2810Sstevel@tonic-gate * "new" cred. 2820Sstevel@tonic-gate */ 2830Sstevel@tonic-gate void 2840Sstevel@tonic-gate crcopy_to(cred_t *oldcr, cred_t *newcr) 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate bcopy(oldcr, newcr, crsize); 2870Sstevel@tonic-gate if (newcr->cr_zone) 2880Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 289*1676Sjpk if (newcr->cr_label) 290*1676Sjpk label_hold(newcr->cr_label); 2910Sstevel@tonic-gate crfree(oldcr); 2920Sstevel@tonic-gate newcr->cr_ref = 2; /* caller gets two references */ 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate /* 2960Sstevel@tonic-gate * Dup a cred struct to a new held one. 2970Sstevel@tonic-gate * The old cred is not freed. 2980Sstevel@tonic-gate */ 2990Sstevel@tonic-gate cred_t * 3000Sstevel@tonic-gate crdup(cred_t *cr) 3010Sstevel@tonic-gate { 3020Sstevel@tonic-gate cred_t *newcr; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate newcr = cralloc(); 3050Sstevel@tonic-gate bcopy(cr, newcr, crsize); 3060Sstevel@tonic-gate if (newcr->cr_zone) 3070Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 308*1676Sjpk if (newcr->cr_label) 309*1676Sjpk label_hold(newcr->cr_label); 3100Sstevel@tonic-gate newcr->cr_ref = 1; 3110Sstevel@tonic-gate return (newcr); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * Dup a cred struct to a new held one. 3160Sstevel@tonic-gate * The old cred is not freed. 3170Sstevel@tonic-gate * This variation on crdup uses a pre-allocated structure for the 3180Sstevel@tonic-gate * "new" cred. 3190Sstevel@tonic-gate */ 3200Sstevel@tonic-gate void 3210Sstevel@tonic-gate crdup_to(cred_t *oldcr, cred_t *newcr) 3220Sstevel@tonic-gate { 3230Sstevel@tonic-gate bcopy(oldcr, newcr, crsize); 3240Sstevel@tonic-gate if (newcr->cr_zone) 3250Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 326*1676Sjpk if (newcr->cr_label) 327*1676Sjpk label_hold(newcr->cr_label); 3280Sstevel@tonic-gate newcr->cr_ref = 1; 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * Return the (held) credentials for the current running process. 3330Sstevel@tonic-gate */ 3340Sstevel@tonic-gate cred_t * 335*1676Sjpk crgetcred(void) 3360Sstevel@tonic-gate { 3370Sstevel@tonic-gate cred_t *cr; 3380Sstevel@tonic-gate proc_t *p; 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate p = ttoproc(curthread); 3410Sstevel@tonic-gate mutex_enter(&p->p_crlock); 3420Sstevel@tonic-gate crhold(cr = p->p_cred); 3430Sstevel@tonic-gate mutex_exit(&p->p_crlock); 3440Sstevel@tonic-gate return (cr); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Backward compatibility check for suser(). 3490Sstevel@tonic-gate * Accounting flag is now set in the policy functions; auditing is 3500Sstevel@tonic-gate * done through use of privilege in the audit trail. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate int 3530Sstevel@tonic-gate suser(cred_t *cr) 3540Sstevel@tonic-gate { 3550Sstevel@tonic-gate return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL) 3560Sstevel@tonic-gate == 0); 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* 3600Sstevel@tonic-gate * Determine whether the supplied group id is a member of the group 3610Sstevel@tonic-gate * described by the supplied credentials. 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate int 3640Sstevel@tonic-gate groupmember(gid_t gid, const cred_t *cr) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate if (gid == cr->cr_gid) 3670Sstevel@tonic-gate return (1); 3680Sstevel@tonic-gate return (supgroupmember(gid, cr)); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate /* 3720Sstevel@tonic-gate * As groupmember but only check against the supplemental groups. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate int 3750Sstevel@tonic-gate supgroupmember(gid_t gid, const cred_t *cr) 3760Sstevel@tonic-gate { 3770Sstevel@tonic-gate const gid_t *gp, *endgp; 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate endgp = &cr->cr_groups[cr->cr_ngroups]; 3800Sstevel@tonic-gate for (gp = cr->cr_groups; gp < endgp; gp++) 3810Sstevel@tonic-gate if (*gp == gid) 3820Sstevel@tonic-gate return (1); 3830Sstevel@tonic-gate return (0); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * This function is called to check whether the credentials set 3880Sstevel@tonic-gate * "scrp" has permission to act on credentials set "tcrp". It enforces the 3890Sstevel@tonic-gate * permission requirements needed to send a signal to a process. 3900Sstevel@tonic-gate * The same requirements are imposed by other system calls, however. 3910Sstevel@tonic-gate * 3920Sstevel@tonic-gate * The rules are: 3930Sstevel@tonic-gate * (1) if the credentials are the same, the check succeeds 3940Sstevel@tonic-gate * (2) if the zone ids don't match, and scrp is not in the global zone or 3950Sstevel@tonic-gate * does not have the PRIV_PROC_ZONE privilege, the check fails 3960Sstevel@tonic-gate * (3) if the real or effective user id of scrp matches the real or saved 3970Sstevel@tonic-gate * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check 3980Sstevel@tonic-gate * succeeds 3990Sstevel@tonic-gate * (4) otherwise, the check fails 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate int 4020Sstevel@tonic-gate hasprocperm(const cred_t *tcrp, const cred_t *scrp) 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate if (scrp == tcrp) 4050Sstevel@tonic-gate return (1); 4060Sstevel@tonic-gate if (scrp->cr_zone != tcrp->cr_zone && 4070Sstevel@tonic-gate (scrp->cr_zone != global_zone || 4080Sstevel@tonic-gate secpolicy_proc_zone(scrp) != 0)) 4090Sstevel@tonic-gate return (0); 4100Sstevel@tonic-gate if (scrp->cr_uid == tcrp->cr_ruid || 4110Sstevel@tonic-gate scrp->cr_ruid == tcrp->cr_ruid || 4120Sstevel@tonic-gate scrp->cr_uid == tcrp->cr_suid || 4130Sstevel@tonic-gate scrp->cr_ruid == tcrp->cr_suid || 4140Sstevel@tonic-gate !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm")) 4150Sstevel@tonic-gate return (1); 4160Sstevel@tonic-gate return (0); 4170Sstevel@tonic-gate } 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * This interface replaces hasprocperm; it works like hasprocperm but 4210Sstevel@tonic-gate * additionally returns success if the proc_t's match 4220Sstevel@tonic-gate * It is the preferred interface for most uses. 4230Sstevel@tonic-gate * And it will acquire pcrlock itself, so it assert's that it shouldn't 4240Sstevel@tonic-gate * be held. 4250Sstevel@tonic-gate */ 4260Sstevel@tonic-gate int 4270Sstevel@tonic-gate prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp) 4280Sstevel@tonic-gate { 4290Sstevel@tonic-gate int rets; 4300Sstevel@tonic-gate cred_t *tcrp; 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&tp->p_crlock)); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate if (tp == sp) 4350Sstevel@tonic-gate return (1); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0) 4380Sstevel@tonic-gate return (0); 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate mutex_enter(&tp->p_crlock); 4410Sstevel@tonic-gate tcrp = tp->p_cred; 4420Sstevel@tonic-gate rets = hasprocperm(tcrp, scrp); 4430Sstevel@tonic-gate mutex_exit(&tp->p_crlock); 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate return (rets); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate /* 4490Sstevel@tonic-gate * This routine is used to compare two credentials to determine if 4500Sstevel@tonic-gate * they refer to the same "user". If the pointers are equal, then 4510Sstevel@tonic-gate * they must refer to the same user. Otherwise, the contents of 4520Sstevel@tonic-gate * the credentials are compared to see whether they are equivalent. 4530Sstevel@tonic-gate * 4540Sstevel@tonic-gate * This routine returns 0 if the credentials refer to the same user, 4550Sstevel@tonic-gate * 1 if they do not. 4560Sstevel@tonic-gate */ 4570Sstevel@tonic-gate int 4580Sstevel@tonic-gate crcmp(const cred_t *cr1, const cred_t *cr2) 4590Sstevel@tonic-gate { 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate if (cr1 == cr2) 4620Sstevel@tonic-gate return (0); 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate if (cr1->cr_uid == cr2->cr_uid && 4650Sstevel@tonic-gate cr1->cr_gid == cr2->cr_gid && 4660Sstevel@tonic-gate cr1->cr_ruid == cr2->cr_ruid && 4670Sstevel@tonic-gate cr1->cr_rgid == cr2->cr_rgid && 4680Sstevel@tonic-gate cr1->cr_ngroups == cr2->cr_ngroups && 4690Sstevel@tonic-gate cr1->cr_zone == cr2->cr_zone && 4700Sstevel@tonic-gate bcmp(cr1->cr_groups, cr2->cr_groups, 4710Sstevel@tonic-gate cr1->cr_ngroups * sizeof (gid_t)) == 0) { 4720Sstevel@tonic-gate return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2))); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate return (1); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * Read access functions to cred_t. 4790Sstevel@tonic-gate */ 4800Sstevel@tonic-gate uid_t 4810Sstevel@tonic-gate crgetuid(const cred_t *cr) 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate return (cr->cr_uid); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate uid_t 4870Sstevel@tonic-gate crgetruid(const cred_t *cr) 4880Sstevel@tonic-gate { 4890Sstevel@tonic-gate return (cr->cr_ruid); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate uid_t 4930Sstevel@tonic-gate crgetsuid(const cred_t *cr) 4940Sstevel@tonic-gate { 4950Sstevel@tonic-gate return (cr->cr_suid); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate gid_t 4990Sstevel@tonic-gate crgetgid(const cred_t *cr) 5000Sstevel@tonic-gate { 5010Sstevel@tonic-gate return (cr->cr_gid); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate gid_t 5050Sstevel@tonic-gate crgetrgid(const cred_t *cr) 5060Sstevel@tonic-gate { 5070Sstevel@tonic-gate return (cr->cr_rgid); 5080Sstevel@tonic-gate } 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate gid_t 5110Sstevel@tonic-gate crgetsgid(const cred_t *cr) 5120Sstevel@tonic-gate { 5130Sstevel@tonic-gate return (cr->cr_sgid); 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate const auditinfo_addr_t * 5170Sstevel@tonic-gate crgetauinfo(const cred_t *cr) 5180Sstevel@tonic-gate { 5190Sstevel@tonic-gate return ((const auditinfo_addr_t *)CR_AUINFO(cr)); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate auditinfo_addr_t * 5230Sstevel@tonic-gate crgetauinfo_modifiable(cred_t *cr) 5240Sstevel@tonic-gate { 5250Sstevel@tonic-gate return (CR_AUINFO(cr)); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate zoneid_t 5290Sstevel@tonic-gate crgetzoneid(const cred_t *cr) 5300Sstevel@tonic-gate { 531*1676Sjpk return (cr->cr_zone == NULL ? 532*1676Sjpk (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) : 533*1676Sjpk cr->cr_zone->zone_id); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate projid_t 5370Sstevel@tonic-gate crgetprojid(const cred_t *cr) 5380Sstevel@tonic-gate { 5390Sstevel@tonic-gate return (cr->cr_projid); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate 542*1676Sjpk zone_t * 543*1676Sjpk crgetzone(const cred_t *cr) 544*1676Sjpk { 545*1676Sjpk return (cr->cr_zone); 546*1676Sjpk } 547*1676Sjpk 548*1676Sjpk struct ts_label_s * 549*1676Sjpk crgetlabel(const cred_t *cr) 550*1676Sjpk { 551*1676Sjpk return (cr->cr_label ? 552*1676Sjpk cr->cr_label : 553*1676Sjpk (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL)); 554*1676Sjpk } 555*1676Sjpk 556*1676Sjpk boolean_t 557*1676Sjpk crisremote(const cred_t *cr) 558*1676Sjpk { 559*1676Sjpk return (REMOTE_PEER_CRED(cr)); 560*1676Sjpk } 561*1676Sjpk 5620Sstevel@tonic-gate #define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID) 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate int 5650Sstevel@tonic-gate crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) 5660Sstevel@tonic-gate { 5670Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate if (BADID(r) || BADID(e) || BADID(s)) 5700Sstevel@tonic-gate return (-1); 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate if (r != -1) 5730Sstevel@tonic-gate cr->cr_ruid = r; 5740Sstevel@tonic-gate if (e != -1) 5750Sstevel@tonic-gate cr->cr_uid = e; 5760Sstevel@tonic-gate if (s != -1) 5770Sstevel@tonic-gate cr->cr_suid = s; 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate return (0); 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate int 5830Sstevel@tonic-gate crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) 5840Sstevel@tonic-gate { 5850Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate if (BADID(r) || BADID(e) || BADID(s)) 5880Sstevel@tonic-gate return (-1); 5890Sstevel@tonic-gate 5900Sstevel@tonic-gate if (r != -1) 5910Sstevel@tonic-gate cr->cr_rgid = r; 5920Sstevel@tonic-gate if (e != -1) 5930Sstevel@tonic-gate cr->cr_gid = e; 5940Sstevel@tonic-gate if (s != -1) 5950Sstevel@tonic-gate cr->cr_sgid = s; 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate return (0); 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate int 6010Sstevel@tonic-gate crsetugid(cred_t *cr, uid_t uid, gid_t gid) 6020Sstevel@tonic-gate { 6030Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate if (uid < 0 || uid > MAXUID || gid < 0 || gid > MAXUID) 6060Sstevel@tonic-gate return (-1); 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; 6090Sstevel@tonic-gate cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid; 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate return (0); 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate int 6150Sstevel@tonic-gate crsetgroups(cred_t *cr, int n, gid_t *grp) 6160Sstevel@tonic-gate { 6170Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate if (n > ngroups_max || n < 0) 6200Sstevel@tonic-gate return (-1); 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate cr->cr_ngroups = n; 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate if (n > 0) 6250Sstevel@tonic-gate bcopy(grp, cr->cr_groups, n * sizeof (gid_t)); 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate return (0); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate void 6310Sstevel@tonic-gate crsetprojid(cred_t *cr, projid_t projid) 6320Sstevel@tonic-gate { 6330Sstevel@tonic-gate ASSERT(projid >= 0 && projid <= MAXPROJID); 6340Sstevel@tonic-gate cr->cr_projid = projid; 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate /* 6380Sstevel@tonic-gate * This routine returns the pointer to the first element of the cr_groups 6390Sstevel@tonic-gate * array. It can move around in an implementation defined way. 6400Sstevel@tonic-gate */ 6410Sstevel@tonic-gate const gid_t * 6420Sstevel@tonic-gate crgetgroups(const cred_t *cr) 6430Sstevel@tonic-gate { 6440Sstevel@tonic-gate return (cr->cr_groups); 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate int 6480Sstevel@tonic-gate crgetngroups(const cred_t *cr) 6490Sstevel@tonic-gate { 6500Sstevel@tonic-gate return (cr->cr_ngroups); 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate void 6540Sstevel@tonic-gate cred2prcred(const cred_t *cr, prcred_t *pcrp) 6550Sstevel@tonic-gate { 6560Sstevel@tonic-gate pcrp->pr_euid = cr->cr_uid; 6570Sstevel@tonic-gate pcrp->pr_ruid = cr->cr_ruid; 6580Sstevel@tonic-gate pcrp->pr_suid = cr->cr_suid; 6590Sstevel@tonic-gate pcrp->pr_egid = cr->cr_gid; 6600Sstevel@tonic-gate pcrp->pr_rgid = cr->cr_rgid; 6610Sstevel@tonic-gate pcrp->pr_sgid = cr->cr_sgid; 6620Sstevel@tonic-gate pcrp->pr_ngroups = MIN(cr->cr_ngroups, (uint_t)ngroups_max); 6630Sstevel@tonic-gate pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */ 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate if (pcrp->pr_ngroups != 0) 6660Sstevel@tonic-gate bcopy(cr->cr_groups, pcrp->pr_groups, 6670Sstevel@tonic-gate sizeof (gid_t) * cr->cr_ngroups); 6680Sstevel@tonic-gate } 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate static int 671*1676Sjpk cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr) 6720Sstevel@tonic-gate { 6730Sstevel@tonic-gate auditinfo_addr_t *ai; 6740Sstevel@tonic-gate au_tid_addr_t tid; 6750Sstevel@tonic-gate 676*1676Sjpk if (secpolicy_audit_getattr(rcr) != 0) 6770Sstevel@tonic-gate return (-1); 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */ 6800Sstevel@tonic-gate tid = ai->ai_termid; 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate ainfo->ai_auid = ai->ai_auid; 6830Sstevel@tonic-gate ainfo->ai_mask = ai->ai_mask; 6840Sstevel@tonic-gate ainfo->ai_asid = ai->ai_asid; 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate ainfo->ai_termid.at_type = tid.at_type; 6870Sstevel@tonic-gate bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t)); 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port); 6900Sstevel@tonic-gate ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port); 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate return (0); 6930Sstevel@tonic-gate } 6940Sstevel@tonic-gate 695*1676Sjpk void 696*1676Sjpk cred2uclabel(const cred_t *cr, bslabel_t *labelp) 697*1676Sjpk { 698*1676Sjpk ts_label_t *tslp; 699*1676Sjpk 700*1676Sjpk if ((tslp = crgetlabel(cr)) != NULL) 701*1676Sjpk bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t)); 702*1676Sjpk } 703*1676Sjpk 7040Sstevel@tonic-gate /* 7050Sstevel@tonic-gate * Convert a credential into a "ucred". Allow the caller to specify 7060Sstevel@tonic-gate * and aligned buffer, e.g., in an mblk, so we don't have to allocate 7070Sstevel@tonic-gate * memory and copy it twice. 708*1676Sjpk * 709*1676Sjpk * This function may call cred2ucaud(), which calls CRED(). Since this 710*1676Sjpk * can be called from an interrupt thread, receiver's cred (rcr) is needed 711*1676Sjpk * to determine whether audit info should be included. 7120Sstevel@tonic-gate */ 7130Sstevel@tonic-gate struct ucred_s * 714*1676Sjpk cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr) 7150Sstevel@tonic-gate { 7160Sstevel@tonic-gate struct ucred_s *uc; 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate /* The structure isn't always completely filled in, so zero it */ 7190Sstevel@tonic-gate if (buf == NULL) { 7200Sstevel@tonic-gate uc = kmem_zalloc(ucredsize, KM_SLEEP); 7210Sstevel@tonic-gate } else { 7220Sstevel@tonic-gate bzero(buf, ucredsize); 7230Sstevel@tonic-gate uc = buf; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate uc->uc_size = ucredsize; 7260Sstevel@tonic-gate uc->uc_credoff = UCRED_CRED_OFF; 7270Sstevel@tonic-gate uc->uc_privoff = UCRED_PRIV_OFF; 7280Sstevel@tonic-gate uc->uc_audoff = UCRED_AUD_OFF; 729*1676Sjpk uc->uc_labeloff = UCRED_LABEL_OFF; 7300Sstevel@tonic-gate uc->uc_pid = pid; 7310Sstevel@tonic-gate uc->uc_projid = cr->cr_projid; 7320Sstevel@tonic-gate uc->uc_zoneid = crgetzoneid(cr); 7330Sstevel@tonic-gate 734*1676Sjpk /* 735*1676Sjpk * Note that cred2uclabel() call should not be factored out 736*1676Sjpk * to the bottom of the if-else. UCXXX() macros depend on 737*1676Sjpk * uc_xxxoff values to work correctly. 738*1676Sjpk */ 739*1676Sjpk if (REMOTE_PEER_CRED(cr)) { 740*1676Sjpk /* 741*1676Sjpk * other than label, the rest of cred info about a 742*1676Sjpk * remote peer isn't available. 743*1676Sjpk */ 744*1676Sjpk cred2uclabel(cr, UCLABEL(uc)); 745*1676Sjpk uc->uc_credoff = 0; 746*1676Sjpk uc->uc_privoff = 0; 7470Sstevel@tonic-gate uc->uc_audoff = 0; 748*1676Sjpk } else { 749*1676Sjpk cred2prcred(cr, UCCRED(uc)); 750*1676Sjpk cred2prpriv(cr, UCPRIV(uc)); 751*1676Sjpk if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0) 752*1676Sjpk uc->uc_audoff = 0; 753*1676Sjpk cred2uclabel(cr, UCLABEL(uc)); 754*1676Sjpk } 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate return (uc); 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate /* 7600Sstevel@tonic-gate * Get the "ucred" of a process. 7610Sstevel@tonic-gate */ 7620Sstevel@tonic-gate struct ucred_s * 7630Sstevel@tonic-gate pgetucred(proc_t *p) 7640Sstevel@tonic-gate { 7650Sstevel@tonic-gate cred_t *cr; 7660Sstevel@tonic-gate struct ucred_s *uc; 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate mutex_enter(&p->p_crlock); 7690Sstevel@tonic-gate cr = p->p_cred; 7700Sstevel@tonic-gate crhold(cr); 7710Sstevel@tonic-gate mutex_exit(&p->p_crlock); 7720Sstevel@tonic-gate 773*1676Sjpk uc = cred2ucred(cr, p->p_pid, NULL, CRED()); 7740Sstevel@tonic-gate crfree(cr); 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate return (uc); 7770Sstevel@tonic-gate } 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate /* 7800Sstevel@tonic-gate * If the reply status is NFSERR_EACCES, it may be because we are 7810Sstevel@tonic-gate * root (no root net access). Check the real uid, if it isn't root 7820Sstevel@tonic-gate * make that the uid instead and retry the call. 7830Sstevel@tonic-gate * Private interface for NFS. 7840Sstevel@tonic-gate */ 7850Sstevel@tonic-gate cred_t * 7860Sstevel@tonic-gate crnetadjust(cred_t *cr) 7870Sstevel@tonic-gate { 7880Sstevel@tonic-gate if (cr->cr_uid == 0 && cr->cr_ruid != 0) { 7890Sstevel@tonic-gate cr = crdup(cr); 7900Sstevel@tonic-gate cr->cr_uid = cr->cr_ruid; 7910Sstevel@tonic-gate return (cr); 7920Sstevel@tonic-gate } 7930Sstevel@tonic-gate return (NULL); 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate /* 7970Sstevel@tonic-gate * The reference count is of interest when you want to check 7980Sstevel@tonic-gate * whether it is ok to modify the credential in place. 7990Sstevel@tonic-gate */ 8000Sstevel@tonic-gate uint_t 8010Sstevel@tonic-gate crgetref(const cred_t *cr) 8020Sstevel@tonic-gate { 8030Sstevel@tonic-gate return (cr->cr_ref); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate static int 8070Sstevel@tonic-gate get_c2audit_load(void) 8080Sstevel@tonic-gate { 8090Sstevel@tonic-gate static int gotit = 0; 8100Sstevel@tonic-gate static int c2audit_load; 8110Sstevel@tonic-gate u_longlong_t audit_load_val; 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate if (gotit) 8140Sstevel@tonic-gate return (c2audit_load); 8150Sstevel@tonic-gate audit_load_val = 0; /* set default value once */ 8160Sstevel@tonic-gate (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); 8170Sstevel@tonic-gate c2audit_load = (int)audit_load_val; 8180Sstevel@tonic-gate gotit++; 8190Sstevel@tonic-gate return (c2audit_load); 8200Sstevel@tonic-gate } 8210Sstevel@tonic-gate 8220Sstevel@tonic-gate int 8230Sstevel@tonic-gate get_audit_ucrsize(void) 8240Sstevel@tonic-gate { 8250Sstevel@tonic-gate return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0); 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate /* 8290Sstevel@tonic-gate * Set zone pointer in credential to indicated value. First adds a 8300Sstevel@tonic-gate * hold for the new zone, then drops the hold on previous zone (if any). 8310Sstevel@tonic-gate * This is done in this order in case the old and new zones are the 8320Sstevel@tonic-gate * same. 8330Sstevel@tonic-gate */ 8340Sstevel@tonic-gate void 8350Sstevel@tonic-gate crsetzone(cred_t *cr, zone_t *zptr) 8360Sstevel@tonic-gate { 8370Sstevel@tonic-gate zone_t *oldzptr = cr->cr_zone; 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate ASSERT(cr != kcred); 8400Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 8410Sstevel@tonic-gate cr->cr_zone = zptr; 8420Sstevel@tonic-gate zone_cred_hold(zptr); 8430Sstevel@tonic-gate if (oldzptr) 8440Sstevel@tonic-gate zone_cred_rele(oldzptr); 8450Sstevel@tonic-gate } 846*1676Sjpk 847*1676Sjpk /* 848*1676Sjpk * Create a new cred based on the supplied label 849*1676Sjpk */ 850*1676Sjpk cred_t * 851*1676Sjpk newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags) 852*1676Sjpk { 853*1676Sjpk ts_label_t *lbl = labelalloc(blabel, doi, flags); 854*1676Sjpk cred_t *cr = NULL; 855*1676Sjpk 856*1676Sjpk if (lbl != NULL) { 857*1676Sjpk if ((cr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 858*1676Sjpk bcopy(dummycr, cr, crsize); 859*1676Sjpk cr->cr_label = lbl; 860*1676Sjpk } else { 861*1676Sjpk label_rele(lbl); 862*1676Sjpk } 863*1676Sjpk } 864*1676Sjpk 865*1676Sjpk return (cr); 866*1676Sjpk } 867*1676Sjpk 868*1676Sjpk /* 869*1676Sjpk * Derive a new cred from the existing cred, but with a different label. 870*1676Sjpk * To be used when a cred is being shared, but the label needs to be changed 871*1676Sjpk * by a caller without affecting other users 872*1676Sjpk */ 873*1676Sjpk cred_t * 874*1676Sjpk copycred_from_bslabel(cred_t *cr, bslabel_t *blabel, uint32_t doi, int flags) 875*1676Sjpk { 876*1676Sjpk ts_label_t *lbl = labelalloc(blabel, doi, flags); 877*1676Sjpk cred_t *newcr = NULL; 878*1676Sjpk 879*1676Sjpk if (lbl != NULL) { 880*1676Sjpk if ((newcr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 881*1676Sjpk bcopy(cr, newcr, crsize); 882*1676Sjpk if (newcr->cr_zone) 883*1676Sjpk zone_cred_hold(newcr->cr_zone); 884*1676Sjpk newcr->cr_label = lbl; 885*1676Sjpk newcr->cr_ref = 1; 886*1676Sjpk } else { 887*1676Sjpk label_rele(lbl); 888*1676Sjpk } 889*1676Sjpk } 890*1676Sjpk 891*1676Sjpk return (newcr); 892*1676Sjpk } 893*1676Sjpk 894*1676Sjpk /* 895*1676Sjpk * This function returns a pointer to the kcred-equivalent in the current zone. 896*1676Sjpk */ 897*1676Sjpk cred_t * 898*1676Sjpk zone_kcred(void) 899*1676Sjpk { 900*1676Sjpk zone_t *zone; 901*1676Sjpk 902*1676Sjpk if ((zone = CRED()->cr_zone) != NULL) 903*1676Sjpk return (zone->zone_kcred); 904*1676Sjpk else 905*1676Sjpk return (kcred); 906*1676Sjpk } 907