xref: /onnv-gate/usr/src/lib/libproject/common/setproject.c (revision 12932:f73b349ded5b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53247Sgjelinek  * Common Development and Distribution License (the "License").
63247Sgjelinek  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12932SRalph.Turner@Sun.COM  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/task.h>
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <unistd.h>
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <ctype.h>
310Sstevel@tonic-gate #include <project.h>
320Sstevel@tonic-gate #include <rctl.h>
330Sstevel@tonic-gate #include <secdb.h>
340Sstevel@tonic-gate #include <signal.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
373684Srd117015 #include <strings.h>
380Sstevel@tonic-gate #include <nss_dbdefs.h>
390Sstevel@tonic-gate #include <pwd.h>
400Sstevel@tonic-gate #include <pool.h>
410Sstevel@tonic-gate #include <libproc.h>
420Sstevel@tonic-gate #include <priv.h>
430Sstevel@tonic-gate #include <priv_utils.h>
440Sstevel@tonic-gate #include <zone.h>
450Sstevel@tonic-gate #include <sys/pool.h>
460Sstevel@tonic-gate #include <sys/pool_impl.h>
473684Srd117015 #include <sys/rctl_impl.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static void
xstrtolower(char * s)500Sstevel@tonic-gate xstrtolower(char *s)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	for (; *s != '\0'; s++)
530Sstevel@tonic-gate 		*s = tolower(*s);
540Sstevel@tonic-gate }
550Sstevel@tonic-gate 
560Sstevel@tonic-gate static void
remove_spaces(char * s)570Sstevel@tonic-gate remove_spaces(char *s)
580Sstevel@tonic-gate {
590Sstevel@tonic-gate 	char *current;
600Sstevel@tonic-gate 	char *next;
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	current = next = s;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	while (*next != '\0') {
650Sstevel@tonic-gate 		while (isspace(*next))
66*12932SRalph.Turner@Sun.COM 			next++;
670Sstevel@tonic-gate 		*current++ = *next++;
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 	*current = '\0';
700Sstevel@tonic-gate }
710Sstevel@tonic-gate 
720Sstevel@tonic-gate int
build_rctlblk(rctlblk_t * blk,int comp_num,char * component)730Sstevel@tonic-gate build_rctlblk(rctlblk_t *blk, int comp_num, char *component)
740Sstevel@tonic-gate {
750Sstevel@tonic-gate 	char *signam;
760Sstevel@tonic-gate 	int sig = 0;
770Sstevel@tonic-gate 	uint_t act = rctlblk_get_local_action(blk, &sig);
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	if (comp_num == 0) {
800Sstevel@tonic-gate 		/*
810Sstevel@tonic-gate 		 * Setting privilege level for resource control block.
820Sstevel@tonic-gate 		 */
830Sstevel@tonic-gate 		xstrtolower(component);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 		if (strcmp("basic", component) == 0) {
860Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_BASIC);
870Sstevel@tonic-gate 			return (0);
880Sstevel@tonic-gate 		}
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 		if (strcmp("priv", component) == 0 ||
910Sstevel@tonic-gate 		    strcmp("privileged", component) == 0) {
920Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
930Sstevel@tonic-gate 			return (0);
940Sstevel@tonic-gate 		}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 		return (-1);
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	if (comp_num == 1) {
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 		/*
1020Sstevel@tonic-gate 		 * Setting value for resource control block.
1030Sstevel@tonic-gate 		 */
1040Sstevel@tonic-gate 		unsigned long long val;
1050Sstevel@tonic-gate 		char *t;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 		/* Negative numbers are not allowed */
1080Sstevel@tonic-gate 		if (strchr(component, '-') != NULL)
1090Sstevel@tonic-gate 			return (-1);
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 		errno = 0;
1120Sstevel@tonic-gate 		val = strtoull(component, &t, 10);
1130Sstevel@tonic-gate 		if (errno != 0 || t == component || *t != '\0')
1140Sstevel@tonic-gate 			return (-1);
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 		rctlblk_set_value(blk, (rctl_qty_t)val);
1170Sstevel@tonic-gate 		return (0);
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	/*
1210Sstevel@tonic-gate 	 * Setting one or more actions on this resource control block.
1220Sstevel@tonic-gate 	 */
1230Sstevel@tonic-gate 	if (comp_num >= 2) {
1240Sstevel@tonic-gate 		if (strcmp("none", component) == 0) {
1250Sstevel@tonic-gate 			rctlblk_set_local_action(blk, 0, 0);
1260Sstevel@tonic-gate 			return (0);
1270Sstevel@tonic-gate 		}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 		if (strcmp("deny", component) == 0) {
1300Sstevel@tonic-gate 			act |= RCTL_LOCAL_DENY;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 			return (0);
1350Sstevel@tonic-gate 		}
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		/*
1380Sstevel@tonic-gate 		 * The last, and trickiest, form of action is the signal
1390Sstevel@tonic-gate 		 * specification.
1400Sstevel@tonic-gate 		 */
1410Sstevel@tonic-gate 		if ((signam = strchr(component, '=')) == NULL)
1420Sstevel@tonic-gate 			return (-1);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 		*signam++ = '\0';
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 		if (strcmp("sig", component) == 0 ||
1470Sstevel@tonic-gate 		    strcmp("signal", component) == 0) {
1480Sstevel@tonic-gate 			if (strncmp("SIG", signam, 3) == 0)
1490Sstevel@tonic-gate 				signam += 3;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 			if (str2sig(signam, &sig) == -1)
1520Sstevel@tonic-gate 				return (-1);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 			act |= RCTL_LOCAL_SIGNAL;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 			return (0);
1590Sstevel@tonic-gate 		}
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 	return (-1);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate  * States:
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate #define	INPAREN		0x1
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Errors:
1710Sstevel@tonic-gate  */
1720Sstevel@tonic-gate #define	SETFAILED	(-1)
1730Sstevel@tonic-gate #define	COMPLETE	1
1740Sstevel@tonic-gate #define	NESTING		2
1750Sstevel@tonic-gate #define	UNCLOSED	3
1760Sstevel@tonic-gate #define	CLOSEBEFOREOPEN	4
1770Sstevel@tonic-gate #define	BADSPEC		5
1780Sstevel@tonic-gate 
179*12932SRalph.Turner@Sun.COM static void
reinit_blk(rctlblk_t * blk,int local_action)180*12932SRalph.Turner@Sun.COM reinit_blk(rctlblk_t *blk, int local_action)
181*12932SRalph.Turner@Sun.COM {
182*12932SRalph.Turner@Sun.COM 	rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
183*12932SRalph.Turner@Sun.COM 	rctlblk_set_value(blk, 0);
184*12932SRalph.Turner@Sun.COM 	rctlblk_set_local_flags(blk, 0);
185*12932SRalph.Turner@Sun.COM 	rctlblk_set_local_action(blk, local_action, 0);
186*12932SRalph.Turner@Sun.COM }
187*12932SRalph.Turner@Sun.COM 
1880Sstevel@tonic-gate static int
rctl_set(char * ctl_name,char * val,struct ps_prochandle * Pr,int flags)1893684Srd117015 rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr, int flags)
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate 	int error = 0;
1920Sstevel@tonic-gate 	uint_t component = 0;
1930Sstevel@tonic-gate 	int valuecount = 0;
1940Sstevel@tonic-gate 	uint_t state = 0;
1950Sstevel@tonic-gate 	char *component_head;
1960Sstevel@tonic-gate 	rctlblk_t *blk;
1973684Srd117015 	rctlblk_t *ablk;
1983684Srd117015 	int project_entity = 0;
1993684Srd117015 	int count = 0;
2003684Srd117015 	char *tmp;
201*12932SRalph.Turner@Sun.COM 	int local_act;
202*12932SRalph.Turner@Sun.COM 	rctlblk_t *rlast;
203*12932SRalph.Turner@Sun.COM 	rctlblk_t *rnext;
204*12932SRalph.Turner@Sun.COM 	rctlblk_t *rtmp;
205*12932SRalph.Turner@Sun.COM 	int teardown_basic = 0;
206*12932SRalph.Turner@Sun.COM 	int teardown_priv = 0;
2070Sstevel@tonic-gate 
2083684Srd117015 	/* We cannot modify a zone resource control */
2093684Srd117015 	if (strncmp(ctl_name, "zone.", strlen("zone.")) == 0) {
2100Sstevel@tonic-gate 		return (SETFAILED);
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 
2133684Srd117015 	remove_spaces(val);
2143684Srd117015 
215*12932SRalph.Turner@Sun.COM 	if (strncmp(ctl_name, "project.", strlen("project.")) == 0) {
2163684Srd117015 		project_entity = 1;
217*12932SRalph.Turner@Sun.COM 	} else if ((strncmp(ctl_name, "process.", strlen("process.")) != 0) &&
218*12932SRalph.Turner@Sun.COM 	    (strncmp(ctl_name, "task.", strlen("task.")) != 0)) {
2193684Srd117015 		return (SETFAILED);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 
222*12932SRalph.Turner@Sun.COM 	/* Determine how many attributes we'll be setting */
223*12932SRalph.Turner@Sun.COM 	for (tmp = val; *tmp != '\0'; tmp++) {
224*12932SRalph.Turner@Sun.COM 		if (*tmp == '(')
225*12932SRalph.Turner@Sun.COM 			count++;
226*12932SRalph.Turner@Sun.COM 	}
227*12932SRalph.Turner@Sun.COM 	/* Allocate sufficient memory for rctl blocks */
228*12932SRalph.Turner@Sun.COM 	if ((count == 0) || ((ablk =
229*12932SRalph.Turner@Sun.COM 	    (rctlblk_t *)malloc(rctlblk_size() * count)) == NULL)) {
230*12932SRalph.Turner@Sun.COM 		return (SETFAILED);
231*12932SRalph.Turner@Sun.COM 	}
232*12932SRalph.Turner@Sun.COM 	blk = ablk;
233*12932SRalph.Turner@Sun.COM 
234*12932SRalph.Turner@Sun.COM 	/*
235*12932SRalph.Turner@Sun.COM 	 * In order to set the new rctl's local_action, we'll need the
236*12932SRalph.Turner@Sun.COM 	 * current value of global_flags.  We obtain global_flags by
237*12932SRalph.Turner@Sun.COM 	 * performing a pr_getrctl().
238*12932SRalph.Turner@Sun.COM 	 *
239*12932SRalph.Turner@Sun.COM 	 * The ctl_name has been verified as valid, so we have no reason
240*12932SRalph.Turner@Sun.COM 	 * to suspect that pr_getrctl() will return an error.
241*12932SRalph.Turner@Sun.COM 	 */
242*12932SRalph.Turner@Sun.COM 	(void) pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST);
243*12932SRalph.Turner@Sun.COM 
244*12932SRalph.Turner@Sun.COM 
2450Sstevel@tonic-gate 	/*
2460Sstevel@tonic-gate 	 * Set initial local action based on global deny properties.
2470Sstevel@tonic-gate 	 */
2480Sstevel@tonic-gate 	rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
2490Sstevel@tonic-gate 	rctlblk_set_value(blk, 0);
2500Sstevel@tonic-gate 	rctlblk_set_local_flags(blk, 0);
2513684Srd117015 
2520Sstevel@tonic-gate 	if (rctlblk_get_global_flags(blk) & RCTL_GLOBAL_DENY_ALWAYS)
253*12932SRalph.Turner@Sun.COM 		local_act = RCTL_LOCAL_DENY;
2540Sstevel@tonic-gate 	else
255*12932SRalph.Turner@Sun.COM 		local_act = RCTL_LOCAL_NOACTION;
2560Sstevel@tonic-gate 
257*12932SRalph.Turner@Sun.COM 	rctlblk_set_local_action(blk, local_act, 0);
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	for (; ; val++) {
260*12932SRalph.Turner@Sun.COM 
2610Sstevel@tonic-gate 		switch (*val) {
2620Sstevel@tonic-gate 			case '(':
2630Sstevel@tonic-gate 				if (state & INPAREN) {
2640Sstevel@tonic-gate 					error = NESTING;
2650Sstevel@tonic-gate 					break;
2660Sstevel@tonic-gate 				}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 				state |= INPAREN;
2690Sstevel@tonic-gate 				component_head = (char *)val + 1;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 				break;
2720Sstevel@tonic-gate 			case ')':
2730Sstevel@tonic-gate 				if (state & INPAREN) {
2740Sstevel@tonic-gate 					*val = '\0';
2750Sstevel@tonic-gate 					if (component < 2) {
2760Sstevel@tonic-gate 						error = BADSPEC;
2770Sstevel@tonic-gate 						break;
2780Sstevel@tonic-gate 					}
2790Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
2800Sstevel@tonic-gate 					    component_head) == -1) {
2810Sstevel@tonic-gate 						error = BADSPEC;
2820Sstevel@tonic-gate 						break;
2830Sstevel@tonic-gate 					}
2840Sstevel@tonic-gate 					state &= ~INPAREN;
2850Sstevel@tonic-gate 					component = 0;
2860Sstevel@tonic-gate 					valuecount++;
2873684Srd117015 
2883684Srd117015 					if (project_entity &&
2893684Srd117015 					    (rctlblk_get_privilege(blk) ==
2903684Srd117015 					    RCPRIV_BASIC)) {
2910Sstevel@tonic-gate 						error = SETFAILED;
292*12932SRalph.Turner@Sun.COM 					} else {
293*12932SRalph.Turner@Sun.COM 						if (rctlblk_get_privilege(blk)
294*12932SRalph.Turner@Sun.COM 						    == RCPRIV_BASIC)
295*12932SRalph.Turner@Sun.COM 							teardown_basic = 1;
296*12932SRalph.Turner@Sun.COM 
297*12932SRalph.Turner@Sun.COM 						if (rctlblk_get_privilege(blk)
298*12932SRalph.Turner@Sun.COM 						    == RCPRIV_PRIVILEGED)
299*12932SRalph.Turner@Sun.COM 							teardown_priv = 1;
300*12932SRalph.Turner@Sun.COM 
301*12932SRalph.Turner@Sun.COM 						if (valuecount > count) {
302*12932SRalph.Turner@Sun.COM 							free(ablk);
3033684Srd117015 							return (SETFAILED);
304*12932SRalph.Turner@Sun.COM 						}
3053684Srd117015 
306*12932SRalph.Turner@Sun.COM 						if (valuecount != count) {
3073684Srd117015 							blk = RCTLBLK_INC(ablk,
308*12932SRalph.Turner@Sun.COM 							    valuecount);
309*12932SRalph.Turner@Sun.COM 							/* re-initialize blk */
310*12932SRalph.Turner@Sun.COM 							reinit_blk(blk,
311*12932SRalph.Turner@Sun.COM 							    local_act);
312*12932SRalph.Turner@Sun.COM 						}
3133684Srd117015 					}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 				} else {
3160Sstevel@tonic-gate 					error = CLOSEBEFOREOPEN;
3170Sstevel@tonic-gate 				}
3180Sstevel@tonic-gate 				break;
3190Sstevel@tonic-gate 			case ',':
3200Sstevel@tonic-gate 				if (state & INPAREN) {
3210Sstevel@tonic-gate 					*val = '\0';
3220Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
3230Sstevel@tonic-gate 					    component_head) == -1)
3240Sstevel@tonic-gate 						error = BADSPEC;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 					component++;
3270Sstevel@tonic-gate 					component_head = (char *)val + 1;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 				}
3300Sstevel@tonic-gate 				break;
3310Sstevel@tonic-gate 			case '\0':
3320Sstevel@tonic-gate 				if (valuecount == 0)
3330Sstevel@tonic-gate 					error = BADSPEC;
3340Sstevel@tonic-gate 				else if (state & INPAREN)
3350Sstevel@tonic-gate 					error = UNCLOSED;
3360Sstevel@tonic-gate 				else
3370Sstevel@tonic-gate 					error = COMPLETE;
3380Sstevel@tonic-gate 				break;
3390Sstevel@tonic-gate 			default:
3400Sstevel@tonic-gate 				if (!(state & INPAREN))
3410Sstevel@tonic-gate 					error = BADSPEC;
3420Sstevel@tonic-gate 				break;
3430Sstevel@tonic-gate 		}
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 		if (error)
3460Sstevel@tonic-gate 			break;
3470Sstevel@tonic-gate 	}
348*12932SRalph.Turner@Sun.COM 	/* ablk points to array of rctlblk_t */
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	if (valuecount == 0)
3510Sstevel@tonic-gate 		error = BADSPEC;
3520Sstevel@tonic-gate 
353*12932SRalph.Turner@Sun.COM 	if (error != COMPLETE) {
354*12932SRalph.Turner@Sun.COM 		free(ablk);
355*12932SRalph.Turner@Sun.COM 		return (error);
356*12932SRalph.Turner@Sun.COM 	}
357*12932SRalph.Turner@Sun.COM 
358*12932SRalph.Turner@Sun.COM 	/* teardown rctls if required */
359*12932SRalph.Turner@Sun.COM 	if (!project_entity) {
360*12932SRalph.Turner@Sun.COM 
361*12932SRalph.Turner@Sun.COM 		if ((rlast = (rctlblk_t *)malloc(rctlblk_size())) == NULL) {
362*12932SRalph.Turner@Sun.COM 			free(ablk);
363*12932SRalph.Turner@Sun.COM 			return (SETFAILED);
364*12932SRalph.Turner@Sun.COM 		}
365*12932SRalph.Turner@Sun.COM 		if ((rnext = (rctlblk_t *)malloc(rctlblk_size())) == NULL) {
366*12932SRalph.Turner@Sun.COM 			free(ablk);
367*12932SRalph.Turner@Sun.COM 			free(rlast);
368*12932SRalph.Turner@Sun.COM 			return (SETFAILED);
369*12932SRalph.Turner@Sun.COM 		}
370*12932SRalph.Turner@Sun.COM 
371*12932SRalph.Turner@Sun.COM 		if (pr_getrctl(Pr, ctl_name, NULL, rnext, RCTL_FIRST) == 0) {
372*12932SRalph.Turner@Sun.COM 
373*12932SRalph.Turner@Sun.COM 			while (1) {
374*12932SRalph.Turner@Sun.COM 				if ((rctlblk_get_privilege(rnext) ==
375*12932SRalph.Turner@Sun.COM 				    RCPRIV_PRIVILEGED) &&
376*12932SRalph.Turner@Sun.COM 				    (teardown_priv == 1)) {
377*12932SRalph.Turner@Sun.COM 					(void) pr_setrctl(Pr, ctl_name, NULL,
378*12932SRalph.Turner@Sun.COM 					    rnext, RCTL_DELETE);
379*12932SRalph.Turner@Sun.COM 				}
380*12932SRalph.Turner@Sun.COM 				if ((rctlblk_get_privilege(rnext) ==
381*12932SRalph.Turner@Sun.COM 				    RCPRIV_BASIC) && (teardown_basic == 1)) {
382*12932SRalph.Turner@Sun.COM 					(void) pr_setrctl(Pr, ctl_name, NULL,
383*12932SRalph.Turner@Sun.COM 					    rnext, RCTL_DELETE);
384*12932SRalph.Turner@Sun.COM 				}
385*12932SRalph.Turner@Sun.COM 
386*12932SRalph.Turner@Sun.COM 				rtmp = rnext;
387*12932SRalph.Turner@Sun.COM 				rnext = rlast;
388*12932SRalph.Turner@Sun.COM 				rlast = rtmp;
389*12932SRalph.Turner@Sun.COM 				if (pr_getrctl(Pr, ctl_name, rlast, rnext,
390*12932SRalph.Turner@Sun.COM 				    RCTL_NEXT) == -1)
391*12932SRalph.Turner@Sun.COM 					break;
392*12932SRalph.Turner@Sun.COM 			}
393*12932SRalph.Turner@Sun.COM 
394*12932SRalph.Turner@Sun.COM 		}
395*12932SRalph.Turner@Sun.COM 
396*12932SRalph.Turner@Sun.COM 		free(rnext);
397*12932SRalph.Turner@Sun.COM 		free(rlast);
398*12932SRalph.Turner@Sun.COM 
399*12932SRalph.Turner@Sun.COM 	}
400*12932SRalph.Turner@Sun.COM 
401*12932SRalph.Turner@Sun.COM 	/* set rctls */
402*12932SRalph.Turner@Sun.COM 
403*12932SRalph.Turner@Sun.COM 	blk = ablk;
404*12932SRalph.Turner@Sun.COM 
405*12932SRalph.Turner@Sun.COM 	if (project_entity) {
406*12932SRalph.Turner@Sun.COM 		if (pr_setprojrctl(Pr, ctl_name, blk, count, flags) == -1)
407*12932SRalph.Turner@Sun.COM 			error = SETFAILED;
408*12932SRalph.Turner@Sun.COM 	} else {
409*12932SRalph.Turner@Sun.COM 		valuecount = 0;
410*12932SRalph.Turner@Sun.COM 		while (valuecount < count) {
411*12932SRalph.Turner@Sun.COM 			if (pr_setrctl(Pr, ctl_name,
412*12932SRalph.Turner@Sun.COM 			    NULL, blk, RCTL_INSERT) == -1) {
413*12932SRalph.Turner@Sun.COM 				error = SETFAILED;
414*12932SRalph.Turner@Sun.COM 				break;
415*12932SRalph.Turner@Sun.COM 				}
416*12932SRalph.Turner@Sun.COM 			valuecount++;
417*12932SRalph.Turner@Sun.COM 			blk = RCTLBLK_INC(ablk, valuecount);
418*12932SRalph.Turner@Sun.COM 		}
419*12932SRalph.Turner@Sun.COM 	}
420*12932SRalph.Turner@Sun.COM 
421*12932SRalph.Turner@Sun.COM 
422*12932SRalph.Turner@Sun.COM 
423*12932SRalph.Turner@Sun.COM 	free(ablk);
424*12932SRalph.Turner@Sun.COM 
4250Sstevel@tonic-gate 	if (error != COMPLETE)
4260Sstevel@tonic-gate 		return (error);
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	return (0);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate static int
rctlwalkfunc(const char * name,void * data)4320Sstevel@tonic-gate rctlwalkfunc(const char *name, void *data)
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	if (strcmp(name, (char *)data) == 0)
4360Sstevel@tonic-gate 		return (-1);
4370Sstevel@tonic-gate 	else
4380Sstevel@tonic-gate 		return (0);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate /*
4430Sstevel@tonic-gate  * This routine determines if /dev/pool device is present on the system and
4440Sstevel@tonic-gate  * pools are currently enabled.  We want to do this directly from libproject
4450Sstevel@tonic-gate  * without using libpool's pool_get_status() routine because pools could be
4460Sstevel@tonic-gate  * completely removed from the system.  Return 1 if pools are enabled, or
4470Sstevel@tonic-gate  * 0 otherwise.  When used inside local zones, always pretend that pools
4480Sstevel@tonic-gate  * are disabled because binding is not allowed and we're already in the
4490Sstevel@tonic-gate  * right pool.
4500Sstevel@tonic-gate  */
4510Sstevel@tonic-gate static int
pools_enabled(void)4520Sstevel@tonic-gate pools_enabled(void)
4530Sstevel@tonic-gate {
4540Sstevel@tonic-gate 	pool_status_t status;
4550Sstevel@tonic-gate 	int fd;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID)
4580Sstevel@tonic-gate 		return (0);
4590Sstevel@tonic-gate 	if ((fd = open("/dev/pool", O_RDONLY)) < 0)
4600Sstevel@tonic-gate 		return (0);
4610Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
4620Sstevel@tonic-gate 		(void) close(fd);
4630Sstevel@tonic-gate 		return (0);
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 	(void) close(fd);
4660Sstevel@tonic-gate 	return (status.ps_io_state);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate  * A pool_name of NULL means to attempt to bind to the default pool.
4710Sstevel@tonic-gate  * If the "force" flag is non-zero, the value of "system.bind-default" will be
4720Sstevel@tonic-gate  * ignored, and the process will be bound to the default pool if one exists.
4730Sstevel@tonic-gate  */
4740Sstevel@tonic-gate static int
bind_to_pool(const char * pool_name,pid_t pid,int force)4750Sstevel@tonic-gate bind_to_pool(const char *pool_name, pid_t pid, int force)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
4780Sstevel@tonic-gate 	pool_t **pools;
4790Sstevel@tonic-gate 	uint_t nelem;
4800Sstevel@tonic-gate 	uchar_t bval;
4810Sstevel@tonic-gate 	pool_conf_t *conf;
4820Sstevel@tonic-gate 	const char *nm;
4830Sstevel@tonic-gate 	int retval;
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
4860Sstevel@tonic-gate 		return (-1);
4870Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
4880Sstevel@tonic-gate 		/*
4890Sstevel@tonic-gate 		 * Pools configuration file is corrupted; allow logins.
4900Sstevel@tonic-gate 		 */
4910Sstevel@tonic-gate 		pool_conf_free(conf);
4920Sstevel@tonic-gate 		return (0);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 	if (pool_name != NULL && pool_get_pool(conf, pool_name) != NULL) {
4950Sstevel@tonic-gate 		/*
4960Sstevel@tonic-gate 		 * There was a project.pool entry, and the pool it refers to
4970Sstevel@tonic-gate 		 * is a valid (active) pool.
4980Sstevel@tonic-gate 		 */
4990Sstevel@tonic-gate 		(void) pool_conf_close(conf);
5000Sstevel@tonic-gate 		pool_conf_free(conf);
5010Sstevel@tonic-gate 		if (pool_set_binding(pool_name, P_PID, pid) != PO_SUCCESS) {
5020Sstevel@tonic-gate 			if (pool_error() != POE_SYSTEM)
5030Sstevel@tonic-gate 				errno = EINVAL;
5040Sstevel@tonic-gate 			return (-1);
5050Sstevel@tonic-gate 		}
5060Sstevel@tonic-gate 		return (0);
5070Sstevel@tonic-gate 	}
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	/*
5100Sstevel@tonic-gate 	 * Bind to the pool with 'pool.default' = 'true' if
5110Sstevel@tonic-gate 	 * 'system.bind-default' = 'true'.
5120Sstevel@tonic-gate 	 */
5130Sstevel@tonic-gate 	if ((pvals[0] = pool_value_alloc()) == NULL) {
5140Sstevel@tonic-gate 		pool_conf_close(conf);
5150Sstevel@tonic-gate 		pool_conf_free(conf);
5160Sstevel@tonic-gate 		return (-1);
5170Sstevel@tonic-gate 	}
5180Sstevel@tonic-gate 	if (!force && pool_get_property(conf, pool_conf_to_elem(conf),
5190Sstevel@tonic-gate 	    "system.bind-default", pvals[0]) != POC_BOOL ||
5200Sstevel@tonic-gate 	    pool_value_get_bool(pvals[0], &bval) != PO_SUCCESS ||
5210Sstevel@tonic-gate 	    bval == PO_FALSE) {
5220Sstevel@tonic-gate 		pool_value_free(pvals[0]);
5230Sstevel@tonic-gate 		pool_conf_close(conf);
5240Sstevel@tonic-gate 		pool_conf_free(conf);
5250Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
5260Sstevel@tonic-gate 		return (-1);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 	(void) pool_value_set_name(pvals[0], "pool.default");
5290Sstevel@tonic-gate 	pool_value_set_bool(pvals[0], PO_TRUE);
5300Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, pvals)) == NULL) {
5310Sstevel@tonic-gate 		/*
5320Sstevel@tonic-gate 		 * No default pools exist.
5330Sstevel@tonic-gate 		 */
5340Sstevel@tonic-gate 		pool_value_free(pvals[0]);
5350Sstevel@tonic-gate 		pool_conf_close(conf);
5360Sstevel@tonic-gate 		pool_conf_free(conf);
5370Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
5380Sstevel@tonic-gate 		return (-1);
5390Sstevel@tonic-gate 	}
5400Sstevel@tonic-gate 	if (nelem != 1 ||
5410Sstevel@tonic-gate 	    pool_get_property(conf, pool_to_elem(conf, pools[0]), "pool.name",
5420Sstevel@tonic-gate 	    pvals[0]) != POC_STRING) {
5430Sstevel@tonic-gate 		/*
5440Sstevel@tonic-gate 		 * Configuration is invalid.
5450Sstevel@tonic-gate 		 */
5460Sstevel@tonic-gate 		free(pools);
5470Sstevel@tonic-gate 		pool_value_free(pvals[0]);
5480Sstevel@tonic-gate 		(void) pool_conf_close(conf);
5490Sstevel@tonic-gate 		pool_conf_free(conf);
5500Sstevel@tonic-gate 		return (0);
5510Sstevel@tonic-gate 	}
5520Sstevel@tonic-gate 	free(pools);
5530Sstevel@tonic-gate 	(void) pool_conf_close(conf);
5540Sstevel@tonic-gate 	pool_conf_free(conf);
5550Sstevel@tonic-gate 	(void) pool_value_get_string(pvals[0], &nm);
5560Sstevel@tonic-gate 	if (pool_set_binding(nm, P_PID, pid) != PO_SUCCESS) {
5570Sstevel@tonic-gate 		if (pool_error() != POE_SYSTEM)
5580Sstevel@tonic-gate 			errno = EINVAL;
5590Sstevel@tonic-gate 		retval = -1;
5600Sstevel@tonic-gate 	} else {
5610Sstevel@tonic-gate 		retval = 0;
5620Sstevel@tonic-gate 	}
5630Sstevel@tonic-gate 	pool_value_free(pvals[0]);
5640Sstevel@tonic-gate 	return (retval);
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate /*
5680Sstevel@tonic-gate  * Changes the assigned project, task and resource pool of a stopped target
5690Sstevel@tonic-gate  * process.
5700Sstevel@tonic-gate  *
5710Sstevel@tonic-gate  * We may not have access to the project table if our target process is in
5720Sstevel@tonic-gate  * getprojbyname()'s execution path. Similarly, we may not be able to get user
5730Sstevel@tonic-gate  * information if the target process is in getpwnam()'s execution path. Thus we
5740Sstevel@tonic-gate  * give the caller the option of skipping these checks by providing a pointer to
5750Sstevel@tonic-gate  * a pre-validated project structure in proj (whose name matches project_name)
5760Sstevel@tonic-gate  * and taking responsibility for ensuring that the target process' owner is a
5770Sstevel@tonic-gate  * member of the target project.
5780Sstevel@tonic-gate  *
5790Sstevel@tonic-gate  * Callers of this function should always provide a pre-validated project
5800Sstevel@tonic-gate  * structure in proj unless they can be sure that the target process will never
5810Sstevel@tonic-gate  * be in setproject_proc()'s execution path.
5820Sstevel@tonic-gate  */
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate projid_t
setproject_proc(const char * project_name,const char * user_name,int flags,pid_t pid,struct ps_prochandle * Pr,struct project * proj)5850Sstevel@tonic-gate setproject_proc(const char *project_name, const char *user_name, int flags,
5860Sstevel@tonic-gate     pid_t pid, struct ps_prochandle *Pr, struct project *proj)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate 	char pwdbuf[NSS_BUFLEN_PASSWD];
5890Sstevel@tonic-gate 	char prbuf[PROJECT_BUFSZ];
5900Sstevel@tonic-gate 	projid_t projid;
5910Sstevel@tonic-gate 	struct passwd pwd;
5920Sstevel@tonic-gate 	int i;
5930Sstevel@tonic-gate 	int unknown = 0;
5940Sstevel@tonic-gate 	int ret = 0;
5950Sstevel@tonic-gate 	kva_t *kv_array;
5960Sstevel@tonic-gate 	struct project local_proj; /* space to store proj if not provided */
5973684Srd117015 	const char *pool_name = NULL;
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if (project_name != NULL) {
6000Sstevel@tonic-gate 		/*
6010Sstevel@tonic-gate 		 * Sanity checks.
6020Sstevel@tonic-gate 		 */
6030Sstevel@tonic-gate 		if (strcmp(project_name, "") == 0 ||
6040Sstevel@tonic-gate 		    user_name == NULL) {
6050Sstevel@tonic-gate 			errno = EINVAL;
6060Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6070Sstevel@tonic-gate 		}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		/*
6100Sstevel@tonic-gate 		 * If proj is NULL, acquire project information to ensure that
6110Sstevel@tonic-gate 		 * project_name is a valid project, and confirm that user_name
6120Sstevel@tonic-gate 		 * exists and is a member of the specified project.
6130Sstevel@tonic-gate 		 */
6140Sstevel@tonic-gate 		if (proj == NULL) {
6150Sstevel@tonic-gate 			if ((proj = getprojbyname(project_name, &local_proj,
6160Sstevel@tonic-gate 			    prbuf, PROJECT_BUFSZ)) == NULL) {
6170Sstevel@tonic-gate 				errno = ESRCH;
6180Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
6190Sstevel@tonic-gate 			}
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 			if (getpwnam_r(user_name, &pwd,
6220Sstevel@tonic-gate 			    pwdbuf, NSS_BUFLEN_PASSWD) == NULL) {
6230Sstevel@tonic-gate 				errno = ESRCH;
6240Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
6250Sstevel@tonic-gate 			}
6260Sstevel@tonic-gate 			/*
6270Sstevel@tonic-gate 			 * Root can join any project.
6280Sstevel@tonic-gate 			 */
6290Sstevel@tonic-gate 			if (pwd.pw_uid != (uid_t)0 &&
6300Sstevel@tonic-gate 			    !inproj(user_name, project_name, prbuf,
6310Sstevel@tonic-gate 			    PROJECT_BUFSZ)) {
6320Sstevel@tonic-gate 				errno = ESRCH;
6330Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
6340Sstevel@tonic-gate 			}
6350Sstevel@tonic-gate 		}
6360Sstevel@tonic-gate 		projid = proj->pj_projid;
6370Sstevel@tonic-gate 	} else {
6380Sstevel@tonic-gate 		projid = getprojid();
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 
6413684Srd117015 
6423684Srd117015 	if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
6433684Srd117015 	    KV_DELIMITER)) != NULL) {
6443684Srd117015 		for (i = 0; i < kv_array->length; i++) {
6453684Srd117015 			if (strcmp(kv_array->data[i].key,
6463684Srd117015 			    "project.pool") == 0) {
6473684Srd117015 				pool_name = kv_array->data[i].value;
6483684Srd117015 			}
6493684Srd117015 			if (strcmp(kv_array->data[i].key, "task.final") == 0) {
6503684Srd117015 				flags |= TASK_FINAL;
6513684Srd117015 			}
6523684Srd117015 		}
6533684Srd117015 	}
6543684Srd117015 
6550Sstevel@tonic-gate 	/*
6563684Srd117015 	 * Bind process to a pool only if pools are configured
6570Sstevel@tonic-gate 	 */
6580Sstevel@tonic-gate 	if (pools_enabled() == 1) {
6590Sstevel@tonic-gate 		char *old_pool_name;
6600Sstevel@tonic-gate 		/*
6610Sstevel@tonic-gate 		 * Attempt to bind to pool before calling
6620Sstevel@tonic-gate 		 * settaskid().
6630Sstevel@tonic-gate 		 */
6640Sstevel@tonic-gate 		old_pool_name = pool_get_binding(pid);
6653684Srd117015 		if (bind_to_pool(pool_name, pid, 0) != 0) {
6660Sstevel@tonic-gate 			if (old_pool_name)
6670Sstevel@tonic-gate 				free(old_pool_name);
6680Sstevel@tonic-gate 			_kva_free(kv_array);
6690Sstevel@tonic-gate 			return (SETPROJ_ERR_POOL);
6700Sstevel@tonic-gate 		}
6713684Srd117015 		if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
6720Sstevel@tonic-gate 			int saved_errno = errno;
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 			/*
6750Sstevel@tonic-gate 			 * Undo pool binding.
6760Sstevel@tonic-gate 			 */
6770Sstevel@tonic-gate 			(void) bind_to_pool(old_pool_name, pid, 1);
6780Sstevel@tonic-gate 			if (old_pool_name)
6790Sstevel@tonic-gate 				free(old_pool_name);
6800Sstevel@tonic-gate 			_kva_free(kv_array);
6810Sstevel@tonic-gate 			/*
6820Sstevel@tonic-gate 			 * Restore errno
6830Sstevel@tonic-gate 			 */
6840Sstevel@tonic-gate 			errno = saved_errno;
6850Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6860Sstevel@tonic-gate 		}
6870Sstevel@tonic-gate 		if (old_pool_name)
6880Sstevel@tonic-gate 			free(old_pool_name);
6890Sstevel@tonic-gate 	} else {
6900Sstevel@tonic-gate 		/*
6910Sstevel@tonic-gate 		 * Pools are not configured, so simply create new task.
6920Sstevel@tonic-gate 		 */
6933684Srd117015 		if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
6943684Srd117015 			_kva_free(kv_array);
6950Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6963684Srd117015 		}
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	if (project_name == NULL) {
7000Sstevel@tonic-gate 		/*
7010Sstevel@tonic-gate 		 * In the case that we are starting a new task in the
7020Sstevel@tonic-gate 		 * current project, we are finished, since the current
7030Sstevel@tonic-gate 		 * resource controls will still apply. (Implicit behaviour:
7040Sstevel@tonic-gate 		 * a project must be entirely logged out before name
7050Sstevel@tonic-gate 		 * service changes will take effect.)
7060Sstevel@tonic-gate 		 */
7070Sstevel@tonic-gate 		_kva_free(kv_array);
7080Sstevel@tonic-gate 		return (projid);
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 	if (kv_array == NULL)
7120Sstevel@tonic-gate 		return (0);
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 	for (i = 0; i < kv_array->length; i++) {
7150Sstevel@tonic-gate 		/*
7160Sstevel@tonic-gate 		 * Providing a special, i.e. a non-resource control, key?  Then
7170Sstevel@tonic-gate 		 * parse that key here and end with "continue;".
7180Sstevel@tonic-gate 		 */
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 		/*
7210Sstevel@tonic-gate 		 * For generic bindings, the kernel performs the binding, as
7220Sstevel@tonic-gate 		 * these are resource controls advertised by kernel subsystems.
7230Sstevel@tonic-gate 		 */
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 		/*
7260Sstevel@tonic-gate 		 * Check for known attribute name.
7270Sstevel@tonic-gate 		 */
7280Sstevel@tonic-gate 		errno = 0;
7290Sstevel@tonic-gate 		if (rctl_walk(rctlwalkfunc, (void *)kv_array->data[i].key)
7300Sstevel@tonic-gate 		    == 0)
7310Sstevel@tonic-gate 			continue;
7320Sstevel@tonic-gate 		if (errno) {
7330Sstevel@tonic-gate 			_kva_free(kv_array);
7340Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
7350Sstevel@tonic-gate 		}
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 		ret = rctl_set(kv_array->data[i].key,
7383684Srd117015 		    kv_array->data[i].value, Pr, flags & TASK_PROJ_MASK);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 		if (ret && unknown == 0) {
7410Sstevel@tonic-gate 			/*
7420Sstevel@tonic-gate 			 * We only report the first failure.
7430Sstevel@tonic-gate 			 */
7440Sstevel@tonic-gate 			unknown = i + 1;
7450Sstevel@tonic-gate 		}
7460Sstevel@tonic-gate 
7470Sstevel@tonic-gate 		if (ret && ret != SETFAILED) {
7480Sstevel@tonic-gate 			/*
7490Sstevel@tonic-gate 			 * We abort if we couldn't set a component, but if
7500Sstevel@tonic-gate 			 * it's merely that the system didn't recognize it, we
7510Sstevel@tonic-gate 			 * continue, as this could be a third party attribute.
7520Sstevel@tonic-gate 			 */
7530Sstevel@tonic-gate 			break;
7540Sstevel@tonic-gate 		}
7550Sstevel@tonic-gate 	}
7560Sstevel@tonic-gate 	_kva_free(kv_array);
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	return (unknown);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate projid_t
setproject(const char * project_name,const char * user_name,int flags)7620Sstevel@tonic-gate setproject(const char *project_name, const char *user_name, int flags)
7630Sstevel@tonic-gate {
7640Sstevel@tonic-gate 	return (setproject_proc(project_name, user_name, flags, P_MYID, NULL,
7650Sstevel@tonic-gate 	    NULL));
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate priv_set_t *
setproject_initpriv(void)7700Sstevel@tonic-gate setproject_initpriv(void)
7710Sstevel@tonic-gate {
7720Sstevel@tonic-gate 	static priv_t taskpriv = PRIV_PROC_TASKID;
7730Sstevel@tonic-gate 	static priv_t rctlpriv = PRIV_SYS_RESOURCE;
7740Sstevel@tonic-gate 	static priv_t poolpriv = PRIV_SYS_RES_CONFIG;
7750Sstevel@tonic-gate 	static priv_t schedpriv = PRIV_PROC_PRIOCNTL;
7760Sstevel@tonic-gate 	int res;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	priv_set_t *nset;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
7810Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, poolpriv,
7820Sstevel@tonic-gate 		    schedpriv, (char *)NULL);
7830Sstevel@tonic-gate 	} else {
7840Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, (char *)NULL);
7850Sstevel@tonic-gate 	}
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 	if (res != 0)
7880Sstevel@tonic-gate 		return (NULL);
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	nset = priv_allocset();
7910Sstevel@tonic-gate 	if (nset != NULL) {
7920Sstevel@tonic-gate 		priv_emptyset(nset);
7930Sstevel@tonic-gate 		(void) priv_addset(nset, taskpriv);
7940Sstevel@tonic-gate 		(void) priv_addset(nset, rctlpriv);
7950Sstevel@tonic-gate 		/*
7960Sstevel@tonic-gate 		 * Only need these if we need to change pools, which can
7970Sstevel@tonic-gate 		 * only happen if the target is in the global zone.  Rather
7980Sstevel@tonic-gate 		 * than checking the target's zone just check our own
7990Sstevel@tonic-gate 		 * (since if we're in a non-global zone we won't be able
8000Sstevel@tonic-gate 		 * to control processes in other zones).
8010Sstevel@tonic-gate 		 */
8020Sstevel@tonic-gate 		if (getzoneid() == GLOBAL_ZONEID) {
8030Sstevel@tonic-gate 			(void) priv_addset(nset, poolpriv);
8040Sstevel@tonic-gate 			(void) priv_addset(nset, schedpriv);
8050Sstevel@tonic-gate 		}
8060Sstevel@tonic-gate 	}
8070Sstevel@tonic-gate 	return (nset);
8080Sstevel@tonic-gate }
809