xref: /titanic_44/usr/src/lib/libproject/common/setproject.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 2005 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/task.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <unistd.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <ctype.h>
34*7c478bd9Sstevel@tonic-gate #include <project.h>
35*7c478bd9Sstevel@tonic-gate #include <rctl.h>
36*7c478bd9Sstevel@tonic-gate #include <secdb.h>
37*7c478bd9Sstevel@tonic-gate #include <signal.h>
38*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
41*7c478bd9Sstevel@tonic-gate #include <pwd.h>
42*7c478bd9Sstevel@tonic-gate #include <pool.h>
43*7c478bd9Sstevel@tonic-gate #include <libproc.h>
44*7c478bd9Sstevel@tonic-gate #include <priv.h>
45*7c478bd9Sstevel@tonic-gate #include <priv_utils.h>
46*7c478bd9Sstevel@tonic-gate #include <zone.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/pool.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate static void
51*7c478bd9Sstevel@tonic-gate xstrtolower(char *s)
52*7c478bd9Sstevel@tonic-gate {
53*7c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++)
54*7c478bd9Sstevel@tonic-gate 		*s = tolower(*s);
55*7c478bd9Sstevel@tonic-gate }
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static void
58*7c478bd9Sstevel@tonic-gate remove_spaces(char *s)
59*7c478bd9Sstevel@tonic-gate {
60*7c478bd9Sstevel@tonic-gate 	char *current;
61*7c478bd9Sstevel@tonic-gate 	char *next;
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 	current = next = s;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	while (*next != '\0') {
66*7c478bd9Sstevel@tonic-gate 		while (isspace(*next))
67*7c478bd9Sstevel@tonic-gate 		    next++;
68*7c478bd9Sstevel@tonic-gate 		*current++ = *next++;
69*7c478bd9Sstevel@tonic-gate 	}
70*7c478bd9Sstevel@tonic-gate 	*current = '\0';
71*7c478bd9Sstevel@tonic-gate }
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate int
74*7c478bd9Sstevel@tonic-gate build_rctlblk(rctlblk_t *blk, int comp_num, char *component)
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	char *signam;
77*7c478bd9Sstevel@tonic-gate 	int sig = 0;
78*7c478bd9Sstevel@tonic-gate 	uint_t act = rctlblk_get_local_action(blk, &sig);
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	if (comp_num == 0) {
81*7c478bd9Sstevel@tonic-gate 		/*
82*7c478bd9Sstevel@tonic-gate 		 * Setting privilege level for resource control block.
83*7c478bd9Sstevel@tonic-gate 		 */
84*7c478bd9Sstevel@tonic-gate 		xstrtolower(component);
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 		if (strcmp("basic", component) == 0) {
87*7c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_BASIC);
88*7c478bd9Sstevel@tonic-gate 			return (0);
89*7c478bd9Sstevel@tonic-gate 		}
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 		if (strcmp("priv", component) == 0 ||
92*7c478bd9Sstevel@tonic-gate 		    strcmp("privileged", component) == 0) {
93*7c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
94*7c478bd9Sstevel@tonic-gate 			return (0);
95*7c478bd9Sstevel@tonic-gate 		}
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 		return (-1);
98*7c478bd9Sstevel@tonic-gate 	}
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	if (comp_num == 1) {
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 		/*
103*7c478bd9Sstevel@tonic-gate 		 * Setting value for resource control block.
104*7c478bd9Sstevel@tonic-gate 		 */
105*7c478bd9Sstevel@tonic-gate 		unsigned long long val;
106*7c478bd9Sstevel@tonic-gate 		char *t;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 		/* Negative numbers are not allowed */
109*7c478bd9Sstevel@tonic-gate 		if (strchr(component, '-') != NULL)
110*7c478bd9Sstevel@tonic-gate 			return (-1);
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 		errno = 0;
113*7c478bd9Sstevel@tonic-gate 		val = strtoull(component, &t, 10);
114*7c478bd9Sstevel@tonic-gate 		if (errno != 0 || t == component || *t != '\0')
115*7c478bd9Sstevel@tonic-gate 			return (-1);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 		rctlblk_set_value(blk, (rctl_qty_t)val);
118*7c478bd9Sstevel@tonic-gate 		return (0);
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * Setting one or more actions on this resource control block.
123*7c478bd9Sstevel@tonic-gate 	 */
124*7c478bd9Sstevel@tonic-gate 	if (comp_num >= 2) {
125*7c478bd9Sstevel@tonic-gate 		if (strcmp("none", component) == 0) {
126*7c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, 0, 0);
127*7c478bd9Sstevel@tonic-gate 			return (0);
128*7c478bd9Sstevel@tonic-gate 		}
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		if (strcmp("deny", component) == 0) {
131*7c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_DENY;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 			return (0);
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 		/*
139*7c478bd9Sstevel@tonic-gate 		 * The last, and trickiest, form of action is the signal
140*7c478bd9Sstevel@tonic-gate 		 * specification.
141*7c478bd9Sstevel@tonic-gate 		 */
142*7c478bd9Sstevel@tonic-gate 		if ((signam = strchr(component, '=')) == NULL)
143*7c478bd9Sstevel@tonic-gate 			return (-1);
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		*signam++ = '\0';
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		if (strcmp("sig", component) == 0 ||
148*7c478bd9Sstevel@tonic-gate 		    strcmp("signal", component) == 0) {
149*7c478bd9Sstevel@tonic-gate 			if (strncmp("SIG", signam, 3) == 0)
150*7c478bd9Sstevel@tonic-gate 				signam += 3;
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 			if (str2sig(signam, &sig) == -1)
153*7c478bd9Sstevel@tonic-gate 				return (-1);
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_SIGNAL;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 			return (0);
160*7c478bd9Sstevel@tonic-gate 		}
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	return (-1);
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate /*
166*7c478bd9Sstevel@tonic-gate  * States:
167*7c478bd9Sstevel@tonic-gate  */
168*7c478bd9Sstevel@tonic-gate #define	INPAREN		0x1
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate /*
171*7c478bd9Sstevel@tonic-gate  * Errors:
172*7c478bd9Sstevel@tonic-gate  */
173*7c478bd9Sstevel@tonic-gate #define	SETFAILED	(-1)
174*7c478bd9Sstevel@tonic-gate #define	COMPLETE	1
175*7c478bd9Sstevel@tonic-gate #define	NESTING		2
176*7c478bd9Sstevel@tonic-gate #define	UNCLOSED	3
177*7c478bd9Sstevel@tonic-gate #define	CLOSEBEFOREOPEN	4
178*7c478bd9Sstevel@tonic-gate #define	BADSPEC		5
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate static int
181*7c478bd9Sstevel@tonic-gate rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
182*7c478bd9Sstevel@tonic-gate {
183*7c478bd9Sstevel@tonic-gate 	int error = 0;
184*7c478bd9Sstevel@tonic-gate 	uint_t component = 0;
185*7c478bd9Sstevel@tonic-gate 	int valuecount = 0;
186*7c478bd9Sstevel@tonic-gate 	uint_t state = 0;
187*7c478bd9Sstevel@tonic-gate 	char *component_head;
188*7c478bd9Sstevel@tonic-gate 	rctlblk_t *blk;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	remove_spaces(val);
191*7c478bd9Sstevel@tonic-gate 	if ((blk = malloc(rctlblk_size())) == NULL) {
192*7c478bd9Sstevel@tonic-gate 		return (SETFAILED);
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	/*
196*7c478bd9Sstevel@tonic-gate 	 * Tear down everything with this ctl name.
197*7c478bd9Sstevel@tonic-gate 	 */
198*7c478bd9Sstevel@tonic-gate 	while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 &&
199*7c478bd9Sstevel@tonic-gate 	    rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) {
200*7c478bd9Sstevel@tonic-gate 		(void) pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE);
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	/*
204*7c478bd9Sstevel@tonic-gate 	 * Set initial local action based on global deny properties.
205*7c478bd9Sstevel@tonic-gate 	 */
206*7c478bd9Sstevel@tonic-gate 	rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
207*7c478bd9Sstevel@tonic-gate 	rctlblk_set_value(blk, 0);
208*7c478bd9Sstevel@tonic-gate 	rctlblk_set_local_flags(blk, 0);
209*7c478bd9Sstevel@tonic-gate 	if (rctlblk_get_global_flags(blk) & RCTL_GLOBAL_DENY_ALWAYS)
210*7c478bd9Sstevel@tonic-gate 		rctlblk_set_local_action(blk, RCTL_LOCAL_DENY, 0);
211*7c478bd9Sstevel@tonic-gate 	else
212*7c478bd9Sstevel@tonic-gate 		rctlblk_set_local_action(blk, RCTL_LOCAL_NOACTION, 0);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate 	for (; ; val++) {
216*7c478bd9Sstevel@tonic-gate 		switch (*val) {
217*7c478bd9Sstevel@tonic-gate 			case '(':
218*7c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
219*7c478bd9Sstevel@tonic-gate 					error = NESTING;
220*7c478bd9Sstevel@tonic-gate 					break;
221*7c478bd9Sstevel@tonic-gate 				}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 				state |= INPAREN;
224*7c478bd9Sstevel@tonic-gate 				component_head = (char *)val + 1;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 				break;
227*7c478bd9Sstevel@tonic-gate 			case ')':
228*7c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
229*7c478bd9Sstevel@tonic-gate 					*val = '\0';
230*7c478bd9Sstevel@tonic-gate 					if (component < 2) {
231*7c478bd9Sstevel@tonic-gate 						error = BADSPEC;
232*7c478bd9Sstevel@tonic-gate 						break;
233*7c478bd9Sstevel@tonic-gate 					}
234*7c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
235*7c478bd9Sstevel@tonic-gate 					    component_head) == -1) {
236*7c478bd9Sstevel@tonic-gate 						error = BADSPEC;
237*7c478bd9Sstevel@tonic-gate 						break;
238*7c478bd9Sstevel@tonic-gate 					}
239*7c478bd9Sstevel@tonic-gate 					state &= ~INPAREN;
240*7c478bd9Sstevel@tonic-gate 					component = 0;
241*7c478bd9Sstevel@tonic-gate 					valuecount++;
242*7c478bd9Sstevel@tonic-gate 					if (pr_setrctl(Pr, ctl_name, NULL, blk,
243*7c478bd9Sstevel@tonic-gate 					    RCTL_INSERT) == -1)
244*7c478bd9Sstevel@tonic-gate 						error = SETFAILED;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 					/* re-initialize block */
247*7c478bd9Sstevel@tonic-gate 					rctlblk_set_privilege(blk,
248*7c478bd9Sstevel@tonic-gate 					    RCPRIV_PRIVILEGED);
249*7c478bd9Sstevel@tonic-gate 					rctlblk_set_value(blk, 0);
250*7c478bd9Sstevel@tonic-gate 					rctlblk_set_local_flags(blk, 0);
251*7c478bd9Sstevel@tonic-gate 					if (rctlblk_get_global_flags(blk) &
252*7c478bd9Sstevel@tonic-gate 					    RCTL_GLOBAL_DENY_ALWAYS)
253*7c478bd9Sstevel@tonic-gate 						rctlblk_set_local_action(blk,
254*7c478bd9Sstevel@tonic-gate 						    RCTL_LOCAL_DENY, 0);
255*7c478bd9Sstevel@tonic-gate 					else
256*7c478bd9Sstevel@tonic-gate 						rctlblk_set_local_action(blk,
257*7c478bd9Sstevel@tonic-gate 						    RCTL_LOCAL_NOACTION, 0);
258*7c478bd9Sstevel@tonic-gate 				} else {
259*7c478bd9Sstevel@tonic-gate 					error = CLOSEBEFOREOPEN;
260*7c478bd9Sstevel@tonic-gate 				}
261*7c478bd9Sstevel@tonic-gate 				break;
262*7c478bd9Sstevel@tonic-gate 			case ',':
263*7c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
264*7c478bd9Sstevel@tonic-gate 					*val = '\0';
265*7c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
266*7c478bd9Sstevel@tonic-gate 					    component_head) == -1)
267*7c478bd9Sstevel@tonic-gate 						error = BADSPEC;
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 					component++;
270*7c478bd9Sstevel@tonic-gate 					component_head = (char *)val + 1;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 				}
273*7c478bd9Sstevel@tonic-gate 				break;
274*7c478bd9Sstevel@tonic-gate 			case '\0':
275*7c478bd9Sstevel@tonic-gate 				if (valuecount == 0)
276*7c478bd9Sstevel@tonic-gate 					error = BADSPEC;
277*7c478bd9Sstevel@tonic-gate 				else if (state & INPAREN)
278*7c478bd9Sstevel@tonic-gate 					error = UNCLOSED;
279*7c478bd9Sstevel@tonic-gate 				else
280*7c478bd9Sstevel@tonic-gate 					error = COMPLETE;
281*7c478bd9Sstevel@tonic-gate 				break;
282*7c478bd9Sstevel@tonic-gate 			default:
283*7c478bd9Sstevel@tonic-gate 				if (!(state & INPAREN))
284*7c478bd9Sstevel@tonic-gate 					error = BADSPEC;
285*7c478bd9Sstevel@tonic-gate 				break;
286*7c478bd9Sstevel@tonic-gate 		}
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 		if (error)
289*7c478bd9Sstevel@tonic-gate 			break;
290*7c478bd9Sstevel@tonic-gate 	}
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	free(blk);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	if (valuecount == 0)
295*7c478bd9Sstevel@tonic-gate 		error = BADSPEC;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	if (error != COMPLETE)
298*7c478bd9Sstevel@tonic-gate 		return (error);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	return (0);
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate static int
304*7c478bd9Sstevel@tonic-gate rctlwalkfunc(const char *name, void *data)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	if (strcmp(name, (char *)data) == 0)
308*7c478bd9Sstevel@tonic-gate 		return (-1);
309*7c478bd9Sstevel@tonic-gate 	else
310*7c478bd9Sstevel@tonic-gate 		return (0);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate }
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate /*
315*7c478bd9Sstevel@tonic-gate  * This routine determines if /dev/pool device is present on the system and
316*7c478bd9Sstevel@tonic-gate  * pools are currently enabled.  We want to do this directly from libproject
317*7c478bd9Sstevel@tonic-gate  * without using libpool's pool_get_status() routine because pools could be
318*7c478bd9Sstevel@tonic-gate  * completely removed from the system.  Return 1 if pools are enabled, or
319*7c478bd9Sstevel@tonic-gate  * 0 otherwise.  When used inside local zones, always pretend that pools
320*7c478bd9Sstevel@tonic-gate  * are disabled because binding is not allowed and we're already in the
321*7c478bd9Sstevel@tonic-gate  * right pool.
322*7c478bd9Sstevel@tonic-gate  */
323*7c478bd9Sstevel@tonic-gate static int
324*7c478bd9Sstevel@tonic-gate pools_enabled(void)
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate 	pool_status_t status;
327*7c478bd9Sstevel@tonic-gate 	int fd;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID)
330*7c478bd9Sstevel@tonic-gate 		return (0);
331*7c478bd9Sstevel@tonic-gate 	if ((fd = open("/dev/pool", O_RDONLY)) < 0)
332*7c478bd9Sstevel@tonic-gate 		return (0);
333*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
334*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
335*7c478bd9Sstevel@tonic-gate 		return (0);
336*7c478bd9Sstevel@tonic-gate 	}
337*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
338*7c478bd9Sstevel@tonic-gate 	return (status.ps_io_state);
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate /*
342*7c478bd9Sstevel@tonic-gate  * A pool_name of NULL means to attempt to bind to the default pool.
343*7c478bd9Sstevel@tonic-gate  * If the "force" flag is non-zero, the value of "system.bind-default" will be
344*7c478bd9Sstevel@tonic-gate  * ignored, and the process will be bound to the default pool if one exists.
345*7c478bd9Sstevel@tonic-gate  */
346*7c478bd9Sstevel@tonic-gate static int
347*7c478bd9Sstevel@tonic-gate bind_to_pool(const char *pool_name, pid_t pid, int force)
348*7c478bd9Sstevel@tonic-gate {
349*7c478bd9Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
350*7c478bd9Sstevel@tonic-gate 	pool_t **pools;
351*7c478bd9Sstevel@tonic-gate 	uint_t nelem;
352*7c478bd9Sstevel@tonic-gate 	uchar_t bval;
353*7c478bd9Sstevel@tonic-gate 	pool_conf_t *conf;
354*7c478bd9Sstevel@tonic-gate 	const char *nm;
355*7c478bd9Sstevel@tonic-gate 	int retval;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
358*7c478bd9Sstevel@tonic-gate 		return (-1);
359*7c478bd9Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
360*7c478bd9Sstevel@tonic-gate 		/*
361*7c478bd9Sstevel@tonic-gate 		 * Pools configuration file is corrupted; allow logins.
362*7c478bd9Sstevel@tonic-gate 		 */
363*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
364*7c478bd9Sstevel@tonic-gate 		return (0);
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 	if (pool_name != NULL && pool_get_pool(conf, pool_name) != NULL) {
367*7c478bd9Sstevel@tonic-gate 		/*
368*7c478bd9Sstevel@tonic-gate 		 * There was a project.pool entry, and the pool it refers to
369*7c478bd9Sstevel@tonic-gate 		 * is a valid (active) pool.
370*7c478bd9Sstevel@tonic-gate 		 */
371*7c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
372*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
373*7c478bd9Sstevel@tonic-gate 		if (pool_set_binding(pool_name, P_PID, pid) != PO_SUCCESS) {
374*7c478bd9Sstevel@tonic-gate 			if (pool_error() != POE_SYSTEM)
375*7c478bd9Sstevel@tonic-gate 				errno = EINVAL;
376*7c478bd9Sstevel@tonic-gate 			return (-1);
377*7c478bd9Sstevel@tonic-gate 		}
378*7c478bd9Sstevel@tonic-gate 		return (0);
379*7c478bd9Sstevel@tonic-gate 	}
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	/*
382*7c478bd9Sstevel@tonic-gate 	 * Bind to the pool with 'pool.default' = 'true' if
383*7c478bd9Sstevel@tonic-gate 	 * 'system.bind-default' = 'true'.
384*7c478bd9Sstevel@tonic-gate 	 */
385*7c478bd9Sstevel@tonic-gate 	if ((pvals[0] = pool_value_alloc()) == NULL) {
386*7c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
387*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
388*7c478bd9Sstevel@tonic-gate 		return (-1);
389*7c478bd9Sstevel@tonic-gate 	}
390*7c478bd9Sstevel@tonic-gate 	if (!force && pool_get_property(conf, pool_conf_to_elem(conf),
391*7c478bd9Sstevel@tonic-gate 	    "system.bind-default", pvals[0]) != POC_BOOL ||
392*7c478bd9Sstevel@tonic-gate 	    pool_value_get_bool(pvals[0], &bval) != PO_SUCCESS ||
393*7c478bd9Sstevel@tonic-gate 	    bval == PO_FALSE) {
394*7c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
395*7c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
396*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
397*7c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
398*7c478bd9Sstevel@tonic-gate 		return (-1);
399*7c478bd9Sstevel@tonic-gate 	}
400*7c478bd9Sstevel@tonic-gate 	(void) pool_value_set_name(pvals[0], "pool.default");
401*7c478bd9Sstevel@tonic-gate 	pool_value_set_bool(pvals[0], PO_TRUE);
402*7c478bd9Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, pvals)) == NULL) {
403*7c478bd9Sstevel@tonic-gate 		/*
404*7c478bd9Sstevel@tonic-gate 		 * No default pools exist.
405*7c478bd9Sstevel@tonic-gate 		 */
406*7c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
407*7c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
408*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
409*7c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
410*7c478bd9Sstevel@tonic-gate 		return (-1);
411*7c478bd9Sstevel@tonic-gate 	}
412*7c478bd9Sstevel@tonic-gate 	if (nelem != 1 ||
413*7c478bd9Sstevel@tonic-gate 	    pool_get_property(conf, pool_to_elem(conf, pools[0]), "pool.name",
414*7c478bd9Sstevel@tonic-gate 	    pvals[0]) != POC_STRING) {
415*7c478bd9Sstevel@tonic-gate 		/*
416*7c478bd9Sstevel@tonic-gate 		 * Configuration is invalid.
417*7c478bd9Sstevel@tonic-gate 		 */
418*7c478bd9Sstevel@tonic-gate 		free(pools);
419*7c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
420*7c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
421*7c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
422*7c478bd9Sstevel@tonic-gate 		return (0);
423*7c478bd9Sstevel@tonic-gate 	}
424*7c478bd9Sstevel@tonic-gate 	free(pools);
425*7c478bd9Sstevel@tonic-gate 	(void) pool_conf_close(conf);
426*7c478bd9Sstevel@tonic-gate 	pool_conf_free(conf);
427*7c478bd9Sstevel@tonic-gate 	(void) pool_value_get_string(pvals[0], &nm);
428*7c478bd9Sstevel@tonic-gate 	if (pool_set_binding(nm, P_PID, pid) != PO_SUCCESS) {
429*7c478bd9Sstevel@tonic-gate 		if (pool_error() != POE_SYSTEM)
430*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
431*7c478bd9Sstevel@tonic-gate 		retval = -1;
432*7c478bd9Sstevel@tonic-gate 	} else {
433*7c478bd9Sstevel@tonic-gate 		retval = 0;
434*7c478bd9Sstevel@tonic-gate 	}
435*7c478bd9Sstevel@tonic-gate 	pool_value_free(pvals[0]);
436*7c478bd9Sstevel@tonic-gate 	return (retval);
437*7c478bd9Sstevel@tonic-gate }
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate /*
440*7c478bd9Sstevel@tonic-gate  * Changes the assigned project, task and resource pool of a stopped target
441*7c478bd9Sstevel@tonic-gate  * process.
442*7c478bd9Sstevel@tonic-gate  *
443*7c478bd9Sstevel@tonic-gate  * We may not have access to the project table if our target process is in
444*7c478bd9Sstevel@tonic-gate  * getprojbyname()'s execution path. Similarly, we may not be able to get user
445*7c478bd9Sstevel@tonic-gate  * information if the target process is in getpwnam()'s execution path. Thus we
446*7c478bd9Sstevel@tonic-gate  * give the caller the option of skipping these checks by providing a pointer to
447*7c478bd9Sstevel@tonic-gate  * a pre-validated project structure in proj (whose name matches project_name)
448*7c478bd9Sstevel@tonic-gate  * and taking responsibility for ensuring that the target process' owner is a
449*7c478bd9Sstevel@tonic-gate  * member of the target project.
450*7c478bd9Sstevel@tonic-gate  *
451*7c478bd9Sstevel@tonic-gate  * Callers of this function should always provide a pre-validated project
452*7c478bd9Sstevel@tonic-gate  * structure in proj unless they can be sure that the target process will never
453*7c478bd9Sstevel@tonic-gate  * be in setproject_proc()'s execution path.
454*7c478bd9Sstevel@tonic-gate  */
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate projid_t
457*7c478bd9Sstevel@tonic-gate setproject_proc(const char *project_name, const char *user_name, int flags,
458*7c478bd9Sstevel@tonic-gate     pid_t pid, struct ps_prochandle *Pr, struct project *proj)
459*7c478bd9Sstevel@tonic-gate {
460*7c478bd9Sstevel@tonic-gate 	char pwdbuf[NSS_BUFLEN_PASSWD];
461*7c478bd9Sstevel@tonic-gate 	char prbuf[PROJECT_BUFSZ];
462*7c478bd9Sstevel@tonic-gate 	projid_t projid;
463*7c478bd9Sstevel@tonic-gate 	struct passwd pwd;
464*7c478bd9Sstevel@tonic-gate 	int i;
465*7c478bd9Sstevel@tonic-gate 	int unknown = 0;
466*7c478bd9Sstevel@tonic-gate 	int ret = 0;
467*7c478bd9Sstevel@tonic-gate 	kva_t *kv_array;
468*7c478bd9Sstevel@tonic-gate 	struct project local_proj; /* space to store proj if not provided */
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 	if (project_name != NULL) {
471*7c478bd9Sstevel@tonic-gate 		/*
472*7c478bd9Sstevel@tonic-gate 		 * Sanity checks.
473*7c478bd9Sstevel@tonic-gate 		 */
474*7c478bd9Sstevel@tonic-gate 		if (strcmp(project_name, "") == 0 ||
475*7c478bd9Sstevel@tonic-gate 		    user_name == NULL) {
476*7c478bd9Sstevel@tonic-gate 			errno = EINVAL;
477*7c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
478*7c478bd9Sstevel@tonic-gate 		}
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 		/*
481*7c478bd9Sstevel@tonic-gate 		 * If proj is NULL, acquire project information to ensure that
482*7c478bd9Sstevel@tonic-gate 		 * project_name is a valid project, and confirm that user_name
483*7c478bd9Sstevel@tonic-gate 		 * exists and is a member of the specified project.
484*7c478bd9Sstevel@tonic-gate 		 */
485*7c478bd9Sstevel@tonic-gate 		if (proj == NULL) {
486*7c478bd9Sstevel@tonic-gate 			if ((proj = getprojbyname(project_name, &local_proj,
487*7c478bd9Sstevel@tonic-gate 			    prbuf, PROJECT_BUFSZ)) == NULL) {
488*7c478bd9Sstevel@tonic-gate 				errno = ESRCH;
489*7c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
490*7c478bd9Sstevel@tonic-gate 			}
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 			if (getpwnam_r(user_name, &pwd,
493*7c478bd9Sstevel@tonic-gate 			    pwdbuf, NSS_BUFLEN_PASSWD) == NULL) {
494*7c478bd9Sstevel@tonic-gate 				errno = ESRCH;
495*7c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
496*7c478bd9Sstevel@tonic-gate 			}
497*7c478bd9Sstevel@tonic-gate 			/*
498*7c478bd9Sstevel@tonic-gate 			 * Root can join any project.
499*7c478bd9Sstevel@tonic-gate 			 */
500*7c478bd9Sstevel@tonic-gate 			if (pwd.pw_uid != (uid_t)0 &&
501*7c478bd9Sstevel@tonic-gate 			    !inproj(user_name, project_name, prbuf,
502*7c478bd9Sstevel@tonic-gate 			    PROJECT_BUFSZ)) {
503*7c478bd9Sstevel@tonic-gate 				errno = ESRCH;
504*7c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
505*7c478bd9Sstevel@tonic-gate 			}
506*7c478bd9Sstevel@tonic-gate 		}
507*7c478bd9Sstevel@tonic-gate 		projid = proj->pj_projid;
508*7c478bd9Sstevel@tonic-gate 	} else {
509*7c478bd9Sstevel@tonic-gate 		projid = getprojid();
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	/*
513*7c478bd9Sstevel@tonic-gate 	 * Only bind to a pool if pools are configured.
514*7c478bd9Sstevel@tonic-gate 	 */
515*7c478bd9Sstevel@tonic-gate 	if (pools_enabled() == 1) {
516*7c478bd9Sstevel@tonic-gate 		const char *pool_name = NULL;
517*7c478bd9Sstevel@tonic-gate 		char *old_pool_name;
518*7c478bd9Sstevel@tonic-gate 		int taskflags = flags;
519*7c478bd9Sstevel@tonic-gate 		/*
520*7c478bd9Sstevel@tonic-gate 		 * Attempt to bind to pool before calling
521*7c478bd9Sstevel@tonic-gate 		 * settaskid().
522*7c478bd9Sstevel@tonic-gate 		 */
523*7c478bd9Sstevel@tonic-gate 		if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
524*7c478bd9Sstevel@tonic-gate 		    KV_DELIMITER)) != NULL) {
525*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < kv_array->length; i++) {
526*7c478bd9Sstevel@tonic-gate 				if (strcmp(kv_array->data[i].key,
527*7c478bd9Sstevel@tonic-gate 				    "project.pool") == 0) {
528*7c478bd9Sstevel@tonic-gate 					pool_name = kv_array->data[i].value;
529*7c478bd9Sstevel@tonic-gate 					break;
530*7c478bd9Sstevel@tonic-gate 				}
531*7c478bd9Sstevel@tonic-gate 				if (strcmp(kv_array->data[i].key,
532*7c478bd9Sstevel@tonic-gate 				    "task.final") == 0) {
533*7c478bd9Sstevel@tonic-gate 					taskflags |= TASK_FINAL;
534*7c478bd9Sstevel@tonic-gate 				}
535*7c478bd9Sstevel@tonic-gate 			}
536*7c478bd9Sstevel@tonic-gate 		}
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 		old_pool_name = pool_get_binding(pid);
539*7c478bd9Sstevel@tonic-gate 		if (bind_to_pool(pool_name, pid, 0) != 0) {
540*7c478bd9Sstevel@tonic-gate 			if (old_pool_name)
541*7c478bd9Sstevel@tonic-gate 				free(old_pool_name);
542*7c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
543*7c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_POOL);
544*7c478bd9Sstevel@tonic-gate 		}
545*7c478bd9Sstevel@tonic-gate 		if (pr_settaskid(Pr, projid, taskflags) == -1) {
546*7c478bd9Sstevel@tonic-gate 			int saved_errno = errno;
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 			/*
549*7c478bd9Sstevel@tonic-gate 			 * Undo pool binding.
550*7c478bd9Sstevel@tonic-gate 			 */
551*7c478bd9Sstevel@tonic-gate 			(void) bind_to_pool(old_pool_name, pid, 1);
552*7c478bd9Sstevel@tonic-gate 			if (old_pool_name)
553*7c478bd9Sstevel@tonic-gate 				free(old_pool_name);
554*7c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
555*7c478bd9Sstevel@tonic-gate 			/*
556*7c478bd9Sstevel@tonic-gate 			 * Restore errno
557*7c478bd9Sstevel@tonic-gate 			 */
558*7c478bd9Sstevel@tonic-gate 			errno = saved_errno;
559*7c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
560*7c478bd9Sstevel@tonic-gate 		}
561*7c478bd9Sstevel@tonic-gate 		if (old_pool_name)
562*7c478bd9Sstevel@tonic-gate 			free(old_pool_name);
563*7c478bd9Sstevel@tonic-gate 	} else {
564*7c478bd9Sstevel@tonic-gate 		/*
565*7c478bd9Sstevel@tonic-gate 		 * Pools are not configured, so simply create new task.
566*7c478bd9Sstevel@tonic-gate 		 */
567*7c478bd9Sstevel@tonic-gate 		if (pr_settaskid(Pr, projid, flags) == -1)
568*7c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
569*7c478bd9Sstevel@tonic-gate 		kv_array = _str2kva(proj->pj_attr, KV_ASSIGN, KV_DELIMITER);
570*7c478bd9Sstevel@tonic-gate 	}
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	if (project_name == NULL) {
573*7c478bd9Sstevel@tonic-gate 		/*
574*7c478bd9Sstevel@tonic-gate 		 * In the case that we are starting a new task in the
575*7c478bd9Sstevel@tonic-gate 		 * current project, we are finished, since the current
576*7c478bd9Sstevel@tonic-gate 		 * resource controls will still apply. (Implicit behaviour:
577*7c478bd9Sstevel@tonic-gate 		 * a project must be entirely logged out before name
578*7c478bd9Sstevel@tonic-gate 		 * service changes will take effect.)
579*7c478bd9Sstevel@tonic-gate 		 */
580*7c478bd9Sstevel@tonic-gate 		_kva_free(kv_array);
581*7c478bd9Sstevel@tonic-gate 		return (projid);
582*7c478bd9Sstevel@tonic-gate 	}
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 	if (kv_array == NULL)
585*7c478bd9Sstevel@tonic-gate 		return (0);
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < kv_array->length; i++) {
588*7c478bd9Sstevel@tonic-gate 		/*
589*7c478bd9Sstevel@tonic-gate 		 * Providing a special, i.e. a non-resource control, key?  Then
590*7c478bd9Sstevel@tonic-gate 		 * parse that key here and end with "continue;".
591*7c478bd9Sstevel@tonic-gate 		 */
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 		/*
594*7c478bd9Sstevel@tonic-gate 		 * For generic bindings, the kernel performs the binding, as
595*7c478bd9Sstevel@tonic-gate 		 * these are resource controls advertised by kernel subsystems.
596*7c478bd9Sstevel@tonic-gate 		 */
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 		/*
599*7c478bd9Sstevel@tonic-gate 		 * Check for known attribute name.
600*7c478bd9Sstevel@tonic-gate 		 */
601*7c478bd9Sstevel@tonic-gate 		errno = 0;
602*7c478bd9Sstevel@tonic-gate 		if (rctl_walk(rctlwalkfunc, (void *)kv_array->data[i].key)
603*7c478bd9Sstevel@tonic-gate 		    == 0)
604*7c478bd9Sstevel@tonic-gate 			continue;
605*7c478bd9Sstevel@tonic-gate 		if (errno) {
606*7c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
607*7c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
608*7c478bd9Sstevel@tonic-gate 		}
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 		ret = rctl_set(kv_array->data[i].key,
611*7c478bd9Sstevel@tonic-gate 		    kv_array->data[i].value, Pr);
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 		if (ret && unknown == 0) {
614*7c478bd9Sstevel@tonic-gate 			/*
615*7c478bd9Sstevel@tonic-gate 			 * We only report the first failure.
616*7c478bd9Sstevel@tonic-gate 			 */
617*7c478bd9Sstevel@tonic-gate 			unknown = i + 1;
618*7c478bd9Sstevel@tonic-gate 		}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 		if (ret && ret != SETFAILED) {
621*7c478bd9Sstevel@tonic-gate 			/*
622*7c478bd9Sstevel@tonic-gate 			 * We abort if we couldn't set a component, but if
623*7c478bd9Sstevel@tonic-gate 			 * it's merely that the system didn't recognize it, we
624*7c478bd9Sstevel@tonic-gate 			 * continue, as this could be a third party attribute.
625*7c478bd9Sstevel@tonic-gate 			 */
626*7c478bd9Sstevel@tonic-gate 			break;
627*7c478bd9Sstevel@tonic-gate 		}
628*7c478bd9Sstevel@tonic-gate 	}
629*7c478bd9Sstevel@tonic-gate 	_kva_free(kv_array);
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	return (unknown);
632*7c478bd9Sstevel@tonic-gate }
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate projid_t
635*7c478bd9Sstevel@tonic-gate setproject(const char *project_name, const char *user_name, int flags)
636*7c478bd9Sstevel@tonic-gate {
637*7c478bd9Sstevel@tonic-gate 	return (setproject_proc(project_name, user_name, flags, P_MYID, NULL,
638*7c478bd9Sstevel@tonic-gate 	    NULL));
639*7c478bd9Sstevel@tonic-gate }
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate priv_set_t *
643*7c478bd9Sstevel@tonic-gate setproject_initpriv(void)
644*7c478bd9Sstevel@tonic-gate {
645*7c478bd9Sstevel@tonic-gate 	static priv_t taskpriv = PRIV_PROC_TASKID;
646*7c478bd9Sstevel@tonic-gate 	static priv_t rctlpriv = PRIV_SYS_RESOURCE;
647*7c478bd9Sstevel@tonic-gate 	static priv_t poolpriv = PRIV_SYS_RES_CONFIG;
648*7c478bd9Sstevel@tonic-gate 	static priv_t schedpriv = PRIV_PROC_PRIOCNTL;
649*7c478bd9Sstevel@tonic-gate 	int res;
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	priv_set_t *nset;
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
654*7c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, poolpriv,
655*7c478bd9Sstevel@tonic-gate 		    schedpriv, (char *)NULL);
656*7c478bd9Sstevel@tonic-gate 	} else {
657*7c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, (char *)NULL);
658*7c478bd9Sstevel@tonic-gate 	}
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	if (res != 0)
661*7c478bd9Sstevel@tonic-gate 		return (NULL);
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	nset = priv_allocset();
664*7c478bd9Sstevel@tonic-gate 	if (nset != NULL) {
665*7c478bd9Sstevel@tonic-gate 		priv_emptyset(nset);
666*7c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, taskpriv);
667*7c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, rctlpriv);
668*7c478bd9Sstevel@tonic-gate 		/*
669*7c478bd9Sstevel@tonic-gate 		 * Only need these if we need to change pools, which can
670*7c478bd9Sstevel@tonic-gate 		 * only happen if the target is in the global zone.  Rather
671*7c478bd9Sstevel@tonic-gate 		 * than checking the target's zone just check our own
672*7c478bd9Sstevel@tonic-gate 		 * (since if we're in a non-global zone we won't be able
673*7c478bd9Sstevel@tonic-gate 		 * to control processes in other zones).
674*7c478bd9Sstevel@tonic-gate 		 */
675*7c478bd9Sstevel@tonic-gate 		if (getzoneid() == GLOBAL_ZONEID) {
676*7c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, poolpriv);
677*7c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, schedpriv);
678*7c478bd9Sstevel@tonic-gate 		}
679*7c478bd9Sstevel@tonic-gate 	}
680*7c478bd9Sstevel@tonic-gate 	return (nset);
681*7c478bd9Sstevel@tonic-gate }
682