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 1994,2001-2003 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 /* 28*7c478bd9Sstevel@tonic-gate * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/cred_impl.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate int 45*7c478bd9Sstevel@tonic-gate setgid(gid_t gid) 46*7c478bd9Sstevel@tonic-gate { 47*7c478bd9Sstevel@tonic-gate register proc_t *p; 48*7c478bd9Sstevel@tonic-gate int error; 49*7c478bd9Sstevel@tonic-gate int do_nocd = 0; 50*7c478bd9Sstevel@tonic-gate cred_t *cr, *newcr; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate if (gid < 0 || gid > MAXUID) 53*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * Need to pre-allocate the new cred structure before grabbing 57*7c478bd9Sstevel@tonic-gate * the p_crlock mutex. 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate newcr = cralloc(); 60*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 61*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 62*7c478bd9Sstevel@tonic-gate cr = p->p_cred; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate if ((gid == cr->cr_rgid || gid == cr->cr_sgid) && 65*7c478bd9Sstevel@tonic-gate secpolicy_allow_setid(cr, -1, B_TRUE) != 0) { 66*7c478bd9Sstevel@tonic-gate error = 0; 67*7c478bd9Sstevel@tonic-gate crcopy_to(cr, newcr); 68*7c478bd9Sstevel@tonic-gate p->p_cred = newcr; 69*7c478bd9Sstevel@tonic-gate newcr->cr_gid = gid; 70*7c478bd9Sstevel@tonic-gate } else if ((error = secpolicy_allow_setid(cr, -1, B_FALSE)) == 0) { 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * A privileged process that makes itself look like a 73*7c478bd9Sstevel@tonic-gate * set-gid process must be marked to produce no core dump. 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate if (cr->cr_gid != gid || 76*7c478bd9Sstevel@tonic-gate cr->cr_rgid != gid || 77*7c478bd9Sstevel@tonic-gate cr->cr_sgid != gid) 78*7c478bd9Sstevel@tonic-gate do_nocd = 1; 79*7c478bd9Sstevel@tonic-gate crcopy_to(cr, newcr); 80*7c478bd9Sstevel@tonic-gate p->p_cred = newcr; 81*7c478bd9Sstevel@tonic-gate newcr->cr_gid = gid; 82*7c478bd9Sstevel@tonic-gate newcr->cr_rgid = gid; 83*7c478bd9Sstevel@tonic-gate newcr->cr_sgid = gid; 84*7c478bd9Sstevel@tonic-gate } else 85*7c478bd9Sstevel@tonic-gate crfree(newcr); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate if (error == 0) { 90*7c478bd9Sstevel@tonic-gate if (do_nocd) { 91*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 92*7c478bd9Sstevel@tonic-gate p->p_flag |= SNOCD; 93*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate crset(p, newcr); /* broadcast to process threads */ 96*7c478bd9Sstevel@tonic-gate return (0); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate int64_t 102*7c478bd9Sstevel@tonic-gate getgid(void) 103*7c478bd9Sstevel@tonic-gate { 104*7c478bd9Sstevel@tonic-gate rval_t r; 105*7c478bd9Sstevel@tonic-gate cred_t *cr; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate cr = curthread->t_cred; 108*7c478bd9Sstevel@tonic-gate r.r_val1 = cr->cr_rgid; 109*7c478bd9Sstevel@tonic-gate r.r_val2 = cr->cr_gid; 110*7c478bd9Sstevel@tonic-gate return (r.r_vals); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate int 114*7c478bd9Sstevel@tonic-gate setegid(gid_t gid) 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate register proc_t *p; 117*7c478bd9Sstevel@tonic-gate register cred_t *cr, *newcr; 118*7c478bd9Sstevel@tonic-gate int error = EPERM; 119*7c478bd9Sstevel@tonic-gate int do_nocd = 0; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate if (gid < 0 || gid > MAXUID) 122*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * Need to pre-allocate the new cred structure before grabbing 126*7c478bd9Sstevel@tonic-gate * the p_crlock mutex. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate newcr = cralloc(); 129*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 130*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 131*7c478bd9Sstevel@tonic-gate cr = p->p_cred; 132*7c478bd9Sstevel@tonic-gate if (gid == cr->cr_rgid || gid == cr->cr_gid || gid == cr->cr_sgid || 133*7c478bd9Sstevel@tonic-gate (error = secpolicy_allow_setid(cr, -1, B_FALSE)) == 0) { 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * A privileged process that makes itself look like a 136*7c478bd9Sstevel@tonic-gate * set-gid process must be marked to produce no core dump. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate if (cr->cr_gid != gid && error == 0) 139*7c478bd9Sstevel@tonic-gate do_nocd = 1; 140*7c478bd9Sstevel@tonic-gate error = 0; 141*7c478bd9Sstevel@tonic-gate crcopy_to(cr, newcr); 142*7c478bd9Sstevel@tonic-gate p->p_cred = newcr; 143*7c478bd9Sstevel@tonic-gate newcr->cr_gid = gid; 144*7c478bd9Sstevel@tonic-gate } else 145*7c478bd9Sstevel@tonic-gate crfree(newcr); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate if (error == 0) { 150*7c478bd9Sstevel@tonic-gate if (do_nocd) { 151*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 152*7c478bd9Sstevel@tonic-gate p->p_flag |= SNOCD; 153*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate crset(p, newcr); /* broadcast to process threads */ 156*7c478bd9Sstevel@tonic-gate return (0); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Buy-back from SunOS 4.x 163*7c478bd9Sstevel@tonic-gate * 164*7c478bd9Sstevel@tonic-gate * Like setgid() and setegid() combined -except- that non-root users 165*7c478bd9Sstevel@tonic-gate * can change cr_rgid to cr_gid, and the semantics of cr_sgid are 166*7c478bd9Sstevel@tonic-gate * subtly different. 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate int 169*7c478bd9Sstevel@tonic-gate setregid(gid_t rgid, gid_t egid) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate proc_t *p; 172*7c478bd9Sstevel@tonic-gate int error = EPERM; 173*7c478bd9Sstevel@tonic-gate int do_nocd = 0; 174*7c478bd9Sstevel@tonic-gate cred_t *cr, *newcr; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if ((rgid != -1 && (rgid < 0 || rgid > MAXUID)) || 177*7c478bd9Sstevel@tonic-gate (egid != -1 && (egid < 0 || egid > MAXUID))) 178*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Need to pre-allocate the new cred structure before grabbing 182*7c478bd9Sstevel@tonic-gate * the p_crlock mutex. 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate newcr = cralloc(); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 187*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 188*7c478bd9Sstevel@tonic-gate cr = p->p_cred; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if ((rgid == -1 || 191*7c478bd9Sstevel@tonic-gate rgid == cr->cr_rgid || rgid == cr->cr_gid || rgid == cr->cr_sgid) && 192*7c478bd9Sstevel@tonic-gate (egid == -1 || egid == cr->cr_rgid || egid == cr->cr_gid || 193*7c478bd9Sstevel@tonic-gate egid == cr->cr_sgid) || 194*7c478bd9Sstevel@tonic-gate (error = secpolicy_allow_setid(cr, -1, B_FALSE)) == 0) { 195*7c478bd9Sstevel@tonic-gate crhold(cr); 196*7c478bd9Sstevel@tonic-gate crcopy_to(cr, newcr); 197*7c478bd9Sstevel@tonic-gate p->p_cred = newcr; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate if (egid != -1) 200*7c478bd9Sstevel@tonic-gate newcr->cr_gid = egid; 201*7c478bd9Sstevel@tonic-gate if (rgid != -1) 202*7c478bd9Sstevel@tonic-gate newcr->cr_rgid = rgid; 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * "If the real gid is being changed, or the effective gid is 205*7c478bd9Sstevel@tonic-gate * being changed to a value not equal to the real gid, the 206*7c478bd9Sstevel@tonic-gate * saved gid is set to the new effective gid." 207*7c478bd9Sstevel@tonic-gate */ 208*7c478bd9Sstevel@tonic-gate if (rgid != -1 || 209*7c478bd9Sstevel@tonic-gate (egid != -1 && newcr->cr_gid != newcr->cr_rgid)) 210*7c478bd9Sstevel@tonic-gate newcr->cr_sgid = newcr->cr_gid; 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * A privileged process that makes itself look like a 213*7c478bd9Sstevel@tonic-gate * set-gid process must be marked to produce no core dump. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate if ((cr->cr_gid != newcr->cr_gid || 216*7c478bd9Sstevel@tonic-gate cr->cr_rgid != newcr->cr_rgid || 217*7c478bd9Sstevel@tonic-gate cr->cr_sgid != newcr->cr_sgid) && error == 0) 218*7c478bd9Sstevel@tonic-gate do_nocd = 1; 219*7c478bd9Sstevel@tonic-gate error = 0; 220*7c478bd9Sstevel@tonic-gate crfree(cr); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if (error == 0) { 225*7c478bd9Sstevel@tonic-gate if (do_nocd) { 226*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 227*7c478bd9Sstevel@tonic-gate p->p_flag |= SNOCD; 228*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate crset(p, newcr); /* broadcast to process threads */ 231*7c478bd9Sstevel@tonic-gate return (0); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate crfree(newcr); 234*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 235*7c478bd9Sstevel@tonic-gate } 236