1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 33*7c478bd9Sstevel@tonic-gate * All Rights Reserved 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*7c478bd9Sstevel@tonic-gate * contributors. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/cred_impl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/acct.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/ucred.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/prsystm.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 61*7c478bd9Sstevel@tonic-gate #include <c2/audit.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/zone.h> 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static struct kmem_cache *cred_cache; 65*7c478bd9Sstevel@tonic-gate static size_t crsize = 0; 66*7c478bd9Sstevel@tonic-gate static int audoff = 0; 67*7c478bd9Sstevel@tonic-gate uint32_t ucredsize; 68*7c478bd9Sstevel@tonic-gate cred_t *kcred; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate int rstlink; /* link(2) restricted to files owned by user? */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate static int get_c2audit_load(void); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \ 75*7c478bd9Sstevel@tonic-gate ((char *)(c)) + audoff) 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * Initialize credentials data structures. 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate void 83*7c478bd9Sstevel@tonic-gate cred_init(void) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate priv_init(); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate crsize = sizeof (cred_t) + sizeof (gid_t) * (ngroups_max - 1); 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * Make sure it's word-aligned. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate if (get_c2audit_load() > 0) { 94*7c478bd9Sstevel@tonic-gate #ifdef _LP64 95*7c478bd9Sstevel@tonic-gate /* assure audit context is 64-bit aligned */ 96*7c478bd9Sstevel@tonic-gate audoff = (crsize + 97*7c478bd9Sstevel@tonic-gate sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1); 98*7c478bd9Sstevel@tonic-gate #else /* _LP64 */ 99*7c478bd9Sstevel@tonic-gate audoff = crsize; 100*7c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 101*7c478bd9Sstevel@tonic-gate crsize = audoff + sizeof (auditinfo_addr_t); 102*7c478bd9Sstevel@tonic-gate crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate cred_cache = kmem_cache_create("cred_cache", crsize, 0, 106*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, NULL, NULL, 0); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * kcred is used by anything that needs all privileges; it's 110*7c478bd9Sstevel@tonic-gate * also the template used for crget as it has all the compatible 111*7c478bd9Sstevel@tonic-gate * sets filled in. 112*7c478bd9Sstevel@tonic-gate */ 113*7c478bd9Sstevel@tonic-gate kcred = cralloc(); 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate bzero(kcred, crsize); 116*7c478bd9Sstevel@tonic-gate kcred->cr_ref = 1; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* kcred is never freed, so we don't need zone_cred_hold here */ 119*7c478bd9Sstevel@tonic-gate kcred->cr_zone = &zone0; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate priv_fillset(&CR_LPRIV(kcred)); 122*7c478bd9Sstevel@tonic-gate CR_IPRIV(kcred) = *priv_basic; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* Not a basic privilege, if chown is not restricted add it to I0 */ 125*7c478bd9Sstevel@tonic-gate if (!rstchown) 126*7c478bd9Sstevel@tonic-gate priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* Basic privilege, if link is restricted remove it from I0 */ 129*7c478bd9Sstevel@tonic-gate if (rstlink) 130*7c478bd9Sstevel@tonic-gate priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY); 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred); 133*7c478bd9Sstevel@tonic-gate /* CR_FLAGS(kcred) == 0, courtesy of bzero() */ 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * Set up credentials of p0. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate ttoproc(curthread)->p_cred = kcred; 139*7c478bd9Sstevel@tonic-gate curthread->t_cred = kcred; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate ucredsize = UCRED_SIZE; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * Allocate (nearly) uninitialized cred_t. 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate cred_t * 148*7c478bd9Sstevel@tonic-gate cralloc(void) 149*7c478bd9Sstevel@tonic-gate { 150*7c478bd9Sstevel@tonic-gate cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 151*7c478bd9Sstevel@tonic-gate cr->cr_ref = 1; /* So we can crfree() */ 152*7c478bd9Sstevel@tonic-gate cr->cr_zone = NULL; 153*7c478bd9Sstevel@tonic-gate return (cr); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * Allocate a initialized cred structure and crhold() it. 158*7c478bd9Sstevel@tonic-gate * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate cred_t * 161*7c478bd9Sstevel@tonic-gate crget(void) 162*7c478bd9Sstevel@tonic-gate { 163*7c478bd9Sstevel@tonic-gate cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate bcopy(kcred, cr, crsize); 166*7c478bd9Sstevel@tonic-gate cr->cr_ref = 1; 167*7c478bd9Sstevel@tonic-gate zone_cred_hold(cr->cr_zone); 168*7c478bd9Sstevel@tonic-gate return (cr); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Broadcast the cred to all the threads in the process. 173*7c478bd9Sstevel@tonic-gate * The current thread's credentials can be set right away, but other 174*7c478bd9Sstevel@tonic-gate * threads must wait until the start of the next system call or trap. 175*7c478bd9Sstevel@tonic-gate * This avoids changing the cred in the middle of a system call. 176*7c478bd9Sstevel@tonic-gate * 177*7c478bd9Sstevel@tonic-gate * The cred has already been held for the process and the thread (2 holds), 178*7c478bd9Sstevel@tonic-gate * and p->p_cred set. 179*7c478bd9Sstevel@tonic-gate * 180*7c478bd9Sstevel@tonic-gate * p->p_crlock shouldn't be held here, since p_lock must be acquired. 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate void 183*7c478bd9Sstevel@tonic-gate crset(proc_t *p, cred_t *cr) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate kthread_id_t t; 186*7c478bd9Sstevel@tonic-gate kthread_id_t first; 187*7c478bd9Sstevel@tonic-gate cred_t *oldcr; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate ASSERT(p == curproc); /* assumes p_lwpcnt can't change */ 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* 192*7c478bd9Sstevel@tonic-gate * DTrace accesses t_cred in probe context. t_cred must always be 193*7c478bd9Sstevel@tonic-gate * either NULL, or point to a valid, allocated cred structure. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate t = curthread; 196*7c478bd9Sstevel@tonic-gate oldcr = t->t_cred; 197*7c478bd9Sstevel@tonic-gate t->t_cred = cr; /* the cred is held by caller for this thread */ 198*7c478bd9Sstevel@tonic-gate crfree(oldcr); /* free the old cred for the thread */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* 201*7c478bd9Sstevel@tonic-gate * Broadcast to other threads, if any. 202*7c478bd9Sstevel@tonic-gate */ 203*7c478bd9Sstevel@tonic-gate if (p->p_lwpcnt > 1) { 204*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); /* to keep thread list safe */ 205*7c478bd9Sstevel@tonic-gate first = curthread; 206*7c478bd9Sstevel@tonic-gate for (t = first->t_forw; t != first; t = t->t_forw) 207*7c478bd9Sstevel@tonic-gate t->t_pre_sys = 1; /* so syscall will get new cred */ 208*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * Put a hold on a cred structure. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate void 216*7c478bd9Sstevel@tonic-gate crhold(cred_t *cr) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate atomic_add_32(&cr->cr_ref, 1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * Release previous hold on a cred structure. Free it if refcnt == 0. 223*7c478bd9Sstevel@tonic-gate */ 224*7c478bd9Sstevel@tonic-gate void 225*7c478bd9Sstevel@tonic-gate crfree(cred_t *cr) 226*7c478bd9Sstevel@tonic-gate { 227*7c478bd9Sstevel@tonic-gate if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) { 228*7c478bd9Sstevel@tonic-gate ASSERT(cr != kcred); 229*7c478bd9Sstevel@tonic-gate if (cr->cr_zone) 230*7c478bd9Sstevel@tonic-gate zone_cred_rele(cr->cr_zone); 231*7c478bd9Sstevel@tonic-gate kmem_cache_free(cred_cache, cr); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * Copy a cred structure to a new one and free the old one. 237*7c478bd9Sstevel@tonic-gate * The new cred will have two references. One for the calling process, 238*7c478bd9Sstevel@tonic-gate * and one for the thread. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate cred_t * 241*7c478bd9Sstevel@tonic-gate crcopy(cred_t *cr) 242*7c478bd9Sstevel@tonic-gate { 243*7c478bd9Sstevel@tonic-gate cred_t *newcr; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate newcr = cralloc(); 246*7c478bd9Sstevel@tonic-gate bcopy(cr, newcr, crsize); 247*7c478bd9Sstevel@tonic-gate if (newcr->cr_zone) 248*7c478bd9Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 249*7c478bd9Sstevel@tonic-gate crfree(cr); 250*7c478bd9Sstevel@tonic-gate newcr->cr_ref = 2; /* caller gets two references */ 251*7c478bd9Sstevel@tonic-gate return (newcr); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * Copy a cred structure to a new one and free the old one. 256*7c478bd9Sstevel@tonic-gate * The new cred will have two references. One for the calling process, 257*7c478bd9Sstevel@tonic-gate * and one for the thread. 258*7c478bd9Sstevel@tonic-gate * This variation on crcopy uses a pre-allocated structure for the 259*7c478bd9Sstevel@tonic-gate * "new" cred. 260*7c478bd9Sstevel@tonic-gate */ 261*7c478bd9Sstevel@tonic-gate void 262*7c478bd9Sstevel@tonic-gate crcopy_to(cred_t *oldcr, cred_t *newcr) 263*7c478bd9Sstevel@tonic-gate { 264*7c478bd9Sstevel@tonic-gate bcopy(oldcr, newcr, crsize); 265*7c478bd9Sstevel@tonic-gate if (newcr->cr_zone) 266*7c478bd9Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 267*7c478bd9Sstevel@tonic-gate crfree(oldcr); 268*7c478bd9Sstevel@tonic-gate newcr->cr_ref = 2; /* caller gets two references */ 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Dup a cred struct to a new held one. 273*7c478bd9Sstevel@tonic-gate * The old cred is not freed. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate cred_t * 276*7c478bd9Sstevel@tonic-gate crdup(cred_t *cr) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate cred_t *newcr; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate newcr = cralloc(); 281*7c478bd9Sstevel@tonic-gate bcopy(cr, newcr, crsize); 282*7c478bd9Sstevel@tonic-gate if (newcr->cr_zone) 283*7c478bd9Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 284*7c478bd9Sstevel@tonic-gate newcr->cr_ref = 1; 285*7c478bd9Sstevel@tonic-gate return (newcr); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * Dup a cred struct to a new held one. 290*7c478bd9Sstevel@tonic-gate * The old cred is not freed. 291*7c478bd9Sstevel@tonic-gate * This variation on crdup uses a pre-allocated structure for the 292*7c478bd9Sstevel@tonic-gate * "new" cred. 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate void 295*7c478bd9Sstevel@tonic-gate crdup_to(cred_t *oldcr, cred_t *newcr) 296*7c478bd9Sstevel@tonic-gate { 297*7c478bd9Sstevel@tonic-gate bcopy(oldcr, newcr, crsize); 298*7c478bd9Sstevel@tonic-gate if (newcr->cr_zone) 299*7c478bd9Sstevel@tonic-gate zone_cred_hold(newcr->cr_zone); 300*7c478bd9Sstevel@tonic-gate newcr->cr_ref = 1; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * Return the (held) credentials for the current running process. 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate cred_t * 307*7c478bd9Sstevel@tonic-gate crgetcred() 308*7c478bd9Sstevel@tonic-gate { 309*7c478bd9Sstevel@tonic-gate cred_t *cr; 310*7c478bd9Sstevel@tonic-gate proc_t *p; 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 313*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 314*7c478bd9Sstevel@tonic-gate crhold(cr = p->p_cred); 315*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 316*7c478bd9Sstevel@tonic-gate return (cr); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* 320*7c478bd9Sstevel@tonic-gate * Backward compatibility check for suser(). 321*7c478bd9Sstevel@tonic-gate * Accounting flag is now set in the policy functions; auditing is 322*7c478bd9Sstevel@tonic-gate * done through use of privilege in the audit trail. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate int 325*7c478bd9Sstevel@tonic-gate suser(cred_t *cr) 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL) 328*7c478bd9Sstevel@tonic-gate == 0); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* 332*7c478bd9Sstevel@tonic-gate * Determine whether the supplied group id is a member of the group 333*7c478bd9Sstevel@tonic-gate * described by the supplied credentials. 334*7c478bd9Sstevel@tonic-gate */ 335*7c478bd9Sstevel@tonic-gate int 336*7c478bd9Sstevel@tonic-gate groupmember(gid_t gid, const cred_t *cr) 337*7c478bd9Sstevel@tonic-gate { 338*7c478bd9Sstevel@tonic-gate if (gid == cr->cr_gid) 339*7c478bd9Sstevel@tonic-gate return (1); 340*7c478bd9Sstevel@tonic-gate return (supgroupmember(gid, cr)); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * As groupmember but only check against the supplemental groups. 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate int 347*7c478bd9Sstevel@tonic-gate supgroupmember(gid_t gid, const cred_t *cr) 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate const gid_t *gp, *endgp; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate endgp = &cr->cr_groups[cr->cr_ngroups]; 352*7c478bd9Sstevel@tonic-gate for (gp = cr->cr_groups; gp < endgp; gp++) 353*7c478bd9Sstevel@tonic-gate if (*gp == gid) 354*7c478bd9Sstevel@tonic-gate return (1); 355*7c478bd9Sstevel@tonic-gate return (0); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * This function is called to check whether the credentials set 360*7c478bd9Sstevel@tonic-gate * "scrp" has permission to act on credentials set "tcrp". It enforces the 361*7c478bd9Sstevel@tonic-gate * permission requirements needed to send a signal to a process. 362*7c478bd9Sstevel@tonic-gate * The same requirements are imposed by other system calls, however. 363*7c478bd9Sstevel@tonic-gate * 364*7c478bd9Sstevel@tonic-gate * The rules are: 365*7c478bd9Sstevel@tonic-gate * (1) if the credentials are the same, the check succeeds 366*7c478bd9Sstevel@tonic-gate * (2) if the zone ids don't match, and scrp is not in the global zone or 367*7c478bd9Sstevel@tonic-gate * does not have the PRIV_PROC_ZONE privilege, the check fails 368*7c478bd9Sstevel@tonic-gate * (3) if the real or effective user id of scrp matches the real or saved 369*7c478bd9Sstevel@tonic-gate * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check 370*7c478bd9Sstevel@tonic-gate * succeeds 371*7c478bd9Sstevel@tonic-gate * (4) otherwise, the check fails 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate int 374*7c478bd9Sstevel@tonic-gate hasprocperm(const cred_t *tcrp, const cred_t *scrp) 375*7c478bd9Sstevel@tonic-gate { 376*7c478bd9Sstevel@tonic-gate if (scrp == tcrp) 377*7c478bd9Sstevel@tonic-gate return (1); 378*7c478bd9Sstevel@tonic-gate if (scrp->cr_zone != tcrp->cr_zone && 379*7c478bd9Sstevel@tonic-gate (scrp->cr_zone != global_zone || 380*7c478bd9Sstevel@tonic-gate secpolicy_proc_zone(scrp) != 0)) 381*7c478bd9Sstevel@tonic-gate return (0); 382*7c478bd9Sstevel@tonic-gate if (scrp->cr_uid == tcrp->cr_ruid || 383*7c478bd9Sstevel@tonic-gate scrp->cr_ruid == tcrp->cr_ruid || 384*7c478bd9Sstevel@tonic-gate scrp->cr_uid == tcrp->cr_suid || 385*7c478bd9Sstevel@tonic-gate scrp->cr_ruid == tcrp->cr_suid || 386*7c478bd9Sstevel@tonic-gate !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm")) 387*7c478bd9Sstevel@tonic-gate return (1); 388*7c478bd9Sstevel@tonic-gate return (0); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * This interface replaces hasprocperm; it works like hasprocperm but 393*7c478bd9Sstevel@tonic-gate * additionally returns success if the proc_t's match 394*7c478bd9Sstevel@tonic-gate * It is the preferred interface for most uses. 395*7c478bd9Sstevel@tonic-gate * And it will acquire pcrlock itself, so it assert's that it shouldn't 396*7c478bd9Sstevel@tonic-gate * be held. 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate int 399*7c478bd9Sstevel@tonic-gate prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp) 400*7c478bd9Sstevel@tonic-gate { 401*7c478bd9Sstevel@tonic-gate int rets; 402*7c478bd9Sstevel@tonic-gate cred_t *tcrp; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&tp->p_crlock)); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate if (tp == sp) 407*7c478bd9Sstevel@tonic-gate return (1); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0) 410*7c478bd9Sstevel@tonic-gate return (0); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate mutex_enter(&tp->p_crlock); 413*7c478bd9Sstevel@tonic-gate tcrp = tp->p_cred; 414*7c478bd9Sstevel@tonic-gate rets = hasprocperm(tcrp, scrp); 415*7c478bd9Sstevel@tonic-gate mutex_exit(&tp->p_crlock); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate return (rets); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * This routine is used to compare two credentials to determine if 422*7c478bd9Sstevel@tonic-gate * they refer to the same "user". If the pointers are equal, then 423*7c478bd9Sstevel@tonic-gate * they must refer to the same user. Otherwise, the contents of 424*7c478bd9Sstevel@tonic-gate * the credentials are compared to see whether they are equivalent. 425*7c478bd9Sstevel@tonic-gate * 426*7c478bd9Sstevel@tonic-gate * This routine returns 0 if the credentials refer to the same user, 427*7c478bd9Sstevel@tonic-gate * 1 if they do not. 428*7c478bd9Sstevel@tonic-gate */ 429*7c478bd9Sstevel@tonic-gate int 430*7c478bd9Sstevel@tonic-gate crcmp(const cred_t *cr1, const cred_t *cr2) 431*7c478bd9Sstevel@tonic-gate { 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate if (cr1 == cr2) 434*7c478bd9Sstevel@tonic-gate return (0); 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if (cr1->cr_uid == cr2->cr_uid && 437*7c478bd9Sstevel@tonic-gate cr1->cr_gid == cr2->cr_gid && 438*7c478bd9Sstevel@tonic-gate cr1->cr_ruid == cr2->cr_ruid && 439*7c478bd9Sstevel@tonic-gate cr1->cr_rgid == cr2->cr_rgid && 440*7c478bd9Sstevel@tonic-gate cr1->cr_ngroups == cr2->cr_ngroups && 441*7c478bd9Sstevel@tonic-gate cr1->cr_zone == cr2->cr_zone && 442*7c478bd9Sstevel@tonic-gate bcmp(cr1->cr_groups, cr2->cr_groups, 443*7c478bd9Sstevel@tonic-gate cr1->cr_ngroups * sizeof (gid_t)) == 0) { 444*7c478bd9Sstevel@tonic-gate return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2))); 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate return (1); 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* 450*7c478bd9Sstevel@tonic-gate * Read access functions to cred_t. 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate uid_t 453*7c478bd9Sstevel@tonic-gate crgetuid(const cred_t *cr) 454*7c478bd9Sstevel@tonic-gate { 455*7c478bd9Sstevel@tonic-gate return (cr->cr_uid); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate uid_t 459*7c478bd9Sstevel@tonic-gate crgetruid(const cred_t *cr) 460*7c478bd9Sstevel@tonic-gate { 461*7c478bd9Sstevel@tonic-gate return (cr->cr_ruid); 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate uid_t 465*7c478bd9Sstevel@tonic-gate crgetsuid(const cred_t *cr) 466*7c478bd9Sstevel@tonic-gate { 467*7c478bd9Sstevel@tonic-gate return (cr->cr_suid); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate gid_t 471*7c478bd9Sstevel@tonic-gate crgetgid(const cred_t *cr) 472*7c478bd9Sstevel@tonic-gate { 473*7c478bd9Sstevel@tonic-gate return (cr->cr_gid); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate gid_t 477*7c478bd9Sstevel@tonic-gate crgetrgid(const cred_t *cr) 478*7c478bd9Sstevel@tonic-gate { 479*7c478bd9Sstevel@tonic-gate return (cr->cr_rgid); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate gid_t 483*7c478bd9Sstevel@tonic-gate crgetsgid(const cred_t *cr) 484*7c478bd9Sstevel@tonic-gate { 485*7c478bd9Sstevel@tonic-gate return (cr->cr_sgid); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate const auditinfo_addr_t * 489*7c478bd9Sstevel@tonic-gate crgetauinfo(const cred_t *cr) 490*7c478bd9Sstevel@tonic-gate { 491*7c478bd9Sstevel@tonic-gate return ((const auditinfo_addr_t *)CR_AUINFO(cr)); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate auditinfo_addr_t * 495*7c478bd9Sstevel@tonic-gate crgetauinfo_modifiable(cred_t *cr) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate return (CR_AUINFO(cr)); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate zoneid_t 501*7c478bd9Sstevel@tonic-gate crgetzoneid(const cred_t *cr) 502*7c478bd9Sstevel@tonic-gate { 503*7c478bd9Sstevel@tonic-gate return (cr->cr_zone->zone_id); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate projid_t 507*7c478bd9Sstevel@tonic-gate crgetprojid(const cred_t *cr) 508*7c478bd9Sstevel@tonic-gate { 509*7c478bd9Sstevel@tonic-gate return (cr->cr_projid); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate #define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID) 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate int 515*7c478bd9Sstevel@tonic-gate crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) 516*7c478bd9Sstevel@tonic-gate { 517*7c478bd9Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if (BADID(r) || BADID(e) || BADID(s)) 520*7c478bd9Sstevel@tonic-gate return (-1); 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (r != -1) 523*7c478bd9Sstevel@tonic-gate cr->cr_ruid = r; 524*7c478bd9Sstevel@tonic-gate if (e != -1) 525*7c478bd9Sstevel@tonic-gate cr->cr_uid = e; 526*7c478bd9Sstevel@tonic-gate if (s != -1) 527*7c478bd9Sstevel@tonic-gate cr->cr_suid = s; 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate return (0); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate int 533*7c478bd9Sstevel@tonic-gate crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) 534*7c478bd9Sstevel@tonic-gate { 535*7c478bd9Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate if (BADID(r) || BADID(e) || BADID(s)) 538*7c478bd9Sstevel@tonic-gate return (-1); 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate if (r != -1) 541*7c478bd9Sstevel@tonic-gate cr->cr_rgid = r; 542*7c478bd9Sstevel@tonic-gate if (e != -1) 543*7c478bd9Sstevel@tonic-gate cr->cr_gid = e; 544*7c478bd9Sstevel@tonic-gate if (s != -1) 545*7c478bd9Sstevel@tonic-gate cr->cr_sgid = s; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate return (0); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate int 551*7c478bd9Sstevel@tonic-gate crsetugid(cred_t *cr, uid_t uid, gid_t gid) 552*7c478bd9Sstevel@tonic-gate { 553*7c478bd9Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (uid < 0 || uid > MAXUID || gid < 0 || gid > MAXUID) 556*7c478bd9Sstevel@tonic-gate return (-1); 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; 559*7c478bd9Sstevel@tonic-gate cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate return (0); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate int 565*7c478bd9Sstevel@tonic-gate crsetgroups(cred_t *cr, int n, gid_t *grp) 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate if (n > ngroups_max || n < 0) 570*7c478bd9Sstevel@tonic-gate return (-1); 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate cr->cr_ngroups = n; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if (n > 0) 575*7c478bd9Sstevel@tonic-gate bcopy(grp, cr->cr_groups, n * sizeof (gid_t)); 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate return (0); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate void 581*7c478bd9Sstevel@tonic-gate crsetprojid(cred_t *cr, projid_t projid) 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate ASSERT(projid >= 0 && projid <= MAXPROJID); 584*7c478bd9Sstevel@tonic-gate cr->cr_projid = projid; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate /* 588*7c478bd9Sstevel@tonic-gate * This routine returns the pointer to the first element of the cr_groups 589*7c478bd9Sstevel@tonic-gate * array. It can move around in an implementation defined way. 590*7c478bd9Sstevel@tonic-gate */ 591*7c478bd9Sstevel@tonic-gate const gid_t * 592*7c478bd9Sstevel@tonic-gate crgetgroups(const cred_t *cr) 593*7c478bd9Sstevel@tonic-gate { 594*7c478bd9Sstevel@tonic-gate return (cr->cr_groups); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate int 598*7c478bd9Sstevel@tonic-gate crgetngroups(const cred_t *cr) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate return (cr->cr_ngroups); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate void 604*7c478bd9Sstevel@tonic-gate cred2prcred(const cred_t *cr, prcred_t *pcrp) 605*7c478bd9Sstevel@tonic-gate { 606*7c478bd9Sstevel@tonic-gate pcrp->pr_euid = cr->cr_uid; 607*7c478bd9Sstevel@tonic-gate pcrp->pr_ruid = cr->cr_ruid; 608*7c478bd9Sstevel@tonic-gate pcrp->pr_suid = cr->cr_suid; 609*7c478bd9Sstevel@tonic-gate pcrp->pr_egid = cr->cr_gid; 610*7c478bd9Sstevel@tonic-gate pcrp->pr_rgid = cr->cr_rgid; 611*7c478bd9Sstevel@tonic-gate pcrp->pr_sgid = cr->cr_sgid; 612*7c478bd9Sstevel@tonic-gate pcrp->pr_ngroups = MIN(cr->cr_ngroups, (uint_t)ngroups_max); 613*7c478bd9Sstevel@tonic-gate pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */ 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate if (pcrp->pr_ngroups != 0) 616*7c478bd9Sstevel@tonic-gate bcopy(cr->cr_groups, pcrp->pr_groups, 617*7c478bd9Sstevel@tonic-gate sizeof (gid_t) * cr->cr_ngroups); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate static int 621*7c478bd9Sstevel@tonic-gate cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate auditinfo_addr_t *ai; 624*7c478bd9Sstevel@tonic-gate au_tid_addr_t tid; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate if (secpolicy_audit_getattr(CRED()) != 0) 627*7c478bd9Sstevel@tonic-gate return (-1); 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */ 630*7c478bd9Sstevel@tonic-gate tid = ai->ai_termid; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate ainfo->ai_auid = ai->ai_auid; 633*7c478bd9Sstevel@tonic-gate ainfo->ai_mask = ai->ai_mask; 634*7c478bd9Sstevel@tonic-gate ainfo->ai_asid = ai->ai_asid; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate ainfo->ai_termid.at_type = tid.at_type; 637*7c478bd9Sstevel@tonic-gate bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t)); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port); 640*7c478bd9Sstevel@tonic-gate ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port); 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate return (0); 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * Convert a credential into a "ucred". Allow the caller to specify 647*7c478bd9Sstevel@tonic-gate * and aligned buffer, e.g., in an mblk, so we don't have to allocate 648*7c478bd9Sstevel@tonic-gate * memory and copy it twice. 649*7c478bd9Sstevel@tonic-gate */ 650*7c478bd9Sstevel@tonic-gate struct ucred_s * 651*7c478bd9Sstevel@tonic-gate cred2ucred(const cred_t *cr, pid_t pid, void *buf) 652*7c478bd9Sstevel@tonic-gate { 653*7c478bd9Sstevel@tonic-gate struct ucred_s *uc; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* The structure isn't always completely filled in, so zero it */ 656*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 657*7c478bd9Sstevel@tonic-gate uc = kmem_zalloc(ucredsize, KM_SLEEP); 658*7c478bd9Sstevel@tonic-gate } else { 659*7c478bd9Sstevel@tonic-gate bzero(buf, ucredsize); 660*7c478bd9Sstevel@tonic-gate uc = buf; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate uc->uc_size = ucredsize; 663*7c478bd9Sstevel@tonic-gate uc->uc_credoff = UCRED_CRED_OFF; 664*7c478bd9Sstevel@tonic-gate uc->uc_privoff = UCRED_PRIV_OFF; 665*7c478bd9Sstevel@tonic-gate uc->uc_audoff = UCRED_AUD_OFF; 666*7c478bd9Sstevel@tonic-gate uc->uc_pid = pid; 667*7c478bd9Sstevel@tonic-gate uc->uc_projid = cr->cr_projid; 668*7c478bd9Sstevel@tonic-gate uc->uc_zoneid = crgetzoneid(cr); 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate cred2prcred(cr, UCCRED(uc)); 671*7c478bd9Sstevel@tonic-gate cred2prpriv(cr, UCPRIV(uc)); 672*7c478bd9Sstevel@tonic-gate if (audoff == 0 || cred2ucaud(cr, UCAUD(uc)) != 0) 673*7c478bd9Sstevel@tonic-gate uc->uc_audoff = 0; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate return (uc); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * Get the "ucred" of a process. 680*7c478bd9Sstevel@tonic-gate */ 681*7c478bd9Sstevel@tonic-gate struct ucred_s * 682*7c478bd9Sstevel@tonic-gate pgetucred(proc_t *p) 683*7c478bd9Sstevel@tonic-gate { 684*7c478bd9Sstevel@tonic-gate cred_t *cr; 685*7c478bd9Sstevel@tonic-gate struct ucred_s *uc; 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 688*7c478bd9Sstevel@tonic-gate cr = p->p_cred; 689*7c478bd9Sstevel@tonic-gate crhold(cr); 690*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate uc = cred2ucred(cr, p->p_pid, NULL); 693*7c478bd9Sstevel@tonic-gate crfree(cr); 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate return (uc); 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate /* 699*7c478bd9Sstevel@tonic-gate * If the reply status is NFSERR_EACCES, it may be because we are 700*7c478bd9Sstevel@tonic-gate * root (no root net access). Check the real uid, if it isn't root 701*7c478bd9Sstevel@tonic-gate * make that the uid instead and retry the call. 702*7c478bd9Sstevel@tonic-gate * Private interface for NFS. 703*7c478bd9Sstevel@tonic-gate */ 704*7c478bd9Sstevel@tonic-gate cred_t * 705*7c478bd9Sstevel@tonic-gate crnetadjust(cred_t *cr) 706*7c478bd9Sstevel@tonic-gate { 707*7c478bd9Sstevel@tonic-gate if (cr->cr_uid == 0 && cr->cr_ruid != 0) { 708*7c478bd9Sstevel@tonic-gate cr = crdup(cr); 709*7c478bd9Sstevel@tonic-gate cr->cr_uid = cr->cr_ruid; 710*7c478bd9Sstevel@tonic-gate return (cr); 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate return (NULL); 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate /* 716*7c478bd9Sstevel@tonic-gate * The reference count is of interest when you want to check 717*7c478bd9Sstevel@tonic-gate * whether it is ok to modify the credential in place. 718*7c478bd9Sstevel@tonic-gate */ 719*7c478bd9Sstevel@tonic-gate uint_t 720*7c478bd9Sstevel@tonic-gate crgetref(const cred_t *cr) 721*7c478bd9Sstevel@tonic-gate { 722*7c478bd9Sstevel@tonic-gate return (cr->cr_ref); 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate static int 726*7c478bd9Sstevel@tonic-gate get_c2audit_load(void) 727*7c478bd9Sstevel@tonic-gate { 728*7c478bd9Sstevel@tonic-gate static int gotit = 0; 729*7c478bd9Sstevel@tonic-gate static int c2audit_load; 730*7c478bd9Sstevel@tonic-gate u_longlong_t audit_load_val; 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate if (gotit) 733*7c478bd9Sstevel@tonic-gate return (c2audit_load); 734*7c478bd9Sstevel@tonic-gate audit_load_val = 0; /* set default value once */ 735*7c478bd9Sstevel@tonic-gate (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); 736*7c478bd9Sstevel@tonic-gate c2audit_load = (int)audit_load_val; 737*7c478bd9Sstevel@tonic-gate gotit++; 738*7c478bd9Sstevel@tonic-gate return (c2audit_load); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate int 742*7c478bd9Sstevel@tonic-gate get_audit_ucrsize(void) 743*7c478bd9Sstevel@tonic-gate { 744*7c478bd9Sstevel@tonic-gate return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate /* 748*7c478bd9Sstevel@tonic-gate * Set zone pointer in credential to indicated value. First adds a 749*7c478bd9Sstevel@tonic-gate * hold for the new zone, then drops the hold on previous zone (if any). 750*7c478bd9Sstevel@tonic-gate * This is done in this order in case the old and new zones are the 751*7c478bd9Sstevel@tonic-gate * same. 752*7c478bd9Sstevel@tonic-gate */ 753*7c478bd9Sstevel@tonic-gate void 754*7c478bd9Sstevel@tonic-gate crsetzone(cred_t *cr, zone_t *zptr) 755*7c478bd9Sstevel@tonic-gate { 756*7c478bd9Sstevel@tonic-gate zone_t *oldzptr = cr->cr_zone; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate ASSERT(cr != kcred); 759*7c478bd9Sstevel@tonic-gate ASSERT(cr->cr_ref <= 2); 760*7c478bd9Sstevel@tonic-gate cr->cr_zone = zptr; 761*7c478bd9Sstevel@tonic-gate zone_cred_hold(zptr); 762*7c478bd9Sstevel@tonic-gate if (oldzptr) 763*7c478bd9Sstevel@tonic-gate zone_cred_rele(oldzptr); 764*7c478bd9Sstevel@tonic-gate } 765