xref: /titanic_44/usr/src/lib/libproject/common/setproject.c (revision 0209230bf1261579beab4f55226bb509e6b850cb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0209230bSgjelinek  * Common Development and Distribution License (the "License").
6*0209230bSgjelinek  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*0209230bSgjelinek  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/task.h>
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <ctype.h>
337c478bd9Sstevel@tonic-gate #include <project.h>
347c478bd9Sstevel@tonic-gate #include <rctl.h>
357c478bd9Sstevel@tonic-gate #include <secdb.h>
367c478bd9Sstevel@tonic-gate #include <signal.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <string.h>
397c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
407c478bd9Sstevel@tonic-gate #include <pwd.h>
417c478bd9Sstevel@tonic-gate #include <pool.h>
427c478bd9Sstevel@tonic-gate #include <libproc.h>
437c478bd9Sstevel@tonic-gate #include <priv.h>
447c478bd9Sstevel@tonic-gate #include <priv_utils.h>
457c478bd9Sstevel@tonic-gate #include <zone.h>
467c478bd9Sstevel@tonic-gate #include <sys/pool.h>
477c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate static void
507c478bd9Sstevel@tonic-gate xstrtolower(char *s)
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++)
537c478bd9Sstevel@tonic-gate 		*s = tolower(*s);
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static void
577c478bd9Sstevel@tonic-gate remove_spaces(char *s)
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	char *current;
607c478bd9Sstevel@tonic-gate 	char *next;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	current = next = s;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	while (*next != '\0') {
657c478bd9Sstevel@tonic-gate 		while (isspace(*next))
667c478bd9Sstevel@tonic-gate 		    next++;
677c478bd9Sstevel@tonic-gate 		*current++ = *next++;
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 	*current = '\0';
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate int
737c478bd9Sstevel@tonic-gate build_rctlblk(rctlblk_t *blk, int comp_num, char *component)
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	char *signam;
767c478bd9Sstevel@tonic-gate 	int sig = 0;
777c478bd9Sstevel@tonic-gate 	uint_t act = rctlblk_get_local_action(blk, &sig);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	if (comp_num == 0) {
807c478bd9Sstevel@tonic-gate 		/*
817c478bd9Sstevel@tonic-gate 		 * Setting privilege level for resource control block.
827c478bd9Sstevel@tonic-gate 		 */
837c478bd9Sstevel@tonic-gate 		xstrtolower(component);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 		if (strcmp("basic", component) == 0) {
867c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_BASIC);
877c478bd9Sstevel@tonic-gate 			return (0);
887c478bd9Sstevel@tonic-gate 		}
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 		if (strcmp("priv", component) == 0 ||
917c478bd9Sstevel@tonic-gate 		    strcmp("privileged", component) == 0) {
927c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
937c478bd9Sstevel@tonic-gate 			return (0);
947c478bd9Sstevel@tonic-gate 		}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 		return (-1);
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	if (comp_num == 1) {
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 		/*
1027c478bd9Sstevel@tonic-gate 		 * Setting value for resource control block.
1037c478bd9Sstevel@tonic-gate 		 */
1047c478bd9Sstevel@tonic-gate 		unsigned long long val;
1057c478bd9Sstevel@tonic-gate 		char *t;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 		/* Negative numbers are not allowed */
1087c478bd9Sstevel@tonic-gate 		if (strchr(component, '-') != NULL)
1097c478bd9Sstevel@tonic-gate 			return (-1);
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 		errno = 0;
1127c478bd9Sstevel@tonic-gate 		val = strtoull(component, &t, 10);
1137c478bd9Sstevel@tonic-gate 		if (errno != 0 || t == component || *t != '\0')
1147c478bd9Sstevel@tonic-gate 			return (-1);
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 		rctlblk_set_value(blk, (rctl_qty_t)val);
1177c478bd9Sstevel@tonic-gate 		return (0);
1187c478bd9Sstevel@tonic-gate 	}
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	/*
1217c478bd9Sstevel@tonic-gate 	 * Setting one or more actions on this resource control block.
1227c478bd9Sstevel@tonic-gate 	 */
1237c478bd9Sstevel@tonic-gate 	if (comp_num >= 2) {
1247c478bd9Sstevel@tonic-gate 		if (strcmp("none", component) == 0) {
1257c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, 0, 0);
1267c478bd9Sstevel@tonic-gate 			return (0);
1277c478bd9Sstevel@tonic-gate 		}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 		if (strcmp("deny", component) == 0) {
1307c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_DENY;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 			return (0);
1357c478bd9Sstevel@tonic-gate 		}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 		/*
1387c478bd9Sstevel@tonic-gate 		 * The last, and trickiest, form of action is the signal
1397c478bd9Sstevel@tonic-gate 		 * specification.
1407c478bd9Sstevel@tonic-gate 		 */
1417c478bd9Sstevel@tonic-gate 		if ((signam = strchr(component, '=')) == NULL)
1427c478bd9Sstevel@tonic-gate 			return (-1);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 		*signam++ = '\0';
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		if (strcmp("sig", component) == 0 ||
1477c478bd9Sstevel@tonic-gate 		    strcmp("signal", component) == 0) {
1487c478bd9Sstevel@tonic-gate 			if (strncmp("SIG", signam, 3) == 0)
1497c478bd9Sstevel@tonic-gate 				signam += 3;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 			if (str2sig(signam, &sig) == -1)
1527c478bd9Sstevel@tonic-gate 				return (-1);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_SIGNAL;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 			return (0);
1597c478bd9Sstevel@tonic-gate 		}
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 	return (-1);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  * States:
1667c478bd9Sstevel@tonic-gate  */
1677c478bd9Sstevel@tonic-gate #define	INPAREN		0x1
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate  * Errors:
1717c478bd9Sstevel@tonic-gate  */
1727c478bd9Sstevel@tonic-gate #define	SETFAILED	(-1)
1737c478bd9Sstevel@tonic-gate #define	COMPLETE	1
1747c478bd9Sstevel@tonic-gate #define	NESTING		2
1757c478bd9Sstevel@tonic-gate #define	UNCLOSED	3
1767c478bd9Sstevel@tonic-gate #define	CLOSEBEFOREOPEN	4
1777c478bd9Sstevel@tonic-gate #define	BADSPEC		5
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate static int
1807c478bd9Sstevel@tonic-gate rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr)
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate 	int error = 0;
1837c478bd9Sstevel@tonic-gate 	uint_t component = 0;
1847c478bd9Sstevel@tonic-gate 	int valuecount = 0;
1857c478bd9Sstevel@tonic-gate 	uint_t state = 0;
1867c478bd9Sstevel@tonic-gate 	char *component_head;
1877c478bd9Sstevel@tonic-gate 	rctlblk_t *blk;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	remove_spaces(val);
1907c478bd9Sstevel@tonic-gate 	if ((blk = malloc(rctlblk_size())) == NULL) {
1917c478bd9Sstevel@tonic-gate 		return (SETFAILED);
1927c478bd9Sstevel@tonic-gate 	}
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	/*
1957c478bd9Sstevel@tonic-gate 	 * Tear down everything with this ctl name.
1967c478bd9Sstevel@tonic-gate 	 */
1977c478bd9Sstevel@tonic-gate 	while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 &&
1987c478bd9Sstevel@tonic-gate 	    rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) {
1997c478bd9Sstevel@tonic-gate 		(void) pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE);
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	/*
2037c478bd9Sstevel@tonic-gate 	 * Set initial local action based on global deny properties.
2047c478bd9Sstevel@tonic-gate 	 */
2057c478bd9Sstevel@tonic-gate 	rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
2067c478bd9Sstevel@tonic-gate 	rctlblk_set_value(blk, 0);
2077c478bd9Sstevel@tonic-gate 	rctlblk_set_local_flags(blk, 0);
2087c478bd9Sstevel@tonic-gate 	if (rctlblk_get_global_flags(blk) & RCTL_GLOBAL_DENY_ALWAYS)
2097c478bd9Sstevel@tonic-gate 		rctlblk_set_local_action(blk, RCTL_LOCAL_DENY, 0);
2107c478bd9Sstevel@tonic-gate 	else
2117c478bd9Sstevel@tonic-gate 		rctlblk_set_local_action(blk, RCTL_LOCAL_NOACTION, 0);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	for (; ; val++) {
2157c478bd9Sstevel@tonic-gate 		switch (*val) {
2167c478bd9Sstevel@tonic-gate 			case '(':
2177c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
2187c478bd9Sstevel@tonic-gate 					error = NESTING;
2197c478bd9Sstevel@tonic-gate 					break;
2207c478bd9Sstevel@tonic-gate 				}
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 				state |= INPAREN;
2237c478bd9Sstevel@tonic-gate 				component_head = (char *)val + 1;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 				break;
2267c478bd9Sstevel@tonic-gate 			case ')':
2277c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
2287c478bd9Sstevel@tonic-gate 					*val = '\0';
2297c478bd9Sstevel@tonic-gate 					if (component < 2) {
2307c478bd9Sstevel@tonic-gate 						error = BADSPEC;
2317c478bd9Sstevel@tonic-gate 						break;
2327c478bd9Sstevel@tonic-gate 					}
2337c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
2347c478bd9Sstevel@tonic-gate 					    component_head) == -1) {
2357c478bd9Sstevel@tonic-gate 						error = BADSPEC;
2367c478bd9Sstevel@tonic-gate 						break;
2377c478bd9Sstevel@tonic-gate 					}
2387c478bd9Sstevel@tonic-gate 					state &= ~INPAREN;
2397c478bd9Sstevel@tonic-gate 					component = 0;
2407c478bd9Sstevel@tonic-gate 					valuecount++;
2417c478bd9Sstevel@tonic-gate 					if (pr_setrctl(Pr, ctl_name, NULL, blk,
2427c478bd9Sstevel@tonic-gate 					    RCTL_INSERT) == -1)
2437c478bd9Sstevel@tonic-gate 						error = SETFAILED;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 					/* re-initialize block */
2467c478bd9Sstevel@tonic-gate 					rctlblk_set_privilege(blk,
2477c478bd9Sstevel@tonic-gate 					    RCPRIV_PRIVILEGED);
2487c478bd9Sstevel@tonic-gate 					rctlblk_set_value(blk, 0);
2497c478bd9Sstevel@tonic-gate 					rctlblk_set_local_flags(blk, 0);
2507c478bd9Sstevel@tonic-gate 					if (rctlblk_get_global_flags(blk) &
2517c478bd9Sstevel@tonic-gate 					    RCTL_GLOBAL_DENY_ALWAYS)
2527c478bd9Sstevel@tonic-gate 						rctlblk_set_local_action(blk,
2537c478bd9Sstevel@tonic-gate 						    RCTL_LOCAL_DENY, 0);
2547c478bd9Sstevel@tonic-gate 					else
2557c478bd9Sstevel@tonic-gate 						rctlblk_set_local_action(blk,
2567c478bd9Sstevel@tonic-gate 						    RCTL_LOCAL_NOACTION, 0);
2577c478bd9Sstevel@tonic-gate 				} else {
2587c478bd9Sstevel@tonic-gate 					error = CLOSEBEFOREOPEN;
2597c478bd9Sstevel@tonic-gate 				}
2607c478bd9Sstevel@tonic-gate 				break;
2617c478bd9Sstevel@tonic-gate 			case ',':
2627c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
2637c478bd9Sstevel@tonic-gate 					*val = '\0';
2647c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
2657c478bd9Sstevel@tonic-gate 					    component_head) == -1)
2667c478bd9Sstevel@tonic-gate 						error = BADSPEC;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 					component++;
2697c478bd9Sstevel@tonic-gate 					component_head = (char *)val + 1;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 				}
2727c478bd9Sstevel@tonic-gate 				break;
2737c478bd9Sstevel@tonic-gate 			case '\0':
2747c478bd9Sstevel@tonic-gate 				if (valuecount == 0)
2757c478bd9Sstevel@tonic-gate 					error = BADSPEC;
2767c478bd9Sstevel@tonic-gate 				else if (state & INPAREN)
2777c478bd9Sstevel@tonic-gate 					error = UNCLOSED;
2787c478bd9Sstevel@tonic-gate 				else
2797c478bd9Sstevel@tonic-gate 					error = COMPLETE;
2807c478bd9Sstevel@tonic-gate 				break;
2817c478bd9Sstevel@tonic-gate 			default:
2827c478bd9Sstevel@tonic-gate 				if (!(state & INPAREN))
2837c478bd9Sstevel@tonic-gate 					error = BADSPEC;
2847c478bd9Sstevel@tonic-gate 				break;
2857c478bd9Sstevel@tonic-gate 		}
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		if (error)
2887c478bd9Sstevel@tonic-gate 			break;
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	free(blk);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	if (valuecount == 0)
2947c478bd9Sstevel@tonic-gate 		error = BADSPEC;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	if (error != COMPLETE)
2977c478bd9Sstevel@tonic-gate 		return (error);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	return (0);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate static int
3037c478bd9Sstevel@tonic-gate rctlwalkfunc(const char *name, void *data)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	if (strcmp(name, (char *)data) == 0)
3077c478bd9Sstevel@tonic-gate 		return (-1);
3087c478bd9Sstevel@tonic-gate 	else
3097c478bd9Sstevel@tonic-gate 		return (0);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate  * This routine determines if /dev/pool device is present on the system and
3157c478bd9Sstevel@tonic-gate  * pools are currently enabled.  We want to do this directly from libproject
3167c478bd9Sstevel@tonic-gate  * without using libpool's pool_get_status() routine because pools could be
3177c478bd9Sstevel@tonic-gate  * completely removed from the system.  Return 1 if pools are enabled, or
3187c478bd9Sstevel@tonic-gate  * 0 otherwise.  When used inside local zones, always pretend that pools
3197c478bd9Sstevel@tonic-gate  * are disabled because binding is not allowed and we're already in the
3207c478bd9Sstevel@tonic-gate  * right pool.
3217c478bd9Sstevel@tonic-gate  */
3227c478bd9Sstevel@tonic-gate static int
3237c478bd9Sstevel@tonic-gate pools_enabled(void)
3247c478bd9Sstevel@tonic-gate {
3257c478bd9Sstevel@tonic-gate 	pool_status_t status;
3267c478bd9Sstevel@tonic-gate 	int fd;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID)
3297c478bd9Sstevel@tonic-gate 		return (0);
3307c478bd9Sstevel@tonic-gate 	if ((fd = open("/dev/pool", O_RDONLY)) < 0)
3317c478bd9Sstevel@tonic-gate 		return (0);
3327c478bd9Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
3337c478bd9Sstevel@tonic-gate 		(void) close(fd);
3347c478bd9Sstevel@tonic-gate 		return (0);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 	(void) close(fd);
3377c478bd9Sstevel@tonic-gate 	return (status.ps_io_state);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate  * A pool_name of NULL means to attempt to bind to the default pool.
3427c478bd9Sstevel@tonic-gate  * If the "force" flag is non-zero, the value of "system.bind-default" will be
3437c478bd9Sstevel@tonic-gate  * ignored, and the process will be bound to the default pool if one exists.
3447c478bd9Sstevel@tonic-gate  */
3457c478bd9Sstevel@tonic-gate static int
3467c478bd9Sstevel@tonic-gate bind_to_pool(const char *pool_name, pid_t pid, int force)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
3497c478bd9Sstevel@tonic-gate 	pool_t **pools;
3507c478bd9Sstevel@tonic-gate 	uint_t nelem;
3517c478bd9Sstevel@tonic-gate 	uchar_t bval;
3527c478bd9Sstevel@tonic-gate 	pool_conf_t *conf;
3537c478bd9Sstevel@tonic-gate 	const char *nm;
3547c478bd9Sstevel@tonic-gate 	int retval;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
3577c478bd9Sstevel@tonic-gate 		return (-1);
3587c478bd9Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
3597c478bd9Sstevel@tonic-gate 		/*
3607c478bd9Sstevel@tonic-gate 		 * Pools configuration file is corrupted; allow logins.
3617c478bd9Sstevel@tonic-gate 		 */
3627c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
3637c478bd9Sstevel@tonic-gate 		return (0);
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 	if (pool_name != NULL && pool_get_pool(conf, pool_name) != NULL) {
3667c478bd9Sstevel@tonic-gate 		/*
3677c478bd9Sstevel@tonic-gate 		 * There was a project.pool entry, and the pool it refers to
3687c478bd9Sstevel@tonic-gate 		 * is a valid (active) pool.
3697c478bd9Sstevel@tonic-gate 		 */
3707c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
3717c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
3727c478bd9Sstevel@tonic-gate 		if (pool_set_binding(pool_name, P_PID, pid) != PO_SUCCESS) {
3737c478bd9Sstevel@tonic-gate 			if (pool_error() != POE_SYSTEM)
3747c478bd9Sstevel@tonic-gate 				errno = EINVAL;
3757c478bd9Sstevel@tonic-gate 			return (-1);
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 		return (0);
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	/*
3817c478bd9Sstevel@tonic-gate 	 * Bind to the pool with 'pool.default' = 'true' if
3827c478bd9Sstevel@tonic-gate 	 * 'system.bind-default' = 'true'.
3837c478bd9Sstevel@tonic-gate 	 */
3847c478bd9Sstevel@tonic-gate 	if ((pvals[0] = pool_value_alloc()) == NULL) {
3857c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
3867c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
3877c478bd9Sstevel@tonic-gate 		return (-1);
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 	if (!force && pool_get_property(conf, pool_conf_to_elem(conf),
3907c478bd9Sstevel@tonic-gate 	    "system.bind-default", pvals[0]) != POC_BOOL ||
3917c478bd9Sstevel@tonic-gate 	    pool_value_get_bool(pvals[0], &bval) != PO_SUCCESS ||
3927c478bd9Sstevel@tonic-gate 	    bval == PO_FALSE) {
3937c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
3947c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
3957c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
3967c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
3977c478bd9Sstevel@tonic-gate 		return (-1);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 	(void) pool_value_set_name(pvals[0], "pool.default");
4007c478bd9Sstevel@tonic-gate 	pool_value_set_bool(pvals[0], PO_TRUE);
4017c478bd9Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, pvals)) == NULL) {
4027c478bd9Sstevel@tonic-gate 		/*
4037c478bd9Sstevel@tonic-gate 		 * No default pools exist.
4047c478bd9Sstevel@tonic-gate 		 */
4057c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
4067c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
4077c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4087c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
4097c478bd9Sstevel@tonic-gate 		return (-1);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	if (nelem != 1 ||
4127c478bd9Sstevel@tonic-gate 	    pool_get_property(conf, pool_to_elem(conf, pools[0]), "pool.name",
4137c478bd9Sstevel@tonic-gate 	    pvals[0]) != POC_STRING) {
4147c478bd9Sstevel@tonic-gate 		/*
4157c478bd9Sstevel@tonic-gate 		 * Configuration is invalid.
4167c478bd9Sstevel@tonic-gate 		 */
4177c478bd9Sstevel@tonic-gate 		free(pools);
4187c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
4197c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
4207c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4217c478bd9Sstevel@tonic-gate 		return (0);
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 	free(pools);
4247c478bd9Sstevel@tonic-gate 	(void) pool_conf_close(conf);
4257c478bd9Sstevel@tonic-gate 	pool_conf_free(conf);
4267c478bd9Sstevel@tonic-gate 	(void) pool_value_get_string(pvals[0], &nm);
4277c478bd9Sstevel@tonic-gate 	if (pool_set_binding(nm, P_PID, pid) != PO_SUCCESS) {
4287c478bd9Sstevel@tonic-gate 		if (pool_error() != POE_SYSTEM)
4297c478bd9Sstevel@tonic-gate 			errno = EINVAL;
4307c478bd9Sstevel@tonic-gate 		retval = -1;
4317c478bd9Sstevel@tonic-gate 	} else {
4327c478bd9Sstevel@tonic-gate 		retval = 0;
4337c478bd9Sstevel@tonic-gate 	}
4347c478bd9Sstevel@tonic-gate 	pool_value_free(pvals[0]);
4357c478bd9Sstevel@tonic-gate 	return (retval);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate /*
4397c478bd9Sstevel@tonic-gate  * Changes the assigned project, task and resource pool of a stopped target
4407c478bd9Sstevel@tonic-gate  * process.
4417c478bd9Sstevel@tonic-gate  *
4427c478bd9Sstevel@tonic-gate  * We may not have access to the project table if our target process is in
4437c478bd9Sstevel@tonic-gate  * getprojbyname()'s execution path. Similarly, we may not be able to get user
4447c478bd9Sstevel@tonic-gate  * information if the target process is in getpwnam()'s execution path. Thus we
4457c478bd9Sstevel@tonic-gate  * give the caller the option of skipping these checks by providing a pointer to
4467c478bd9Sstevel@tonic-gate  * a pre-validated project structure in proj (whose name matches project_name)
4477c478bd9Sstevel@tonic-gate  * and taking responsibility for ensuring that the target process' owner is a
4487c478bd9Sstevel@tonic-gate  * member of the target project.
4497c478bd9Sstevel@tonic-gate  *
4507c478bd9Sstevel@tonic-gate  * Callers of this function should always provide a pre-validated project
4517c478bd9Sstevel@tonic-gate  * structure in proj unless they can be sure that the target process will never
4527c478bd9Sstevel@tonic-gate  * be in setproject_proc()'s execution path.
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate projid_t
4567c478bd9Sstevel@tonic-gate setproject_proc(const char *project_name, const char *user_name, int flags,
4577c478bd9Sstevel@tonic-gate     pid_t pid, struct ps_prochandle *Pr, struct project *proj)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate 	char pwdbuf[NSS_BUFLEN_PASSWD];
4607c478bd9Sstevel@tonic-gate 	char prbuf[PROJECT_BUFSZ];
4617c478bd9Sstevel@tonic-gate 	projid_t projid;
4627c478bd9Sstevel@tonic-gate 	struct passwd pwd;
4637c478bd9Sstevel@tonic-gate 	int i;
4647c478bd9Sstevel@tonic-gate 	int unknown = 0;
4657c478bd9Sstevel@tonic-gate 	int ret = 0;
4667c478bd9Sstevel@tonic-gate 	kva_t *kv_array;
4677c478bd9Sstevel@tonic-gate 	struct project local_proj; /* space to store proj if not provided */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	if (project_name != NULL) {
4707c478bd9Sstevel@tonic-gate 		/*
4717c478bd9Sstevel@tonic-gate 		 * Sanity checks.
4727c478bd9Sstevel@tonic-gate 		 */
4737c478bd9Sstevel@tonic-gate 		if (strcmp(project_name, "") == 0 ||
4747c478bd9Sstevel@tonic-gate 		    user_name == NULL) {
4757c478bd9Sstevel@tonic-gate 			errno = EINVAL;
4767c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
4777c478bd9Sstevel@tonic-gate 		}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 		/*
4807c478bd9Sstevel@tonic-gate 		 * If proj is NULL, acquire project information to ensure that
4817c478bd9Sstevel@tonic-gate 		 * project_name is a valid project, and confirm that user_name
4827c478bd9Sstevel@tonic-gate 		 * exists and is a member of the specified project.
4837c478bd9Sstevel@tonic-gate 		 */
4847c478bd9Sstevel@tonic-gate 		if (proj == NULL) {
4857c478bd9Sstevel@tonic-gate 			if ((proj = getprojbyname(project_name, &local_proj,
4867c478bd9Sstevel@tonic-gate 			    prbuf, PROJECT_BUFSZ)) == NULL) {
4877c478bd9Sstevel@tonic-gate 				errno = ESRCH;
4887c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
4897c478bd9Sstevel@tonic-gate 			}
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 			if (getpwnam_r(user_name, &pwd,
4927c478bd9Sstevel@tonic-gate 			    pwdbuf, NSS_BUFLEN_PASSWD) == NULL) {
4937c478bd9Sstevel@tonic-gate 				errno = ESRCH;
4947c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 			/*
4977c478bd9Sstevel@tonic-gate 			 * Root can join any project.
4987c478bd9Sstevel@tonic-gate 			 */
4997c478bd9Sstevel@tonic-gate 			if (pwd.pw_uid != (uid_t)0 &&
5007c478bd9Sstevel@tonic-gate 			    !inproj(user_name, project_name, prbuf,
5017c478bd9Sstevel@tonic-gate 			    PROJECT_BUFSZ)) {
5027c478bd9Sstevel@tonic-gate 				errno = ESRCH;
5037c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
5047c478bd9Sstevel@tonic-gate 			}
5057c478bd9Sstevel@tonic-gate 		}
5067c478bd9Sstevel@tonic-gate 		projid = proj->pj_projid;
5077c478bd9Sstevel@tonic-gate 	} else {
5087c478bd9Sstevel@tonic-gate 		projid = getprojid();
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	/*
5127c478bd9Sstevel@tonic-gate 	 * Only bind to a pool if pools are configured.
5137c478bd9Sstevel@tonic-gate 	 */
5147c478bd9Sstevel@tonic-gate 	if (pools_enabled() == 1) {
5157c478bd9Sstevel@tonic-gate 		const char *pool_name = NULL;
5167c478bd9Sstevel@tonic-gate 		char *old_pool_name;
5177c478bd9Sstevel@tonic-gate 		int taskflags = flags;
5187c478bd9Sstevel@tonic-gate 		/*
5197c478bd9Sstevel@tonic-gate 		 * Attempt to bind to pool before calling
5207c478bd9Sstevel@tonic-gate 		 * settaskid().
5217c478bd9Sstevel@tonic-gate 		 */
5227c478bd9Sstevel@tonic-gate 		if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
5237c478bd9Sstevel@tonic-gate 		    KV_DELIMITER)) != NULL) {
5247c478bd9Sstevel@tonic-gate 			for (i = 0; i < kv_array->length; i++) {
5257c478bd9Sstevel@tonic-gate 				if (strcmp(kv_array->data[i].key,
5267c478bd9Sstevel@tonic-gate 				    "project.pool") == 0) {
5277c478bd9Sstevel@tonic-gate 					pool_name = kv_array->data[i].value;
5287c478bd9Sstevel@tonic-gate 					break;
5297c478bd9Sstevel@tonic-gate 				}
5307c478bd9Sstevel@tonic-gate 				if (strcmp(kv_array->data[i].key,
5317c478bd9Sstevel@tonic-gate 				    "task.final") == 0) {
5327c478bd9Sstevel@tonic-gate 					taskflags |= TASK_FINAL;
5337c478bd9Sstevel@tonic-gate 				}
5347c478bd9Sstevel@tonic-gate 			}
5357c478bd9Sstevel@tonic-gate 		}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		old_pool_name = pool_get_binding(pid);
538*0209230bSgjelinek 
539*0209230bSgjelinek 		/*
540*0209230bSgjelinek 		 * If parent is not bound to the default pool, then we want
541*0209230bSgjelinek 		 * to preserve same binding as parent.
542*0209230bSgjelinek 		 */
543*0209230bSgjelinek 		if (pool_name != NULL && bind_to_pool(pool_name, pid, 0) != 0) {
5447c478bd9Sstevel@tonic-gate 			if (old_pool_name)
5457c478bd9Sstevel@tonic-gate 				free(old_pool_name);
5467c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
5477c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_POOL);
5487c478bd9Sstevel@tonic-gate 		}
5497c478bd9Sstevel@tonic-gate 		if (pr_settaskid(Pr, projid, taskflags) == -1) {
5507c478bd9Sstevel@tonic-gate 			int saved_errno = errno;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 			/*
5537c478bd9Sstevel@tonic-gate 			 * Undo pool binding.
5547c478bd9Sstevel@tonic-gate 			 */
5557c478bd9Sstevel@tonic-gate 			(void) bind_to_pool(old_pool_name, pid, 1);
5567c478bd9Sstevel@tonic-gate 			if (old_pool_name)
5577c478bd9Sstevel@tonic-gate 				free(old_pool_name);
5587c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
5597c478bd9Sstevel@tonic-gate 			/*
5607c478bd9Sstevel@tonic-gate 			 * Restore errno
5617c478bd9Sstevel@tonic-gate 			 */
5627c478bd9Sstevel@tonic-gate 			errno = saved_errno;
5637c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
5647c478bd9Sstevel@tonic-gate 		}
5657c478bd9Sstevel@tonic-gate 		if (old_pool_name)
5667c478bd9Sstevel@tonic-gate 			free(old_pool_name);
5677c478bd9Sstevel@tonic-gate 	} else {
5687c478bd9Sstevel@tonic-gate 		/*
5697c478bd9Sstevel@tonic-gate 		 * Pools are not configured, so simply create new task.
5707c478bd9Sstevel@tonic-gate 		 */
5717c478bd9Sstevel@tonic-gate 		if (pr_settaskid(Pr, projid, flags) == -1)
5727c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
5737c478bd9Sstevel@tonic-gate 		kv_array = _str2kva(proj->pj_attr, KV_ASSIGN, KV_DELIMITER);
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if (project_name == NULL) {
5777c478bd9Sstevel@tonic-gate 		/*
5787c478bd9Sstevel@tonic-gate 		 * In the case that we are starting a new task in the
5797c478bd9Sstevel@tonic-gate 		 * current project, we are finished, since the current
5807c478bd9Sstevel@tonic-gate 		 * resource controls will still apply. (Implicit behaviour:
5817c478bd9Sstevel@tonic-gate 		 * a project must be entirely logged out before name
5827c478bd9Sstevel@tonic-gate 		 * service changes will take effect.)
5837c478bd9Sstevel@tonic-gate 		 */
5847c478bd9Sstevel@tonic-gate 		_kva_free(kv_array);
5857c478bd9Sstevel@tonic-gate 		return (projid);
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (kv_array == NULL)
5897c478bd9Sstevel@tonic-gate 		return (0);
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	for (i = 0; i < kv_array->length; i++) {
5927c478bd9Sstevel@tonic-gate 		/*
5937c478bd9Sstevel@tonic-gate 		 * Providing a special, i.e. a non-resource control, key?  Then
5947c478bd9Sstevel@tonic-gate 		 * parse that key here and end with "continue;".
5957c478bd9Sstevel@tonic-gate 		 */
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 		/*
5987c478bd9Sstevel@tonic-gate 		 * For generic bindings, the kernel performs the binding, as
5997c478bd9Sstevel@tonic-gate 		 * these are resource controls advertised by kernel subsystems.
6007c478bd9Sstevel@tonic-gate 		 */
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 		/*
6037c478bd9Sstevel@tonic-gate 		 * Check for known attribute name.
6047c478bd9Sstevel@tonic-gate 		 */
6057c478bd9Sstevel@tonic-gate 		errno = 0;
6067c478bd9Sstevel@tonic-gate 		if (rctl_walk(rctlwalkfunc, (void *)kv_array->data[i].key)
6077c478bd9Sstevel@tonic-gate 		    == 0)
6087c478bd9Sstevel@tonic-gate 			continue;
6097c478bd9Sstevel@tonic-gate 		if (errno) {
6107c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
6117c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6127c478bd9Sstevel@tonic-gate 		}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 		ret = rctl_set(kv_array->data[i].key,
6157c478bd9Sstevel@tonic-gate 		    kv_array->data[i].value, Pr);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 		if (ret && unknown == 0) {
6187c478bd9Sstevel@tonic-gate 			/*
6197c478bd9Sstevel@tonic-gate 			 * We only report the first failure.
6207c478bd9Sstevel@tonic-gate 			 */
6217c478bd9Sstevel@tonic-gate 			unknown = i + 1;
6227c478bd9Sstevel@tonic-gate 		}
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 		if (ret && ret != SETFAILED) {
6257c478bd9Sstevel@tonic-gate 			/*
6267c478bd9Sstevel@tonic-gate 			 * We abort if we couldn't set a component, but if
6277c478bd9Sstevel@tonic-gate 			 * it's merely that the system didn't recognize it, we
6287c478bd9Sstevel@tonic-gate 			 * continue, as this could be a third party attribute.
6297c478bd9Sstevel@tonic-gate 			 */
6307c478bd9Sstevel@tonic-gate 			break;
6317c478bd9Sstevel@tonic-gate 		}
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 	_kva_free(kv_array);
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	return (unknown);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate projid_t
6397c478bd9Sstevel@tonic-gate setproject(const char *project_name, const char *user_name, int flags)
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate 	return (setproject_proc(project_name, user_name, flags, P_MYID, NULL,
6427c478bd9Sstevel@tonic-gate 	    NULL));
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate priv_set_t *
6477c478bd9Sstevel@tonic-gate setproject_initpriv(void)
6487c478bd9Sstevel@tonic-gate {
6497c478bd9Sstevel@tonic-gate 	static priv_t taskpriv = PRIV_PROC_TASKID;
6507c478bd9Sstevel@tonic-gate 	static priv_t rctlpriv = PRIV_SYS_RESOURCE;
6517c478bd9Sstevel@tonic-gate 	static priv_t poolpriv = PRIV_SYS_RES_CONFIG;
6527c478bd9Sstevel@tonic-gate 	static priv_t schedpriv = PRIV_PROC_PRIOCNTL;
6537c478bd9Sstevel@tonic-gate 	int res;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	priv_set_t *nset;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
6587c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, poolpriv,
6597c478bd9Sstevel@tonic-gate 		    schedpriv, (char *)NULL);
6607c478bd9Sstevel@tonic-gate 	} else {
6617c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, (char *)NULL);
6627c478bd9Sstevel@tonic-gate 	}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	if (res != 0)
6657c478bd9Sstevel@tonic-gate 		return (NULL);
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	nset = priv_allocset();
6687c478bd9Sstevel@tonic-gate 	if (nset != NULL) {
6697c478bd9Sstevel@tonic-gate 		priv_emptyset(nset);
6707c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, taskpriv);
6717c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, rctlpriv);
6727c478bd9Sstevel@tonic-gate 		/*
6737c478bd9Sstevel@tonic-gate 		 * Only need these if we need to change pools, which can
6747c478bd9Sstevel@tonic-gate 		 * only happen if the target is in the global zone.  Rather
6757c478bd9Sstevel@tonic-gate 		 * than checking the target's zone just check our own
6767c478bd9Sstevel@tonic-gate 		 * (since if we're in a non-global zone we won't be able
6777c478bd9Sstevel@tonic-gate 		 * to control processes in other zones).
6787c478bd9Sstevel@tonic-gate 		 */
6797c478bd9Sstevel@tonic-gate 		if (getzoneid() == GLOBAL_ZONEID) {
6807c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, poolpriv);
6817c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, schedpriv);
6827c478bd9Sstevel@tonic-gate 		}
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 	return (nset);
6857c478bd9Sstevel@tonic-gate }
686