xref: /titanic_51/usr/src/uts/common/syscall/uid.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 /*
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/tuneable.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/cred_impl.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/zone.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate int
47*7c478bd9Sstevel@tonic-gate setuid(uid_t uid)
48*7c478bd9Sstevel@tonic-gate {
49*7c478bd9Sstevel@tonic-gate 	register proc_t *p;
50*7c478bd9Sstevel@tonic-gate 	int error;
51*7c478bd9Sstevel@tonic-gate 	int do_nocd = 0;
52*7c478bd9Sstevel@tonic-gate 	int uidchge = 0;
53*7c478bd9Sstevel@tonic-gate 	cred_t	*cr, *newcr;
54*7c478bd9Sstevel@tonic-gate 	uid_t oldruid = uid;
55*7c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = getzoneid();
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	if (uid < 0 || uid > MAXUID)
58*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 	/*
61*7c478bd9Sstevel@tonic-gate 	 * Need to pre-allocate the new cred structure before grabbing
62*7c478bd9Sstevel@tonic-gate 	 * the p_crlock mutex.
63*7c478bd9Sstevel@tonic-gate 	 */
64*7c478bd9Sstevel@tonic-gate 	newcr = cralloc();
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 	p = ttoproc(curthread);
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate retry:
69*7c478bd9Sstevel@tonic-gate 	mutex_enter(&p->p_crlock);
70*7c478bd9Sstevel@tonic-gate 	cr = p->p_cred;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate 	if ((uid == cr->cr_ruid || uid == cr->cr_suid) &&
73*7c478bd9Sstevel@tonic-gate 	    secpolicy_allow_setid(cr, uid, B_TRUE) != 0) {
74*7c478bd9Sstevel@tonic-gate 		error = 0;
75*7c478bd9Sstevel@tonic-gate 		crcopy_to(cr, newcr);
76*7c478bd9Sstevel@tonic-gate 		p->p_cred = newcr;
77*7c478bd9Sstevel@tonic-gate 		newcr->cr_uid = uid;
78*7c478bd9Sstevel@tonic-gate 	} else if ((error = secpolicy_allow_setid(cr, uid, B_FALSE)) == 0) {
79*7c478bd9Sstevel@tonic-gate 		if (!uidchge && uid != cr->cr_ruid) {
80*7c478bd9Sstevel@tonic-gate 			/*
81*7c478bd9Sstevel@tonic-gate 			 * The ruid of the process is going to change. In order
82*7c478bd9Sstevel@tonic-gate 			 * to avoid a race condition involving the
83*7c478bd9Sstevel@tonic-gate 			 * process-count associated with the newly given ruid,
84*7c478bd9Sstevel@tonic-gate 			 * we increment the count before assigning the
85*7c478bd9Sstevel@tonic-gate 			 * credential to the process.
86*7c478bd9Sstevel@tonic-gate 			 * To do that, we'll have to take pidlock, so we first
87*7c478bd9Sstevel@tonic-gate 			 * release p_crlock.
88*7c478bd9Sstevel@tonic-gate 			 */
89*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_crlock);
90*7c478bd9Sstevel@tonic-gate 			uidchge = 1;
91*7c478bd9Sstevel@tonic-gate 			mutex_enter(&pidlock);
92*7c478bd9Sstevel@tonic-gate 			upcount_inc(uid, zoneid);
93*7c478bd9Sstevel@tonic-gate 			mutex_exit(&pidlock);
94*7c478bd9Sstevel@tonic-gate 			/*
95*7c478bd9Sstevel@tonic-gate 			 * As we released p_crlock we can't rely on the cr
96*7c478bd9Sstevel@tonic-gate 			 * we read. So retry the whole thing.
97*7c478bd9Sstevel@tonic-gate 			 */
98*7c478bd9Sstevel@tonic-gate 			goto retry;
99*7c478bd9Sstevel@tonic-gate 		}
100*7c478bd9Sstevel@tonic-gate 		/*
101*7c478bd9Sstevel@tonic-gate 		 * A privileged process that gives up its privilege
102*7c478bd9Sstevel@tonic-gate 		 * must be marked to produce no core dump.
103*7c478bd9Sstevel@tonic-gate 		 */
104*7c478bd9Sstevel@tonic-gate 		if (cr->cr_uid != uid ||
105*7c478bd9Sstevel@tonic-gate 		    cr->cr_ruid != uid ||
106*7c478bd9Sstevel@tonic-gate 		    cr->cr_suid != uid)
107*7c478bd9Sstevel@tonic-gate 			do_nocd = 1;
108*7c478bd9Sstevel@tonic-gate 		oldruid = cr->cr_ruid;
109*7c478bd9Sstevel@tonic-gate 		crcopy_to(cr, newcr);
110*7c478bd9Sstevel@tonic-gate 		p->p_cred = newcr;
111*7c478bd9Sstevel@tonic-gate 		newcr->cr_ruid = uid;
112*7c478bd9Sstevel@tonic-gate 		newcr->cr_suid = uid;
113*7c478bd9Sstevel@tonic-gate 		newcr->cr_uid = uid;
114*7c478bd9Sstevel@tonic-gate 		ASSERT(uid != oldruid ? uidchge : 1);
115*7c478bd9Sstevel@tonic-gate 	} else
116*7c478bd9Sstevel@tonic-gate 		crfree(newcr);
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	mutex_exit(&p->p_crlock);
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	/*
121*7c478bd9Sstevel@tonic-gate 	 * We decrement the number of processes associated with the oldruid
122*7c478bd9Sstevel@tonic-gate 	 * to match the increment above, even if the ruid of the process
123*7c478bd9Sstevel@tonic-gate 	 * did not change or an error occurred (oldruid == uid).
124*7c478bd9Sstevel@tonic-gate 	 */
125*7c478bd9Sstevel@tonic-gate 	if (uidchge) {
126*7c478bd9Sstevel@tonic-gate 		mutex_enter(&pidlock);
127*7c478bd9Sstevel@tonic-gate 		upcount_dec(oldruid, zoneid);
128*7c478bd9Sstevel@tonic-gate 		mutex_exit(&pidlock);
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	if (error == 0) {
132*7c478bd9Sstevel@tonic-gate 		if (do_nocd) {
133*7c478bd9Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
134*7c478bd9Sstevel@tonic-gate 			p->p_flag |= SNOCD;
135*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 		crset(p, newcr);	/* broadcast to process threads */
138*7c478bd9Sstevel@tonic-gate 		return (0);
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 	return (set_errno(error));
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate int64_t
144*7c478bd9Sstevel@tonic-gate getuid(void)
145*7c478bd9Sstevel@tonic-gate {
146*7c478bd9Sstevel@tonic-gate 	rval_t	r;
147*7c478bd9Sstevel@tonic-gate 	cred_t *cr;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	cr = curthread->t_cred;
150*7c478bd9Sstevel@tonic-gate 	r.r_val1 = cr->cr_ruid;
151*7c478bd9Sstevel@tonic-gate 	r.r_val2 = cr->cr_uid;
152*7c478bd9Sstevel@tonic-gate 	return (r.r_vals);
153*7c478bd9Sstevel@tonic-gate }
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate int
156*7c478bd9Sstevel@tonic-gate seteuid(uid_t uid)
157*7c478bd9Sstevel@tonic-gate {
158*7c478bd9Sstevel@tonic-gate 	register proc_t *p;
159*7c478bd9Sstevel@tonic-gate 	int error = EPERM;
160*7c478bd9Sstevel@tonic-gate 	int do_nocd = 0;
161*7c478bd9Sstevel@tonic-gate 	cred_t	*cr, *newcr;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	if (uid < 0 || uid > MAXUID)
164*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	/*
167*7c478bd9Sstevel@tonic-gate 	 * Need to pre-allocate the new cred structure before grabbing
168*7c478bd9Sstevel@tonic-gate 	 * the p_crlock mutex.
169*7c478bd9Sstevel@tonic-gate 	 */
170*7c478bd9Sstevel@tonic-gate 	newcr = cralloc();
171*7c478bd9Sstevel@tonic-gate 	p = ttoproc(curthread);
172*7c478bd9Sstevel@tonic-gate 	mutex_enter(&p->p_crlock);
173*7c478bd9Sstevel@tonic-gate 	cr = p->p_cred;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	if (uid == cr->cr_ruid || uid == cr->cr_uid || uid == cr->cr_suid ||
176*7c478bd9Sstevel@tonic-gate 	    (error = secpolicy_allow_setid(cr, uid, B_FALSE)) == 0) {
177*7c478bd9Sstevel@tonic-gate 		/*
178*7c478bd9Sstevel@tonic-gate 		 * A privileged process that makes itself look like a
179*7c478bd9Sstevel@tonic-gate 		 * set-uid process must be marked to produce no core dump,
180*7c478bd9Sstevel@tonic-gate 		 * if the effective uid did changed.
181*7c478bd9Sstevel@tonic-gate 		 */
182*7c478bd9Sstevel@tonic-gate 		if (cr->cr_uid != uid && error == 0)
183*7c478bd9Sstevel@tonic-gate 			do_nocd = 1;
184*7c478bd9Sstevel@tonic-gate 		error = 0;
185*7c478bd9Sstevel@tonic-gate 		crcopy_to(cr, newcr);
186*7c478bd9Sstevel@tonic-gate 		p->p_cred = newcr;
187*7c478bd9Sstevel@tonic-gate 		newcr->cr_uid = uid;
188*7c478bd9Sstevel@tonic-gate 	} else
189*7c478bd9Sstevel@tonic-gate 		crfree(newcr);
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	mutex_exit(&p->p_crlock);
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	if (error == 0) {
194*7c478bd9Sstevel@tonic-gate 		if (do_nocd) {
195*7c478bd9Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
196*7c478bd9Sstevel@tonic-gate 			p->p_flag |= SNOCD;
197*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
198*7c478bd9Sstevel@tonic-gate 		}
199*7c478bd9Sstevel@tonic-gate 		crset(p, newcr);	/* broadcast to process threads */
200*7c478bd9Sstevel@tonic-gate 		return (0);
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 	return (set_errno(error));
203*7c478bd9Sstevel@tonic-gate }
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate /*
206*7c478bd9Sstevel@tonic-gate  * Buy-back from SunOS 4.x
207*7c478bd9Sstevel@tonic-gate  *
208*7c478bd9Sstevel@tonic-gate  * Like setuid() and seteuid() combined -except- that non-root users
209*7c478bd9Sstevel@tonic-gate  * can change cr_ruid to cr_uid, and the semantics of cr_suid are
210*7c478bd9Sstevel@tonic-gate  * subtly different.
211*7c478bd9Sstevel@tonic-gate  */
212*7c478bd9Sstevel@tonic-gate int
213*7c478bd9Sstevel@tonic-gate setreuid(uid_t ruid, uid_t euid)
214*7c478bd9Sstevel@tonic-gate {
215*7c478bd9Sstevel@tonic-gate 	proc_t *p;
216*7c478bd9Sstevel@tonic-gate 	int error = 0;
217*7c478bd9Sstevel@tonic-gate 	int do_nocd = 0;
218*7c478bd9Sstevel@tonic-gate 	int uidchge = 0;
219*7c478bd9Sstevel@tonic-gate 	uid_t oldruid = ruid;
220*7c478bd9Sstevel@tonic-gate 	cred_t *cr, *newcr;
221*7c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = getzoneid();
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	if ((ruid != -1 && (ruid < 0 || ruid > MAXUID)) ||
224*7c478bd9Sstevel@tonic-gate 	    (euid != -1 && (euid < 0 || euid > MAXUID)))
225*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	/*
228*7c478bd9Sstevel@tonic-gate 	 * Need to pre-allocate the new cred structure before grabbing
229*7c478bd9Sstevel@tonic-gate 	 * the p_crlock mutex.
230*7c478bd9Sstevel@tonic-gate 	 */
231*7c478bd9Sstevel@tonic-gate 	newcr = cralloc();
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	p = ttoproc(curthread);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate retry:
236*7c478bd9Sstevel@tonic-gate 	mutex_enter(&p->p_crlock);
237*7c478bd9Sstevel@tonic-gate 	cr = p->p_cred;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	if (ruid != -1 && ruid != cr->cr_ruid && ruid != cr->cr_uid &&
240*7c478bd9Sstevel@tonic-gate 	    secpolicy_allow_setid(cr, ruid, B_FALSE) != 0) {
241*7c478bd9Sstevel@tonic-gate 		error = EPERM;
242*7c478bd9Sstevel@tonic-gate 	} else if (euid != -1 &&
243*7c478bd9Sstevel@tonic-gate 	    euid != cr->cr_ruid && euid != cr->cr_uid &&
244*7c478bd9Sstevel@tonic-gate 	    euid != cr->cr_suid && secpolicy_allow_setid(cr, euid, B_FALSE)) {
245*7c478bd9Sstevel@tonic-gate 		error = EPERM;
246*7c478bd9Sstevel@tonic-gate 	} else {
247*7c478bd9Sstevel@tonic-gate 		if (!uidchge && ruid != -1 && cr->cr_ruid != ruid) {
248*7c478bd9Sstevel@tonic-gate 			/*
249*7c478bd9Sstevel@tonic-gate 			 * The ruid of the process is going to change. In order
250*7c478bd9Sstevel@tonic-gate 			 * to avoid a race condition involving the
251*7c478bd9Sstevel@tonic-gate 			 * process-count associated with the newly given ruid,
252*7c478bd9Sstevel@tonic-gate 			 * we increment the count before assigning the
253*7c478bd9Sstevel@tonic-gate 			 * credential to the process.
254*7c478bd9Sstevel@tonic-gate 			 * To do that, we'll have to take pidlock, so we first
255*7c478bd9Sstevel@tonic-gate 			 * release p_crlock.
256*7c478bd9Sstevel@tonic-gate 			 */
257*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_crlock);
258*7c478bd9Sstevel@tonic-gate 			uidchge = 1;
259*7c478bd9Sstevel@tonic-gate 			mutex_enter(&pidlock);
260*7c478bd9Sstevel@tonic-gate 			upcount_inc(ruid, zoneid);
261*7c478bd9Sstevel@tonic-gate 			mutex_exit(&pidlock);
262*7c478bd9Sstevel@tonic-gate 			/*
263*7c478bd9Sstevel@tonic-gate 			 * As we released p_crlock we can't rely on the cr
264*7c478bd9Sstevel@tonic-gate 			 * we read. So retry the whole thing.
265*7c478bd9Sstevel@tonic-gate 			 */
266*7c478bd9Sstevel@tonic-gate 			goto retry;
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 		crhold(cr);
269*7c478bd9Sstevel@tonic-gate 		crcopy_to(cr, newcr);
270*7c478bd9Sstevel@tonic-gate 		p->p_cred = newcr;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 		if (euid != -1)
273*7c478bd9Sstevel@tonic-gate 			newcr->cr_uid = euid;
274*7c478bd9Sstevel@tonic-gate 		if (ruid != -1) {
275*7c478bd9Sstevel@tonic-gate 			oldruid = newcr->cr_ruid;
276*7c478bd9Sstevel@tonic-gate 			newcr->cr_ruid = ruid;
277*7c478bd9Sstevel@tonic-gate 			ASSERT(ruid != oldruid ? uidchge : 1);
278*7c478bd9Sstevel@tonic-gate 		}
279*7c478bd9Sstevel@tonic-gate 		/*
280*7c478bd9Sstevel@tonic-gate 		 * "If the real uid is being changed, or the effective uid is
281*7c478bd9Sstevel@tonic-gate 		 * being changed to a value not equal to the real uid, the
282*7c478bd9Sstevel@tonic-gate 		 * saved uid is set to the new effective uid."
283*7c478bd9Sstevel@tonic-gate 		 */
284*7c478bd9Sstevel@tonic-gate 		if (ruid != -1 ||
285*7c478bd9Sstevel@tonic-gate 		    (euid != -1 && newcr->cr_uid != newcr->cr_ruid))
286*7c478bd9Sstevel@tonic-gate 			newcr->cr_suid = newcr->cr_uid;
287*7c478bd9Sstevel@tonic-gate 		/*
288*7c478bd9Sstevel@tonic-gate 		 * A process that gives up its privilege
289*7c478bd9Sstevel@tonic-gate 		 * must be marked to produce no core dump.
290*7c478bd9Sstevel@tonic-gate 		 */
291*7c478bd9Sstevel@tonic-gate 		if ((cr->cr_uid != newcr->cr_uid ||
292*7c478bd9Sstevel@tonic-gate 		    cr->cr_ruid != newcr->cr_ruid ||
293*7c478bd9Sstevel@tonic-gate 		    cr->cr_suid != newcr->cr_suid))
294*7c478bd9Sstevel@tonic-gate 			do_nocd = 1;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 		crfree(cr);
297*7c478bd9Sstevel@tonic-gate 	}
298*7c478bd9Sstevel@tonic-gate 	mutex_exit(&p->p_crlock);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	/*
301*7c478bd9Sstevel@tonic-gate 	 * We decrement the number of processes associated with the oldruid
302*7c478bd9Sstevel@tonic-gate 	 * to match the increment above, even if the ruid of the process
303*7c478bd9Sstevel@tonic-gate 	 * did not change or an error occurred (oldruid == uid).
304*7c478bd9Sstevel@tonic-gate 	 */
305*7c478bd9Sstevel@tonic-gate 	if (uidchge) {
306*7c478bd9Sstevel@tonic-gate 		ASSERT(oldruid != -1 && ruid != -1);
307*7c478bd9Sstevel@tonic-gate 		mutex_enter(&pidlock);
308*7c478bd9Sstevel@tonic-gate 		upcount_dec(oldruid, zoneid);
309*7c478bd9Sstevel@tonic-gate 		mutex_exit(&pidlock);
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	if (error == 0) {
313*7c478bd9Sstevel@tonic-gate 		if (do_nocd) {
314*7c478bd9Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
315*7c478bd9Sstevel@tonic-gate 			p->p_flag |= SNOCD;
316*7c478bd9Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
317*7c478bd9Sstevel@tonic-gate 		}
318*7c478bd9Sstevel@tonic-gate 		crset(p, newcr);	/* broadcast to process threads */
319*7c478bd9Sstevel@tonic-gate 		return (0);
320*7c478bd9Sstevel@tonic-gate 	}
321*7c478bd9Sstevel@tonic-gate 	crfree(newcr);
322*7c478bd9Sstevel@tonic-gate 	return (set_errno(error));
323*7c478bd9Sstevel@tonic-gate }
324