xref: /titanic_44/usr/src/lib/libproject/common/setproject.c (revision 532877c46d04a2d0b254f9b5797720078adcea07)
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
50209230bSgjelinek  * Common Development and Distribution License (the "License").
60209230bSgjelinek  * 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*532877c4Srd117015  * Copyright 2007 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>
39*532877c4Srd117015 #include <strings.h>
407c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
417c478bd9Sstevel@tonic-gate #include <pwd.h>
427c478bd9Sstevel@tonic-gate #include <pool.h>
437c478bd9Sstevel@tonic-gate #include <libproc.h>
447c478bd9Sstevel@tonic-gate #include <priv.h>
457c478bd9Sstevel@tonic-gate #include <priv_utils.h>
467c478bd9Sstevel@tonic-gate #include <zone.h>
477c478bd9Sstevel@tonic-gate #include <sys/pool.h>
487c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h>
49*532877c4Srd117015 #include <sys/rctl_impl.h>
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static void
527c478bd9Sstevel@tonic-gate xstrtolower(char *s)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++)
557c478bd9Sstevel@tonic-gate 		*s = tolower(*s);
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static void
597c478bd9Sstevel@tonic-gate remove_spaces(char *s)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate 	char *current;
627c478bd9Sstevel@tonic-gate 	char *next;
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	current = next = s;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	while (*next != '\0') {
677c478bd9Sstevel@tonic-gate 		while (isspace(*next))
687c478bd9Sstevel@tonic-gate 		    next++;
697c478bd9Sstevel@tonic-gate 		*current++ = *next++;
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 	*current = '\0';
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate int
757c478bd9Sstevel@tonic-gate build_rctlblk(rctlblk_t *blk, int comp_num, char *component)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 	char *signam;
787c478bd9Sstevel@tonic-gate 	int sig = 0;
797c478bd9Sstevel@tonic-gate 	uint_t act = rctlblk_get_local_action(blk, &sig);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	if (comp_num == 0) {
827c478bd9Sstevel@tonic-gate 		/*
837c478bd9Sstevel@tonic-gate 		 * Setting privilege level for resource control block.
847c478bd9Sstevel@tonic-gate 		 */
857c478bd9Sstevel@tonic-gate 		xstrtolower(component);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 		if (strcmp("basic", component) == 0) {
887c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_BASIC);
897c478bd9Sstevel@tonic-gate 			return (0);
907c478bd9Sstevel@tonic-gate 		}
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 		if (strcmp("priv", component) == 0 ||
937c478bd9Sstevel@tonic-gate 		    strcmp("privileged", component) == 0) {
947c478bd9Sstevel@tonic-gate 			rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
957c478bd9Sstevel@tonic-gate 			return (0);
967c478bd9Sstevel@tonic-gate 		}
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 		return (-1);
997c478bd9Sstevel@tonic-gate 	}
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (comp_num == 1) {
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 		/*
1047c478bd9Sstevel@tonic-gate 		 * Setting value for resource control block.
1057c478bd9Sstevel@tonic-gate 		 */
1067c478bd9Sstevel@tonic-gate 		unsigned long long val;
1077c478bd9Sstevel@tonic-gate 		char *t;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 		/* Negative numbers are not allowed */
1107c478bd9Sstevel@tonic-gate 		if (strchr(component, '-') != NULL)
1117c478bd9Sstevel@tonic-gate 			return (-1);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		errno = 0;
1147c478bd9Sstevel@tonic-gate 		val = strtoull(component, &t, 10);
1157c478bd9Sstevel@tonic-gate 		if (errno != 0 || t == component || *t != '\0')
1167c478bd9Sstevel@tonic-gate 			return (-1);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 		rctlblk_set_value(blk, (rctl_qty_t)val);
1197c478bd9Sstevel@tonic-gate 		return (0);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/*
1237c478bd9Sstevel@tonic-gate 	 * Setting one or more actions on this resource control block.
1247c478bd9Sstevel@tonic-gate 	 */
1257c478bd9Sstevel@tonic-gate 	if (comp_num >= 2) {
1267c478bd9Sstevel@tonic-gate 		if (strcmp("none", component) == 0) {
1277c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, 0, 0);
1287c478bd9Sstevel@tonic-gate 			return (0);
1297c478bd9Sstevel@tonic-gate 		}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 		if (strcmp("deny", component) == 0) {
1327c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_DENY;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 			return (0);
1377c478bd9Sstevel@tonic-gate 		}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 		/*
1407c478bd9Sstevel@tonic-gate 		 * The last, and trickiest, form of action is the signal
1417c478bd9Sstevel@tonic-gate 		 * specification.
1427c478bd9Sstevel@tonic-gate 		 */
1437c478bd9Sstevel@tonic-gate 		if ((signam = strchr(component, '=')) == NULL)
1447c478bd9Sstevel@tonic-gate 			return (-1);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 		*signam++ = '\0';
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 		if (strcmp("sig", component) == 0 ||
1497c478bd9Sstevel@tonic-gate 		    strcmp("signal", component) == 0) {
1507c478bd9Sstevel@tonic-gate 			if (strncmp("SIG", signam, 3) == 0)
1517c478bd9Sstevel@tonic-gate 				signam += 3;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 			if (str2sig(signam, &sig) == -1)
1547c478bd9Sstevel@tonic-gate 				return (-1);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 			act |= RCTL_LOCAL_SIGNAL;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 			rctlblk_set_local_action(blk, act, sig);
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 			return (0);
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 	return (-1);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate  * States:
1687c478bd9Sstevel@tonic-gate  */
1697c478bd9Sstevel@tonic-gate #define	INPAREN		0x1
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Errors:
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate #define	SETFAILED	(-1)
1757c478bd9Sstevel@tonic-gate #define	COMPLETE	1
1767c478bd9Sstevel@tonic-gate #define	NESTING		2
1777c478bd9Sstevel@tonic-gate #define	UNCLOSED	3
1787c478bd9Sstevel@tonic-gate #define	CLOSEBEFOREOPEN	4
1797c478bd9Sstevel@tonic-gate #define	BADSPEC		5
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static int
182*532877c4Srd117015 rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr, int flags)
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	int error = 0;
1857c478bd9Sstevel@tonic-gate 	uint_t component = 0;
1867c478bd9Sstevel@tonic-gate 	int valuecount = 0;
1877c478bd9Sstevel@tonic-gate 	uint_t state = 0;
1887c478bd9Sstevel@tonic-gate 	char *component_head;
1897c478bd9Sstevel@tonic-gate 	rctlblk_t *blk;
190*532877c4Srd117015 	rctlblk_t *ablk;
191*532877c4Srd117015 	int project_entity = 0;
192*532877c4Srd117015 	int count = 0;
193*532877c4Srd117015 	char *tmp;
194*532877c4Srd117015 	int local_action;
1957c478bd9Sstevel@tonic-gate 
196*532877c4Srd117015 	/* We cannot modify a zone resource control */
197*532877c4Srd117015 	if (strncmp(ctl_name, "zone.", strlen("zone.")) == 0) {
1987c478bd9Sstevel@tonic-gate 		return (SETFAILED);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
201*532877c4Srd117015 	remove_spaces(val);
202*532877c4Srd117015 
2037c478bd9Sstevel@tonic-gate 	/*
204*532877c4Srd117015 	 * As we are operating in a new task, both process and task
205*532877c4Srd117015 	 * rctls are referenced by this process alone.  Tear down
206*532877c4Srd117015 	 * matching process and task rctls only.
207*532877c4Srd117015 	 *
208*532877c4Srd117015 	 * blk will be the RCPRIV_SYSTEM for this resource control,
209*532877c4Srd117015 	 * populated by the last pr_setrctl().
2107c478bd9Sstevel@tonic-gate 	 */
211*532877c4Srd117015 	if ((strncmp(ctl_name, "process.", strlen("process.")) == 0) ||
212*532877c4Srd117015 	    (strncmp(ctl_name, "task.", strlen("task.")) == 0)) {
213*532877c4Srd117015 
214*532877c4Srd117015 		if ((blk = (rctlblk_t *)malloc(rctlblk_size())) == NULL) {
215*532877c4Srd117015 			return (SETFAILED);
216*532877c4Srd117015 		}
217*532877c4Srd117015 
218*532877c4Srd117015 
2197c478bd9Sstevel@tonic-gate 		while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 &&
2207c478bd9Sstevel@tonic-gate 		    rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) {
2217c478bd9Sstevel@tonic-gate 			(void) pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE);
2227c478bd9Sstevel@tonic-gate 		}
2237c478bd9Sstevel@tonic-gate 
224*532877c4Srd117015 	} else if (strncmp(ctl_name, "project.", strlen("project.")) == 0) {
225*532877c4Srd117015 		project_entity = 1;
226*532877c4Srd117015 
227*532877c4Srd117015 		/* Determine how many attributes we'll be setting */
228*532877c4Srd117015 		for (tmp = val; *tmp != '\0'; tmp++) {
229*532877c4Srd117015 			if (*tmp == '(')
230*532877c4Srd117015 				count++;
231*532877c4Srd117015 		}
232*532877c4Srd117015 
233*532877c4Srd117015 		/* Allocate sufficient memory for rctl blocks */
234*532877c4Srd117015 		if ((count == 0) || ((ablk =
235*532877c4Srd117015 		    (rctlblk_t *)malloc(rctlblk_size() * count)) == NULL)) {
236*532877c4Srd117015 			return (SETFAILED);
237*532877c4Srd117015 		}
238*532877c4Srd117015 		blk = ablk;
239*532877c4Srd117015 
240*532877c4Srd117015 		/*
241*532877c4Srd117015 		 * In order to set the new rctl's local_action, we'll need the
242*532877c4Srd117015 		 * current value of global_flags.  We obtain global_flags by
243*532877c4Srd117015 		 * performing a pr_getrctl().
244*532877c4Srd117015 		 *
245*532877c4Srd117015 		 * The ctl_name has been verified as valid, so we have no reason
246*532877c4Srd117015 		 * to suspect that pr_getrctl() will return an error.
247*532877c4Srd117015 		 */
248*532877c4Srd117015 		(void) pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST);
249*532877c4Srd117015 
250*532877c4Srd117015 	} else {
251*532877c4Srd117015 		return (SETFAILED);
252*532877c4Srd117015 	}
253*532877c4Srd117015 
2547c478bd9Sstevel@tonic-gate 	/*
2557c478bd9Sstevel@tonic-gate 	 * Set initial local action based on global deny properties.
2567c478bd9Sstevel@tonic-gate 	 */
2577c478bd9Sstevel@tonic-gate 	rctlblk_set_privilege(blk, RCPRIV_PRIVILEGED);
2587c478bd9Sstevel@tonic-gate 	rctlblk_set_value(blk, 0);
2597c478bd9Sstevel@tonic-gate 	rctlblk_set_local_flags(blk, 0);
2607c478bd9Sstevel@tonic-gate 
261*532877c4Srd117015 	if (rctlblk_get_global_flags(blk) & RCTL_GLOBAL_DENY_ALWAYS)
262*532877c4Srd117015 		local_action = RCTL_LOCAL_DENY;
263*532877c4Srd117015 	else
264*532877c4Srd117015 		local_action = RCTL_LOCAL_NOACTION;
265*532877c4Srd117015 
266*532877c4Srd117015 	rctlblk_set_local_action(blk, local_action, 0);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	for (; ; val++) {
2697c478bd9Sstevel@tonic-gate 		switch (*val) {
2707c478bd9Sstevel@tonic-gate 			case '(':
2717c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
2727c478bd9Sstevel@tonic-gate 					error = NESTING;
2737c478bd9Sstevel@tonic-gate 					break;
2747c478bd9Sstevel@tonic-gate 				}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 				state |= INPAREN;
2777c478bd9Sstevel@tonic-gate 				component_head = (char *)val + 1;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 				break;
2807c478bd9Sstevel@tonic-gate 			case ')':
2817c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
2827c478bd9Sstevel@tonic-gate 					*val = '\0';
2837c478bd9Sstevel@tonic-gate 					if (component < 2) {
2847c478bd9Sstevel@tonic-gate 						error = BADSPEC;
2857c478bd9Sstevel@tonic-gate 						break;
2867c478bd9Sstevel@tonic-gate 					}
2877c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
2887c478bd9Sstevel@tonic-gate 					    component_head) == -1) {
2897c478bd9Sstevel@tonic-gate 						error = BADSPEC;
2907c478bd9Sstevel@tonic-gate 						break;
2917c478bd9Sstevel@tonic-gate 					}
2927c478bd9Sstevel@tonic-gate 					state &= ~INPAREN;
2937c478bd9Sstevel@tonic-gate 					component = 0;
2947c478bd9Sstevel@tonic-gate 					valuecount++;
295*532877c4Srd117015 
296*532877c4Srd117015 					if (project_entity &&
297*532877c4Srd117015 					    (rctlblk_get_privilege(blk) ==
298*532877c4Srd117015 					    RCPRIV_BASIC)) {
2997c478bd9Sstevel@tonic-gate 						error = SETFAILED;
300*532877c4Srd117015 					} else if (project_entity) {
301*532877c4Srd117015 						if (valuecount > count)
302*532877c4Srd117015 							return (SETFAILED);
303*532877c4Srd117015 
304*532877c4Srd117015 						if (valuecount != count)
305*532877c4Srd117015 							blk = RCTLBLK_INC(ablk,
306*532877c4Srd117015 								valuecount);
307*532877c4Srd117015 					} else {
308*532877c4Srd117015 						if (pr_setrctl(Pr, ctl_name,
309*532877c4Srd117015 						    NULL, blk, RCTL_INSERT) ==
310*532877c4Srd117015 						    -1)
311*532877c4Srd117015 							error = SETFAILED;
312*532877c4Srd117015 					}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 					/* re-initialize block */
315*532877c4Srd117015 					if (!project_entity ||
316*532877c4Srd117015 					    (valuecount != count)) {
3177c478bd9Sstevel@tonic-gate 						rctlblk_set_privilege(blk,
3187c478bd9Sstevel@tonic-gate 						    RCPRIV_PRIVILEGED);
3197c478bd9Sstevel@tonic-gate 						rctlblk_set_value(blk, 0);
3207c478bd9Sstevel@tonic-gate 						rctlblk_set_local_flags(blk, 0);
3217c478bd9Sstevel@tonic-gate 						rctlblk_set_local_action(blk,
322*532877c4Srd117015 						    local_action, 0);
323*532877c4Srd117015 					}
3247c478bd9Sstevel@tonic-gate 				} else {
3257c478bd9Sstevel@tonic-gate 					error = CLOSEBEFOREOPEN;
3267c478bd9Sstevel@tonic-gate 				}
3277c478bd9Sstevel@tonic-gate 				break;
3287c478bd9Sstevel@tonic-gate 			case ',':
3297c478bd9Sstevel@tonic-gate 				if (state & INPAREN) {
3307c478bd9Sstevel@tonic-gate 					*val = '\0';
3317c478bd9Sstevel@tonic-gate 					if (build_rctlblk(blk, component,
3327c478bd9Sstevel@tonic-gate 					    component_head) == -1)
3337c478bd9Sstevel@tonic-gate 						error = BADSPEC;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 					component++;
3367c478bd9Sstevel@tonic-gate 					component_head = (char *)val + 1;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 				}
3397c478bd9Sstevel@tonic-gate 				break;
3407c478bd9Sstevel@tonic-gate 			case '\0':
3417c478bd9Sstevel@tonic-gate 				if (valuecount == 0)
3427c478bd9Sstevel@tonic-gate 					error = BADSPEC;
3437c478bd9Sstevel@tonic-gate 				else if (state & INPAREN)
3447c478bd9Sstevel@tonic-gate 					error = UNCLOSED;
3457c478bd9Sstevel@tonic-gate 				else
3467c478bd9Sstevel@tonic-gate 					error = COMPLETE;
3477c478bd9Sstevel@tonic-gate 				break;
3487c478bd9Sstevel@tonic-gate 			default:
3497c478bd9Sstevel@tonic-gate 				if (!(state & INPAREN))
3507c478bd9Sstevel@tonic-gate 					error = BADSPEC;
3517c478bd9Sstevel@tonic-gate 				break;
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		if (error)
3557c478bd9Sstevel@tonic-gate 			break;
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
358*532877c4Srd117015 	if (project_entity) {
359*532877c4Srd117015 		blk = ablk;
360*532877c4Srd117015 		if (pr_setprojrctl(Pr, ctl_name, blk, count, flags) == -1)
361*532877c4Srd117015 			error = SETFAILED;
362*532877c4Srd117015 	}
363*532877c4Srd117015 
3647c478bd9Sstevel@tonic-gate 	free(blk);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	if (valuecount == 0)
3677c478bd9Sstevel@tonic-gate 		error = BADSPEC;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (error != COMPLETE)
3707c478bd9Sstevel@tonic-gate 		return (error);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	return (0);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate static int
3767c478bd9Sstevel@tonic-gate rctlwalkfunc(const char *name, void *data)
3777c478bd9Sstevel@tonic-gate {
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (strcmp(name, (char *)data) == 0)
3807c478bd9Sstevel@tonic-gate 		return (-1);
3817c478bd9Sstevel@tonic-gate 	else
3827c478bd9Sstevel@tonic-gate 		return (0);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * This routine determines if /dev/pool device is present on the system and
3887c478bd9Sstevel@tonic-gate  * pools are currently enabled.  We want to do this directly from libproject
3897c478bd9Sstevel@tonic-gate  * without using libpool's pool_get_status() routine because pools could be
3907c478bd9Sstevel@tonic-gate  * completely removed from the system.  Return 1 if pools are enabled, or
3917c478bd9Sstevel@tonic-gate  * 0 otherwise.  When used inside local zones, always pretend that pools
3927c478bd9Sstevel@tonic-gate  * are disabled because binding is not allowed and we're already in the
3937c478bd9Sstevel@tonic-gate  * right pool.
3947c478bd9Sstevel@tonic-gate  */
3957c478bd9Sstevel@tonic-gate static int
3967c478bd9Sstevel@tonic-gate pools_enabled(void)
3977c478bd9Sstevel@tonic-gate {
3987c478bd9Sstevel@tonic-gate 	pool_status_t status;
3997c478bd9Sstevel@tonic-gate 	int fd;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (getzoneid() != GLOBAL_ZONEID)
4027c478bd9Sstevel@tonic-gate 		return (0);
4037c478bd9Sstevel@tonic-gate 	if ((fd = open("/dev/pool", O_RDONLY)) < 0)
4047c478bd9Sstevel@tonic-gate 		return (0);
4057c478bd9Sstevel@tonic-gate 	if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
4067c478bd9Sstevel@tonic-gate 		(void) close(fd);
4077c478bd9Sstevel@tonic-gate 		return (0);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 	(void) close(fd);
4107c478bd9Sstevel@tonic-gate 	return (status.ps_io_state);
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate  * A pool_name of NULL means to attempt to bind to the default pool.
4157c478bd9Sstevel@tonic-gate  * If the "force" flag is non-zero, the value of "system.bind-default" will be
4167c478bd9Sstevel@tonic-gate  * ignored, and the process will be bound to the default pool if one exists.
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate static int
4197c478bd9Sstevel@tonic-gate bind_to_pool(const char *pool_name, pid_t pid, int force)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	pool_value_t *pvals[] = { NULL, NULL };
4227c478bd9Sstevel@tonic-gate 	pool_t **pools;
4237c478bd9Sstevel@tonic-gate 	uint_t nelem;
4247c478bd9Sstevel@tonic-gate 	uchar_t bval;
4257c478bd9Sstevel@tonic-gate 	pool_conf_t *conf;
4267c478bd9Sstevel@tonic-gate 	const char *nm;
4277c478bd9Sstevel@tonic-gate 	int retval;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	if ((conf = pool_conf_alloc()) == NULL)
4307c478bd9Sstevel@tonic-gate 		return (-1);
4317c478bd9Sstevel@tonic-gate 	if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) < 0) {
4327c478bd9Sstevel@tonic-gate 		/*
4337c478bd9Sstevel@tonic-gate 		 * Pools configuration file is corrupted; allow logins.
4347c478bd9Sstevel@tonic-gate 		 */
4357c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4367c478bd9Sstevel@tonic-gate 		return (0);
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 	if (pool_name != NULL && pool_get_pool(conf, pool_name) != NULL) {
4397c478bd9Sstevel@tonic-gate 		/*
4407c478bd9Sstevel@tonic-gate 		 * There was a project.pool entry, and the pool it refers to
4417c478bd9Sstevel@tonic-gate 		 * is a valid (active) pool.
4427c478bd9Sstevel@tonic-gate 		 */
4437c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
4447c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4457c478bd9Sstevel@tonic-gate 		if (pool_set_binding(pool_name, P_PID, pid) != PO_SUCCESS) {
4467c478bd9Sstevel@tonic-gate 			if (pool_error() != POE_SYSTEM)
4477c478bd9Sstevel@tonic-gate 				errno = EINVAL;
4487c478bd9Sstevel@tonic-gate 			return (-1);
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 		return (0);
4517c478bd9Sstevel@tonic-gate 	}
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * Bind to the pool with 'pool.default' = 'true' if
4557c478bd9Sstevel@tonic-gate 	 * 'system.bind-default' = 'true'.
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 	if ((pvals[0] = pool_value_alloc()) == NULL) {
4587c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
4597c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4607c478bd9Sstevel@tonic-gate 		return (-1);
4617c478bd9Sstevel@tonic-gate 	}
4627c478bd9Sstevel@tonic-gate 	if (!force && pool_get_property(conf, pool_conf_to_elem(conf),
4637c478bd9Sstevel@tonic-gate 	    "system.bind-default", pvals[0]) != POC_BOOL ||
4647c478bd9Sstevel@tonic-gate 	    pool_value_get_bool(pvals[0], &bval) != PO_SUCCESS ||
4657c478bd9Sstevel@tonic-gate 	    bval == PO_FALSE) {
4667c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
4677c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
4687c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4697c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
4707c478bd9Sstevel@tonic-gate 		return (-1);
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 	(void) pool_value_set_name(pvals[0], "pool.default");
4737c478bd9Sstevel@tonic-gate 	pool_value_set_bool(pvals[0], PO_TRUE);
4747c478bd9Sstevel@tonic-gate 	if ((pools = pool_query_pools(conf, &nelem, pvals)) == NULL) {
4757c478bd9Sstevel@tonic-gate 		/*
4767c478bd9Sstevel@tonic-gate 		 * No default pools exist.
4777c478bd9Sstevel@tonic-gate 		 */
4787c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
4797c478bd9Sstevel@tonic-gate 		pool_conf_close(conf);
4807c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4817c478bd9Sstevel@tonic-gate 		errno = pool_name == NULL ? EACCES : ESRCH;
4827c478bd9Sstevel@tonic-gate 		return (-1);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 	if (nelem != 1 ||
4857c478bd9Sstevel@tonic-gate 	    pool_get_property(conf, pool_to_elem(conf, pools[0]), "pool.name",
4867c478bd9Sstevel@tonic-gate 	    pvals[0]) != POC_STRING) {
4877c478bd9Sstevel@tonic-gate 		/*
4887c478bd9Sstevel@tonic-gate 		 * Configuration is invalid.
4897c478bd9Sstevel@tonic-gate 		 */
4907c478bd9Sstevel@tonic-gate 		free(pools);
4917c478bd9Sstevel@tonic-gate 		pool_value_free(pvals[0]);
4927c478bd9Sstevel@tonic-gate 		(void) pool_conf_close(conf);
4937c478bd9Sstevel@tonic-gate 		pool_conf_free(conf);
4947c478bd9Sstevel@tonic-gate 		return (0);
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 	free(pools);
4977c478bd9Sstevel@tonic-gate 	(void) pool_conf_close(conf);
4987c478bd9Sstevel@tonic-gate 	pool_conf_free(conf);
4997c478bd9Sstevel@tonic-gate 	(void) pool_value_get_string(pvals[0], &nm);
5007c478bd9Sstevel@tonic-gate 	if (pool_set_binding(nm, P_PID, pid) != PO_SUCCESS) {
5017c478bd9Sstevel@tonic-gate 		if (pool_error() != POE_SYSTEM)
5027c478bd9Sstevel@tonic-gate 			errno = EINVAL;
5037c478bd9Sstevel@tonic-gate 		retval = -1;
5047c478bd9Sstevel@tonic-gate 	} else {
5057c478bd9Sstevel@tonic-gate 		retval = 0;
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 	pool_value_free(pvals[0]);
5087c478bd9Sstevel@tonic-gate 	return (retval);
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate /*
5127c478bd9Sstevel@tonic-gate  * Changes the assigned project, task and resource pool of a stopped target
5137c478bd9Sstevel@tonic-gate  * process.
5147c478bd9Sstevel@tonic-gate  *
5157c478bd9Sstevel@tonic-gate  * We may not have access to the project table if our target process is in
5167c478bd9Sstevel@tonic-gate  * getprojbyname()'s execution path. Similarly, we may not be able to get user
5177c478bd9Sstevel@tonic-gate  * information if the target process is in getpwnam()'s execution path. Thus we
5187c478bd9Sstevel@tonic-gate  * give the caller the option of skipping these checks by providing a pointer to
5197c478bd9Sstevel@tonic-gate  * a pre-validated project structure in proj (whose name matches project_name)
5207c478bd9Sstevel@tonic-gate  * and taking responsibility for ensuring that the target process' owner is a
5217c478bd9Sstevel@tonic-gate  * member of the target project.
5227c478bd9Sstevel@tonic-gate  *
5237c478bd9Sstevel@tonic-gate  * Callers of this function should always provide a pre-validated project
5247c478bd9Sstevel@tonic-gate  * structure in proj unless they can be sure that the target process will never
5257c478bd9Sstevel@tonic-gate  * be in setproject_proc()'s execution path.
5267c478bd9Sstevel@tonic-gate  */
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate projid_t
5297c478bd9Sstevel@tonic-gate setproject_proc(const char *project_name, const char *user_name, int flags,
5307c478bd9Sstevel@tonic-gate     pid_t pid, struct ps_prochandle *Pr, struct project *proj)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	char pwdbuf[NSS_BUFLEN_PASSWD];
5337c478bd9Sstevel@tonic-gate 	char prbuf[PROJECT_BUFSZ];
5347c478bd9Sstevel@tonic-gate 	projid_t projid;
5357c478bd9Sstevel@tonic-gate 	struct passwd pwd;
5367c478bd9Sstevel@tonic-gate 	int i;
5377c478bd9Sstevel@tonic-gate 	int unknown = 0;
5387c478bd9Sstevel@tonic-gate 	int ret = 0;
5397c478bd9Sstevel@tonic-gate 	kva_t *kv_array;
5407c478bd9Sstevel@tonic-gate 	struct project local_proj; /* space to store proj if not provided */
541*532877c4Srd117015 	const char *pool_name = NULL;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	if (project_name != NULL) {
5447c478bd9Sstevel@tonic-gate 		/*
5457c478bd9Sstevel@tonic-gate 		 * Sanity checks.
5467c478bd9Sstevel@tonic-gate 		 */
5477c478bd9Sstevel@tonic-gate 		if (strcmp(project_name, "") == 0 ||
5487c478bd9Sstevel@tonic-gate 		    user_name == NULL) {
5497c478bd9Sstevel@tonic-gate 			errno = EINVAL;
5507c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
5517c478bd9Sstevel@tonic-gate 		}
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 		/*
5547c478bd9Sstevel@tonic-gate 		 * If proj is NULL, acquire project information to ensure that
5557c478bd9Sstevel@tonic-gate 		 * project_name is a valid project, and confirm that user_name
5567c478bd9Sstevel@tonic-gate 		 * exists and is a member of the specified project.
5577c478bd9Sstevel@tonic-gate 		 */
5587c478bd9Sstevel@tonic-gate 		if (proj == NULL) {
5597c478bd9Sstevel@tonic-gate 			if ((proj = getprojbyname(project_name, &local_proj,
5607c478bd9Sstevel@tonic-gate 			    prbuf, PROJECT_BUFSZ)) == NULL) {
5617c478bd9Sstevel@tonic-gate 				errno = ESRCH;
5627c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
5637c478bd9Sstevel@tonic-gate 			}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 			if (getpwnam_r(user_name, &pwd,
5667c478bd9Sstevel@tonic-gate 			    pwdbuf, NSS_BUFLEN_PASSWD) == NULL) {
5677c478bd9Sstevel@tonic-gate 				errno = ESRCH;
5687c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
5697c478bd9Sstevel@tonic-gate 			}
5707c478bd9Sstevel@tonic-gate 			/*
5717c478bd9Sstevel@tonic-gate 			 * Root can join any project.
5727c478bd9Sstevel@tonic-gate 			 */
5737c478bd9Sstevel@tonic-gate 			if (pwd.pw_uid != (uid_t)0 &&
5747c478bd9Sstevel@tonic-gate 			    !inproj(user_name, project_name, prbuf,
5757c478bd9Sstevel@tonic-gate 			    PROJECT_BUFSZ)) {
5767c478bd9Sstevel@tonic-gate 				errno = ESRCH;
5777c478bd9Sstevel@tonic-gate 				return (SETPROJ_ERR_TASK);
5787c478bd9Sstevel@tonic-gate 			}
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 		projid = proj->pj_projid;
5817c478bd9Sstevel@tonic-gate 	} else {
5827c478bd9Sstevel@tonic-gate 		projid = getprojid();
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
585*532877c4Srd117015 
5867c478bd9Sstevel@tonic-gate 	if ((kv_array = _str2kva(proj->pj_attr, KV_ASSIGN,
5877c478bd9Sstevel@tonic-gate 	    KV_DELIMITER)) != NULL) {
5887c478bd9Sstevel@tonic-gate 		for (i = 0; i < kv_array->length; i++) {
5897c478bd9Sstevel@tonic-gate 			if (strcmp(kv_array->data[i].key,
5907c478bd9Sstevel@tonic-gate 			    "project.pool") == 0) {
5917c478bd9Sstevel@tonic-gate 				pool_name = kv_array->data[i].value;
5927c478bd9Sstevel@tonic-gate 			}
593*532877c4Srd117015 			if (strcmp(kv_array->data[i].key, "task.final") == 0) {
594*532877c4Srd117015 				flags |= TASK_FINAL;
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 		}
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 
5990209230bSgjelinek 	/*
600*532877c4Srd117015 	 * Bind process to a pool only if pools are configured
6010209230bSgjelinek 	 */
602*532877c4Srd117015 	if (pools_enabled() == 1) {
603*532877c4Srd117015 		char *old_pool_name;
604*532877c4Srd117015 		/*
605*532877c4Srd117015 		 * Attempt to bind to pool before calling
606*532877c4Srd117015 		 * settaskid().
607*532877c4Srd117015 		 */
608*532877c4Srd117015 		old_pool_name = pool_get_binding(pid);
609*532877c4Srd117015 		if (bind_to_pool(pool_name, pid, 0) != 0) {
6107c478bd9Sstevel@tonic-gate 			if (old_pool_name)
6117c478bd9Sstevel@tonic-gate 				free(old_pool_name);
6127c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
6137c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_POOL);
6147c478bd9Sstevel@tonic-gate 		}
615*532877c4Srd117015 		if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
6167c478bd9Sstevel@tonic-gate 			int saved_errno = errno;
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 			/*
6197c478bd9Sstevel@tonic-gate 			 * Undo pool binding.
6207c478bd9Sstevel@tonic-gate 			 */
6217c478bd9Sstevel@tonic-gate 			(void) bind_to_pool(old_pool_name, pid, 1);
6227c478bd9Sstevel@tonic-gate 			if (old_pool_name)
6237c478bd9Sstevel@tonic-gate 				free(old_pool_name);
6247c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
6257c478bd9Sstevel@tonic-gate 			/*
6267c478bd9Sstevel@tonic-gate 			 * Restore errno
6277c478bd9Sstevel@tonic-gate 			 */
6287c478bd9Sstevel@tonic-gate 			errno = saved_errno;
6297c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6307c478bd9Sstevel@tonic-gate 		}
6317c478bd9Sstevel@tonic-gate 		if (old_pool_name)
6327c478bd9Sstevel@tonic-gate 			free(old_pool_name);
6337c478bd9Sstevel@tonic-gate 	} else {
6347c478bd9Sstevel@tonic-gate 		/*
6357c478bd9Sstevel@tonic-gate 		 * Pools are not configured, so simply create new task.
6367c478bd9Sstevel@tonic-gate 		 */
637*532877c4Srd117015 		if (pr_settaskid(Pr, projid, flags & TASK_MASK) == -1) {
638*532877c4Srd117015 			_kva_free(kv_array);
6397c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
640*532877c4Srd117015 		}
6417c478bd9Sstevel@tonic-gate 	}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	if (project_name == NULL) {
6447c478bd9Sstevel@tonic-gate 		/*
6457c478bd9Sstevel@tonic-gate 		 * In the case that we are starting a new task in the
6467c478bd9Sstevel@tonic-gate 		 * current project, we are finished, since the current
6477c478bd9Sstevel@tonic-gate 		 * resource controls will still apply. (Implicit behaviour:
6487c478bd9Sstevel@tonic-gate 		 * a project must be entirely logged out before name
6497c478bd9Sstevel@tonic-gate 		 * service changes will take effect.)
6507c478bd9Sstevel@tonic-gate 		 */
6517c478bd9Sstevel@tonic-gate 		_kva_free(kv_array);
6527c478bd9Sstevel@tonic-gate 		return (projid);
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	if (kv_array == NULL)
6567c478bd9Sstevel@tonic-gate 		return (0);
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	for (i = 0; i < kv_array->length; i++) {
6597c478bd9Sstevel@tonic-gate 		/*
6607c478bd9Sstevel@tonic-gate 		 * Providing a special, i.e. a non-resource control, key?  Then
6617c478bd9Sstevel@tonic-gate 		 * parse that key here and end with "continue;".
6627c478bd9Sstevel@tonic-gate 		 */
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 		/*
6657c478bd9Sstevel@tonic-gate 		 * For generic bindings, the kernel performs the binding, as
6667c478bd9Sstevel@tonic-gate 		 * these are resource controls advertised by kernel subsystems.
6677c478bd9Sstevel@tonic-gate 		 */
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 		/*
6707c478bd9Sstevel@tonic-gate 		 * Check for known attribute name.
6717c478bd9Sstevel@tonic-gate 		 */
6727c478bd9Sstevel@tonic-gate 		errno = 0;
6737c478bd9Sstevel@tonic-gate 		if (rctl_walk(rctlwalkfunc, (void *)kv_array->data[i].key)
6747c478bd9Sstevel@tonic-gate 		    == 0)
6757c478bd9Sstevel@tonic-gate 			continue;
6767c478bd9Sstevel@tonic-gate 		if (errno) {
6777c478bd9Sstevel@tonic-gate 			_kva_free(kv_array);
6787c478bd9Sstevel@tonic-gate 			return (SETPROJ_ERR_TASK);
6797c478bd9Sstevel@tonic-gate 		}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 		ret = rctl_set(kv_array->data[i].key,
682*532877c4Srd117015 		    kv_array->data[i].value, Pr, flags & TASK_PROJ_MASK);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		if (ret && unknown == 0) {
6857c478bd9Sstevel@tonic-gate 			/*
6867c478bd9Sstevel@tonic-gate 			 * We only report the first failure.
6877c478bd9Sstevel@tonic-gate 			 */
6887c478bd9Sstevel@tonic-gate 			unknown = i + 1;
6897c478bd9Sstevel@tonic-gate 		}
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 		if (ret && ret != SETFAILED) {
6927c478bd9Sstevel@tonic-gate 			/*
6937c478bd9Sstevel@tonic-gate 			 * We abort if we couldn't set a component, but if
6947c478bd9Sstevel@tonic-gate 			 * it's merely that the system didn't recognize it, we
6957c478bd9Sstevel@tonic-gate 			 * continue, as this could be a third party attribute.
6967c478bd9Sstevel@tonic-gate 			 */
6977c478bd9Sstevel@tonic-gate 			break;
6987c478bd9Sstevel@tonic-gate 		}
6997c478bd9Sstevel@tonic-gate 	}
7007c478bd9Sstevel@tonic-gate 	_kva_free(kv_array);
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	return (unknown);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate projid_t
7067c478bd9Sstevel@tonic-gate setproject(const char *project_name, const char *user_name, int flags)
7077c478bd9Sstevel@tonic-gate {
7087c478bd9Sstevel@tonic-gate 	return (setproject_proc(project_name, user_name, flags, P_MYID, NULL,
7097c478bd9Sstevel@tonic-gate 	    NULL));
7107c478bd9Sstevel@tonic-gate }
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate priv_set_t *
7147c478bd9Sstevel@tonic-gate setproject_initpriv(void)
7157c478bd9Sstevel@tonic-gate {
7167c478bd9Sstevel@tonic-gate 	static priv_t taskpriv = PRIV_PROC_TASKID;
7177c478bd9Sstevel@tonic-gate 	static priv_t rctlpriv = PRIV_SYS_RESOURCE;
7187c478bd9Sstevel@tonic-gate 	static priv_t poolpriv = PRIV_SYS_RES_CONFIG;
7197c478bd9Sstevel@tonic-gate 	static priv_t schedpriv = PRIV_PROC_PRIOCNTL;
7207c478bd9Sstevel@tonic-gate 	int res;
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	priv_set_t *nset;
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
7257c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, poolpriv,
7267c478bd9Sstevel@tonic-gate 		    schedpriv, (char *)NULL);
7277c478bd9Sstevel@tonic-gate 	} else {
7287c478bd9Sstevel@tonic-gate 		res = __init_suid_priv(0, taskpriv, rctlpriv, (char *)NULL);
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	if (res != 0)
7327c478bd9Sstevel@tonic-gate 		return (NULL);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	nset = priv_allocset();
7357c478bd9Sstevel@tonic-gate 	if (nset != NULL) {
7367c478bd9Sstevel@tonic-gate 		priv_emptyset(nset);
7377c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, taskpriv);
7387c478bd9Sstevel@tonic-gate 		(void) priv_addset(nset, rctlpriv);
7397c478bd9Sstevel@tonic-gate 		/*
7407c478bd9Sstevel@tonic-gate 		 * Only need these if we need to change pools, which can
7417c478bd9Sstevel@tonic-gate 		 * only happen if the target is in the global zone.  Rather
7427c478bd9Sstevel@tonic-gate 		 * than checking the target's zone just check our own
7437c478bd9Sstevel@tonic-gate 		 * (since if we're in a non-global zone we won't be able
7447c478bd9Sstevel@tonic-gate 		 * to control processes in other zones).
7457c478bd9Sstevel@tonic-gate 		 */
7467c478bd9Sstevel@tonic-gate 		if (getzoneid() == GLOBAL_ZONEID) {
7477c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, poolpriv);
7487c478bd9Sstevel@tonic-gate 			(void) priv_addset(nset, schedpriv);
7497c478bd9Sstevel@tonic-gate 		}
7507c478bd9Sstevel@tonic-gate 	}
7517c478bd9Sstevel@tonic-gate 	return (nset);
7527c478bd9Sstevel@tonic-gate }
753