1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 
27 /*
28  * Module:	zones.c
29  * Group:	libinstzones
30  * Description:	Provide "zones" interface for install consolidation code
31  *
32  * Public Methods:
33  *  z_create_zone_admin_file - Given a location to create the file, and
34  *	optionally an existing administration file, generate an
35  *	administration file that can be used to perform "non-interactive"
36  *	operations in a non-global zone.
37  *  z_free_zone_list - free contents of zoneList_t object
38  *  z_get_nonglobal_zone_list - return zoneList_t object describing all
39  *	non-global native zones
40  *  z_get_nonglobal_zone_list_by_brand - return zoneList_t object describing
41  *      all non-global zones matching the list of zone brands passed in.
42  *  z_free_brand_list - free contents of a zoneBrandList_t object
43  *  z_make_brand_list - return a zoneBrandList_t object describing the list
44  *	of all zone brands passed in.
45  *  z_get_zonename - return the name of the current zone
46  *  z_global_only - Determine if the global zone is only zone on the spec list
47  *  z_lock_this_zone - lock this zone
48  *  z_lock_zones - lock specified zones
49  *  z_mount_in_lz - Mount global zone directory in specified zone's root file
50  *	system
51  *  z_non_global_zones_exist - Determine if any non-global native zones exist
52  *  z_on_zone_spec - Determine if named zone is on the zone_spec list
53  *  z_running_in_global_zone - Determine if running in the "global" zone
54  *  z_set_output_functions - Link program specific output functions
55  *  z_set_zone_root - Set root for zones library operations
56  *  z_set_zone_spec - Set list of zones on which actions will be performed
57  *  z_umount_lz_mount - Unmount directory mounted with z_mount_in_lz
58  *  z_unlock_this_zone - unlock this zone
59  *  z_unlock_zones - unlock specified zones
60  *  z_verify_zone_spec - Verify list of zones on which actions will be performed
61  *  z_zlist_change_zone_state - Change the current state of the specified zone
62  *  z_zlist_get_current_state - Determine the current kernel state of the
63  *	specified zone
64  *  z_zlist_get_original_state - Return the original kernal state of the
65  *	specified zone
66  *  z_zlist_get_scratch - Determine name of scratch zone
67  *  z_zlist_get_zonename - Determine name of specified zone
68  *  z_zlist_get_zonepath - Determine zonepath of specified zone
69  *  z_zlist_restore_zone_state - Return the zone to the state it was originally
70  *	in
71  *  z_zone_exec - Execute a Unix command in a specified zone and return results
72  *  z_zones_are_implemented - Determine if any zone operations can be performed
73  *  z_is_zone_branded - determine if zone has a non-native brand
74  *  z_is_zone_brand_in_list - determine if the zone's brand matches the
75  *      brand list passed in.
76  *  z_brands_are_implemented - determine if branded zones are implemented on
77  *			this system
78  */
79 
80 /*
81  * System includes
82  */
83 
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <unistd.h>
87 #include <fcntl.h>
88 #include <ctype.h>
89 #include <sys/types.h>
90 #include <sys/param.h>
91 #include <sys/sysmacros.h>
92 #include <string.h>
93 #include <strings.h>
94 #include <sys/stat.h>
95 #include <stdarg.h>
96 #include <limits.h>
97 #include <errno.h>
98 #include <time.h>
99 #include <signal.h>
100 #include <stropts.h>
101 #include <wait.h>
102 #include <zone.h>
103 #include <sys/brand.h>
104 #include <libintl.h>
105 #include <locale.h>
106 #include <libzonecfg.h>
107 #include <libcontract.h>
108 #include <sys/contract/process.h>
109 #include <sys/ctfs.h>
110 #include <assert.h>
111 #include <dlfcn.h>
112 #include <link.h>
113 #include <time.h>
114 
115 /*
116  * local includes
117  */
118 
119 /*
120  * When _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA is defined,
121  * instzones_lib.h will define the z_global_data structure.
122  * Otherwise an extern to the structure is inserted.
123  */
124 
125 #define	_INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA
126 #include "instzones_lib.h"
127 #include "zones_strings.h"
128 
129 /*
130  * Private structures
131  */
132 
133 #define	CLUSTER_BRAND_NAME	"cluster"
134 
135 /* maximum number of arguments to exec() call */
136 
137 #define	UUID_FORMAT	"%02d%02d%02d%03d-%02d%02d%02d%d-%016llx"
138 
139 /*
140  * Library Function Prototypes
141  */
142 
143 #define	streq(a, b) (strcmp((a), (b)) == 0)
144 
145 /*
146  * Local Function Prototypes
147  */
148 
149 /*
150  * global internal (private) declarations
151  */
152 
153 /*
154  * *****************************************************************************
155  * global external (public) functions
156  * *****************************************************************************
157  */
158 
159 /*
160  * Name:	z_create_zone_admin_file
161  * Description:	Given a location to create the file, and optionally an existing
162  *		administration file, generate an administration file that
163  *		can be used to perform "non-interactive" operations in a
164  *		non-global zone.
165  * Arguments:	a_zoneAdminFilename - pointer to string representing the
166  *			full path of zone admin file to create
167  *		a_userAdminFilename - pointer to string representing the path
168  *			to an existing "user" administration file - the
169  *			administration file created will contain the
170  *			settings contained in this file, modified as
171  *			appropriate to supress any interaction;
172  *			If this is == NULL then the administration file
173  *			created will not contain any extra settings
174  * Returns:	boolean_t
175  *			== B_TRUE - admin file created
176  *			== B_FALSE - failed to create admin file
177  */
178 
179 boolean_t
z_create_zone_admin_file(char * a_zoneAdminFilename,char * a_userAdminFilename)180 z_create_zone_admin_file(char *a_zoneAdminFilename, char *a_userAdminFilename)
181 {
182 	FILE	*zFp;
183 	FILE	*uFp = (FILE *)NULL;
184 
185 	/* entry assertions */
186 
187 	assert(a_zoneAdminFilename != NULL);
188 	assert(*a_zoneAdminFilename != '\0');
189 
190 	/* create temporary zone admin file */
191 
192 	zFp = fopen(a_zoneAdminFilename, "w");
193 	if (zFp == (FILE *)NULL) {
194 		return (B_FALSE);
195 	}
196 
197 	/* open user admin file if specified */
198 
199 	if (a_userAdminFilename != (char *)NULL) {
200 		uFp = fopen(a_userAdminFilename, "r");
201 	}
202 
203 	/* create default admin file for zone pkg ops if no user admin file */
204 
205 	if (uFp == (FILE *)NULL) {
206 		/* create default admin file */
207 		(void) fprintf(zFp, "action=nocheck\nauthentication=nocheck\n"
208 		    "basedir=default\nconflict=nocheck\nidepend=nocheck\n"
209 		    "instance=unique\npartial=nocheck\nrdepend=nocheck\n"
210 		    "runlevel=nocheck\nsetuid=nocheck\nspace=nocheck\n"
211 		    "mail=\n");
212 	} else for (;;) {
213 		/* copy user admin file substitute/change appropriate entries */
214 		char	buf[LINE_MAX+1];
215 		char	*p;
216 
217 		/* read next line of user admin file */
218 
219 		p = fgets(buf, sizeof (buf), uFp);
220 		if (p == (char *)NULL) {
221 			(void) fclose(uFp);
222 			break;
223 		}
224 
225 		/* modify / replace / accept as appropriate */
226 
227 		if (strncmp(buf, "instance=quit", 13) == 0) {
228 			(void) fprintf(zFp, "%s", "instance=unique\n");
229 			/*LINTED*/
230 		} else if (strncmp(buf, "keystore=", 9) == 0) {
231 		} else if (strncmp(buf, "action=", 7) == 0) {
232 			(void) fprintf(zFp, "action=nocheck\n");
233 		} else if (strncmp(buf, "authentication=", 15) == 0) {
234 			(void) fprintf(zFp, "authentication=nocheck\n");
235 		} else if (strncmp(buf, "conflict=", 9) == 0) {
236 			(void) fprintf(zFp, "conflict=nocheck\n");
237 		} else if (strncmp(buf, "idepend=", 8) == 0) {
238 			(void) fprintf(zFp, "idepend=nocheck\n");
239 		} else if (strncmp(buf, "mail=", 5) == 0) {
240 			(void) fprintf(zFp, "mail=\n");
241 		} else if (strncmp(buf, "partial=", 8) == 0) {
242 			(void) fprintf(zFp, "partial=nocheck\n");
243 		} else if (strncmp(buf, "rdepend=", 8) == 0) {
244 			(void) fprintf(zFp, "rdepend=nocheck\n");
245 		} else if (strncmp(buf, "runlevel=", 9) == 0) {
246 			(void) fprintf(zFp, "runlevel=nocheck\n");
247 		} else if (strncmp(buf, "setuid=", 7) == 0) {
248 			(void) fprintf(zFp, "setuid=nocheck\n");
249 		} else if (strncmp(buf, "space=", 6) == 0) {
250 			(void) fprintf(zFp, "space=nocheck\n");
251 		} else {
252 			(void) fprintf(zFp, "%s", buf);
253 		}
254 	}
255 
256 	/* close admin file and return success */
257 
258 	(void) fclose(zFp);
259 	return (B_TRUE);
260 }
261 
262 /*
263  * Name:	z_brands_are_implemented
264  * Description:	Determine if any branded zones may be present
265  * Arguments:	void
266  * Returns:	boolean_t
267  *			== B_TRUE - branded zones are supported
268  *			== B_FALSE - branded zones are not supported
269  */
270 
271 boolean_t
z_brands_are_implemented(void)272 z_brands_are_implemented(void)
273 {
274 static	boolean_t	_brandsImplementedDetermined = B_FALSE;
275 static	boolean_t	_brandsAreImplemented = B_FALSE;
276 
277 	/* if availability has not been determined, cache it now */
278 
279 	if (!_brandsImplementedDetermined) {
280 		_brandsImplementedDetermined = B_TRUE;
281 		_brandsAreImplemented = _z_brands_are_implemented();
282 		if (_brandsAreImplemented) {
283 			_z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED);
284 		} else {
285 			_z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED);
286 		}
287 	}
288 
289 	/* return cached answer */
290 
291 	return (_brandsAreImplemented);
292 }
293 
294 /*
295  * Name:	z_free_zone_list
296  * Description:	free contents of zoneList_t object
297  * Arguments:	a_zlst - handle to zoneList_t object to free
298  * Returns:	void
299  */
300 
301 void
z_free_zone_list(zoneList_t a_zlst)302 z_free_zone_list(zoneList_t a_zlst)
303 {
304 	int	numzones;
305 
306 	/* ignore empty list */
307 
308 	if (a_zlst == (zoneList_t)NULL) {
309 		return;
310 	}
311 
312 	/* free each entry in the zone list */
313 
314 	for (numzones = 0; a_zlst[numzones]._zlName != (char *)NULL;
315 	    numzones++) {
316 		zoneListElement_t *zelm = &a_zlst[numzones];
317 
318 		/* free zone name string */
319 
320 		free(zelm->_zlName);
321 
322 		/* free zonepath string */
323 
324 		if (zelm->_zlPath != (char *)NULL) {
325 			free(zelm->_zlPath);
326 		}
327 
328 	}
329 
330 	/* free handle to the list */
331 
332 	free(a_zlst);
333 }
334 
335 /*
336  * Name:	z_get_nonglobal_zone_list
337  * Description: return zoneList_t object describing all non-global
338  *              native zones - branded zones are not included in list
339  * Arguments:	None.
340  * Returns:	zoneList_t
341  *			== NULL - error, list could not be generated
342  *			!= NULL - success, list returned
343  * NOTE:    	Any zoneList_t returned is placed in new storage for the
344  *		calling function. The caller must use 'z_free_zone_list' to
345  *		dispose of the storage once the list is no longer needed.
346  */
347 
348 zoneList_t
z_get_nonglobal_zone_list(void)349 z_get_nonglobal_zone_list(void)
350 {
351 	zoneList_t zones;
352 	zoneBrandList_t *brands = NULL;
353 
354 	if ((brands = z_make_brand_list("native cluster", " ")) == NULL)
355 		return (NULL);
356 
357 	zones = z_get_nonglobal_zone_list_by_brand(brands);
358 
359 	z_free_brand_list(brands);
360 
361 	return (zones);
362 }
363 
364 /*
365  * Name:	z_free_brand_list
366  * Description: Free contents of zoneBrandList_t object
367  * Arguments:	brands - pointer to zoneBrandList_t object to free
368  * Returns: 	void
369  */
370 void
z_free_brand_list(zoneBrandList_t * brands)371 z_free_brand_list(zoneBrandList_t *brands)
372 {
373 	while (brands != NULL) {
374 		zoneBrandList_t *temp = brands;
375 		free(brands->string_ptr);
376 		brands = brands->next;
377 		free(temp);
378 	}
379 }
380 
381 /*
382  * Name:	z_make_brand_list
383  * Description:	Given a string with a list of brand name delimited by
384  *		the delimeter passed in, build a zoneBrandList_t structure
385  *		with the list of brand names and return it to the caller.
386  * Arguments:
387  *		brands - const char pointer to string list of brand names
388  *		delim - const char pointer to string representing the
389  *			delimeter for brands string.
390  * Returns:	zoneBrandList_t *
391  *			== NULL - error, list could not be generated
392  *			!= NULL - success, list returned
393  * NOTE:	Any zoneBrandList_t returned is placed in new storage for the
394  *		calling function.  The caller must use 'z_free_brand_list' to
395  *		dispose of the storage once the list is no longer needed.
396  */
397 zoneBrandList_t *
z_make_brand_list(const char * brands,const char * delim)398 z_make_brand_list(const char *brands, const char *delim)
399 {
400 	zoneBrandList_t *brand = NULL, *head = NULL;
401 	char		*blist = NULL;
402 	char		*str = NULL;
403 
404 	if ((blist = strdup(brands)) == NULL)
405 		return (NULL);
406 
407 	if ((str = strtok(blist, delim)) != NULL) {
408 		if ((brand = (zoneBrandList_t *)
409 		    malloc(sizeof (struct _zoneBrandList))) == NULL) {
410 			return (NULL);
411 		}
412 
413 		head = brand;
414 		brand->string_ptr = strdup(str);
415 		brand->next = NULL;
416 
417 		while ((str = strtok(NULL, delim)) != NULL) {
418 			if ((brand->next = (zoneBrandList_t *)
419 			    malloc(sizeof (struct _zoneBrandList))) == NULL) {
420 				return (NULL);
421 			}
422 
423 			brand = brand->next;
424 			brand->string_ptr = strdup(str);
425 			brand->next = NULL;
426 		}
427 	}
428 
429 	free(blist);
430 	return (head);
431 }
432 
433 /*
434  * Name:	z_get_nonglobal_zone_list_by_brand
435  * Description: return zoneList_t object describing all non-global
436  *              zones matching the list of brands passed in.
437  * Arguments:	brands - The list of zone brands to look for.
438  * Returns:	zoneList_t
439  *			== NULL - error, list could not be generated
440  *			!= NULL - success, list returned
441  * NOTE:    	Any zoneList_t returned is placed in new storage for the
442  *		calling function. The caller must use 'z_free_zone_list' to
443  *		dispose of the storage once the list is no longer needed.
444  */
445 zoneList_t
z_get_nonglobal_zone_list_by_brand(zoneBrandList_t * brands)446 z_get_nonglobal_zone_list_by_brand(zoneBrandList_t *brands)
447 {
448 	FILE		*zoneIndexFP;
449 	int		numzones = 0;
450 	struct zoneent	*ze;
451 	zoneList_t	zlst = NULL;
452 	FILE		*mapFP;
453 	char		zonename[ZONENAME_MAX];
454 	zone_spec_t	*zent;
455 
456 	/* if zones are not implemented, return empty list */
457 
458 	if (!z_zones_are_implemented()) {
459 		return ((zoneList_t)NULL);
460 	}
461 
462 	/*
463 	 * Open the zone index file.  Note that getzoneent_private() handles
464 	 * NULL.
465 	 */
466 	zoneIndexFP = setzoneent();
467 
468 	mapFP = zonecfg_open_scratch("", B_FALSE);
469 
470 	/* index file open; scan all zones; see if any are at least installed */
471 
472 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
473 		zone_state_t	st;
474 
475 		/* skip the global zone */
476 
477 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
478 			free(ze);
479 			continue;
480 		}
481 
482 		/*
483 		 * skip any zones with brands not on the brand list
484 		 */
485 		if (!z_is_zone_brand_in_list(ze->zone_name, brands)) {
486 			free(ze);
487 			continue;
488 		}
489 
490 		/*
491 		 * If the user specified an explicit zone list, then ignore any
492 		 * zones that aren't on that list.
493 		 */
494 		if ((zent = _z_global_data._zone_spec) != NULL) {
495 			while (zent != NULL) {
496 				if (strcmp(zent->zl_name, ze->zone_name) == 0)
497 					break;
498 				zent = zent->zl_next;
499 			}
500 			if (zent == NULL) {
501 				free(ze);
502 				continue;
503 			}
504 		}
505 
506 		/* non-global zone: create entry for this zone */
507 
508 		if (numzones == 0) {
509 			zlst = (zoneList_t)_z_calloc(
510 			    sizeof (zoneListElement_t)*2);
511 		} else {
512 			zlst = (zoneList_t)_z_realloc(zlst,
513 			    sizeof (zoneListElement_t)*(numzones+2));
514 			(void) memset(&zlst[numzones], 0L,
515 			    sizeof (zoneListElement_t)*2);
516 		}
517 
518 		/*
519 		 * remember the zone name, zonepath and the current
520 		 * zone state of the zone.
521 		 */
522 		zlst[numzones]._zlName = _z_strdup(ze->zone_name);
523 		zlst[numzones]._zlPath = _z_strdup(ze->zone_path);
524 		zlst[numzones]._zlOrigInstallState = ze->zone_state;
525 		zlst[numzones]._zlCurrInstallState = ze->zone_state;
526 
527 		/* get the zone kernel status */
528 
529 		if (zone_get_state(ze->zone_name, &st) != Z_OK) {
530 			st = ZONE_STATE_INCOMPLETE;
531 		}
532 
533 		_z_echoDebug(DBG_ZONES_NGZ_LIST_STATES,
534 		    ze->zone_name, ze->zone_state, st);
535 
536 		/*
537 		 * For a scratch zone, we need to know the kernel zone name.
538 		 */
539 		if (zonecfg_in_alt_root() && mapFP != NULL &&
540 		    zonecfg_find_scratch(mapFP, ze->zone_name,
541 		    zonecfg_get_root(), zonename, sizeof (zonename)) != -1) {
542 			free(zlst[numzones]._zlScratchName);
543 			zlst[numzones]._zlScratchName = _z_strdup(zonename);
544 		}
545 
546 		/*
547 		 * remember the current kernel status of the zone.
548 		 */
549 
550 		zlst[numzones]._zlOrigKernelStatus = st;
551 		zlst[numzones]._zlCurrKernelStatus = st;
552 
553 		numzones++;
554 		free(ze);
555 	}
556 
557 	/* close the index file */
558 	endzoneent(zoneIndexFP);
559 
560 	if (mapFP != NULL)
561 		zonecfg_close_scratch(mapFP);
562 
563 	/* return generated list */
564 
565 	return (zlst);
566 }
567 
568 /*
569  * Name:	z_get_zonename
570  * Description:	return the name of the current zone
571  * Arguments:	void
572  * Returns:	char *
573  *			- pointer to string representing the name of the current
574  *			zone
575  * NOTE:    	Any string returned is placed in new storage for the
576  *		calling function. The caller must use 'Free' to dispose
577  *		of the storage once the string is no longer needed.
578  */
579 
580 char *
z_get_zonename(void)581 z_get_zonename(void)
582 {
583 	ssize_t		zonenameLen;
584 	char		zonename[ZONENAME_MAX];
585 	zoneid_t	zoneid = (zoneid_t)-1;
586 
587 	/* if zones are not implemented, return "" */
588 
589 	if (!z_zones_are_implemented()) {
590 		return (_z_strdup(""));
591 	}
592 
593 	/* get the zone i.d. of the current zone */
594 
595 	zoneid = getzoneid();
596 
597 	/* get the name of the current zone */
598 
599 	zonenameLen = getzonenamebyid(zoneid, zonename, sizeof (zonename));
600 
601 	/* return "" if could not get zonename */
602 
603 	if (zonenameLen < 1) {
604 		return (_z_strdup(""));
605 	}
606 
607 	return (_z_strdup(zonename));
608 }
609 
610 /*
611  * Name:	z_global_only
612  * Description:	Determine if the global zone is only zone on the spec list.
613  * Arguments:	None
614  * Returns:	B_TRUE if global zone is the only zone on the list,
615  *		B_FALSE otherwise.
616  */
617 
618 boolean_t
z_global_only(void)619 z_global_only(void)
620 {
621 	/* return true if zones are not implemented - treate as global zone */
622 
623 	if (!z_zones_are_implemented()) {
624 		return (B_TRUE);
625 	}
626 
627 	/* return true if this is the global zone */
628 
629 	if (_z_global_data._zone_spec != NULL &&
630 	    _z_global_data._zone_spec->zl_next == NULL &&
631 	    strcmp(_z_global_data._zone_spec->zl_name, GLOBAL_ZONENAME) == 0) {
632 		return (B_TRUE);
633 	}
634 
635 	/* return false - not the global zone */
636 
637 	return (B_FALSE);
638 }
639 
640 /*
641  * Name:	z_lock_this_zone
642  * Description:	lock this zone
643  * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
644  *			Flags indicating which locks to acquire
645  * Returns:	boolean_t
646  *			== B_TRUE - success specified locks acquired
647  *			== B_FALSE - failure specified locks not acquired
648  * NOTE: the lock objects for "this zone" are maintained internally.
649  */
650 
651 boolean_t
z_lock_this_zone(ZLOCKS_T a_lflags)652 z_lock_this_zone(ZLOCKS_T a_lflags)
653 {
654 	boolean_t	b;
655 	char		*zoneName;
656 	pid_t		pid = (pid_t)0;
657 
658 	/* entry assertions */
659 
660 	assert(a_lflags != ZLOCKS_NONE);
661 
662 	/* entry debugging info */
663 
664 	_z_echoDebug(DBG_ZONES_LCK_THIS, a_lflags);
665 
666 	zoneName = z_get_zonename();
667 	pid = getpid();
668 
669 	/* lock zone administration */
670 
671 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
672 		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
673 		    zoneName, LOBJ_ZONEADMIN, pid,
674 		    MSG_ZONES_LCK_THIS_ZONEADM,
675 		    ERR_ZONES_LCK_THIS_ZONEADM);
676 		if (!b) {
677 			(void) free(zoneName);
678 			return (B_FALSE);
679 		}
680 	}
681 
682 	/* lock package administration always */
683 
684 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
685 		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
686 		    zoneName, LOBJ_PKGADMIN, pid,
687 		    MSG_ZONES_LCK_THIS_PKGADM,
688 		    ERR_ZONES_LCK_THIS_PKGADM);
689 		if (!b) {
690 			(void) z_unlock_this_zone(a_lflags);
691 			(void) free(zoneName);
692 			return (B_FALSE);
693 		}
694 	}
695 
696 	(void) free(zoneName);
697 
698 	return (B_TRUE);
699 }
700 
701 /*
702  * Name:	z_lock_zones
703  * Description:	lock specified zones
704  * Arguments:	a_zlst - zoneList_t object describing zones to lock
705  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
706  *			Flags indicating which locks to acquire
707  * Returns:	boolean_t
708  *			== B_TRUE - success, zones locked
709  *			== B_FALSE - failure, zones not locked
710  */
711 
712 boolean_t
z_lock_zones(zoneList_t a_zlst,ZLOCKS_T a_lflags)713 z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
714 {
715 	boolean_t	b;
716 	int		i;
717 
718 	/* entry assertions */
719 
720 	assert(a_lflags != ZLOCKS_NONE);
721 
722 	/* entry debugging info */
723 
724 	_z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags);
725 
726 	/* if zones are not implemented, return TRUE */
727 
728 	if (z_zones_are_implemented() == B_FALSE) {
729 		_z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP);
730 		return (B_TRUE);
731 	}
732 
733 	/* lock this zone first before locking other zones */
734 
735 	b = z_lock_this_zone(a_lflags);
736 	if (b == B_FALSE) {
737 		return (b);
738 	}
739 
740 	/* ignore empty list */
741 
742 	if (a_zlst == (zoneList_t)NULL) {
743 		_z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES);
744 		return (B_FALSE);
745 	}
746 
747 	/* zones exist */
748 
749 	_z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST);
750 
751 	/*
752 	 * lock each listed zone that is currently running
753 	 */
754 
755 	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
756 		/* ignore zone if already locked */
757 		if (a_zlst[i]._zlStatus & ZST_LOCKED) {
758 			continue;
759 		}
760 
761 		/* ignore zone if not running */
762 		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
763 		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
764 			continue;
765 		}
766 
767 		/*
768 		 * mark zone locked - if interrupted out during lock, an attempt
769 		 * will be made to release the lock
770 		 */
771 		a_zlst[i]._zlStatus |= ZST_LOCKED;
772 
773 		/* lock this zone */
774 		b = _z_lock_zone(&a_zlst[i], a_lflags);
775 
776 		/* on failure unlock all zones and return error */
777 		if (b != B_TRUE) {
778 			_z_program_error(ERR_ZONES_LCK_ZONES_FAILED,
779 			    a_zlst[i]._zlName);
780 			(void) z_unlock_zones(a_zlst, a_lflags);
781 			return (B_FALSE);
782 		}
783 	}
784 
785 	/* success */
786 
787 	return (B_TRUE);
788 }
789 
790 /*
791  * Name:	z_mount_in_lz
792  * Description:	Mount global zone directory in specified zone's root file system
793  * Arguments:	r_lzMountPoint - pointer to handle to string - on success, the
794  *			full path to the mount point relative to the global zone
795  *			root file system is returned here - this is needed to
796  *			unmount the directory when it is no longer needed
797  *		r_lzRootPath - pointer to handle to string - on success, the
798  *			full path to the mount point relative to the specified
799  *			zone's root file system is returned here - this is
800  *			passed to any command executing in the specified zone to
801  *			access the directory mounted
802  *		a_zoneName - pointer to string representing the name of the zone
803  *			to mount the specified global zone directory in
804  *		a_gzPath - pointer to string representing the full absolute path
805  *			of the global zone directory to LOFS mount inside of the
806  *			specified non-global zone
807  *		a_mountPointPrefix - pointer to string representing the prefix
808  *			to be used when creating the mount point name in the
809  *			specified zone's root directory
810  * Returns:	boolean_t
811  *			== B_TRUE - global zone directory mounted successfully
812  *			== B_FALSE - failed to mount directory in specified zone
813  * NOTE:    	Any strings returned is placed in new storage for the
814  *		calling function. The caller must use 'Free' to dispose
815  *		of the storage once the strings are no longer needed.
816  */
817 
818 boolean_t
z_mount_in_lz(char ** r_lzMountPoint,char ** r_lzRootPath,char * a_zoneName,char * a_gzPath,char * a_mountPointPrefix)819 z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName,
820 	char *a_gzPath, char *a_mountPointPrefix)
821 {
822 	char		lzRootPath[MAXPATHLEN] = {'\0'};
823 	char		uuid[MAXPATHLEN] = {'\0'};
824 	char		gzMountPoint[MAXPATHLEN] = {'\0'};
825 	char		lzMountPoint[MAXPATHLEN] = {'\0'};
826 	hrtime_t	hretime;
827 	int		err;
828 	int		slen;
829 	struct tm	tstruct;
830 	time_t		thetime;
831 	zoneid_t	zid;
832 
833 	/* entry assertions */
834 
835 	assert(a_zoneName != (char *)NULL);
836 	assert(*a_zoneName != '\0');
837 	assert(a_gzPath != (char *)NULL);
838 	assert(*a_gzPath != '\0');
839 	assert(r_lzMountPoint != (char **)NULL);
840 	assert(r_lzRootPath != (char **)NULL);
841 
842 	/* entry debugging info */
843 
844 	_z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath);
845 
846 	/* reset returned non-global zone mount point path handle */
847 
848 	*r_lzMountPoint = (char *)NULL;
849 	*r_lzRootPath = (char *)NULL;
850 
851 	/* if zones are not implemented, return FALSE */
852 
853 	if (z_zones_are_implemented() == B_FALSE) {
854 		return (B_FALSE);
855 	}
856 
857 	/* error if global zone path is not absolute */
858 
859 	if (*a_gzPath != '/') {
860 		_z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath);
861 		return (B_FALSE);
862 	}
863 
864 	/* error if global zone path does not exist */
865 
866 	if (_z_is_directory(a_gzPath) != 0) {
867 		_z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno));
868 		return (B_FALSE);
869 	}
870 
871 	/* verify that specified non-global zone exists */
872 
873 	err = zone_get_id(a_zoneName, &zid);
874 	if (err != Z_OK) {
875 		_z_program_error(ERR_GET_ZONEID, a_zoneName,
876 		    zonecfg_strerror(err));
877 		return (B_FALSE);
878 	}
879 
880 	/* obtain global zone path to non-global zones root file system */
881 
882 	err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath));
883 	if (err != Z_OK) {
884 		_z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName,
885 		    zonecfg_strerror(err));
886 		return (B_FALSE);
887 	}
888 
889 	if (lzRootPath[0] == '\0') {
890 		_z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName);
891 		return (B_FALSE);
892 	}
893 
894 	/*
895 	 * lofs resolve the non-global zone's root path first in case
896 	 * its in a path that's been lofs mounted read-only.
897 	 */
898 	z_resolve_lofs(lzRootPath, sizeof (lzRootPath));
899 
900 	/* verify that the root path exists */
901 
902 	if (_z_is_directory(lzRootPath) != 0) {
903 		_z_program_error(ERR_LZROOT_NOTDIR, lzRootPath,
904 		    strerror(errno));
905 		return (B_FALSE);
906 	}
907 
908 	/*
909 	 * generate a unique key - the key is the same length as unique uid
910 	 * but contains different information that is as unique as can be made;
911 	 * include current hires time (nanosecond real timer). Such a unique
912 	 * i.d. will look like:
913 	 *		0203104092-1145345-0004e94d6af481a0
914 	 */
915 
916 	hretime = gethrtime();
917 
918 	thetime = time((time_t *)NULL);
919 	(void) localtime_r(&thetime, &tstruct);
920 
921 	slen = snprintf(uuid, sizeof (uuid),
922 	    UUID_FORMAT,
923 	    tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year,
924 	    tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min,
925 	    tstruct.tm_sec,	tstruct.tm_wday, hretime);
926 	if (slen > sizeof (uuid)) {
927 		_z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED,
928 		    UUID_FORMAT, sizeof (uuid));
929 		return (B_FALSE);
930 	}
931 
932 	/* create the global zone mount point */
933 
934 	slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s",
935 	    lzRootPath,
936 	    a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid);
937 	if (slen > sizeof (gzMountPoint)) {
938 		_z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED,
939 		    "%s/.SUNW_%s_%s", lzRootPath,
940 		    a_mountPointPrefix ? a_mountPointPrefix : "zones",
941 		    uuid, sizeof (gzMountPoint));
942 		return (B_FALSE);
943 	}
944 
945 	slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s",
946 	    gzMountPoint+strlen(lzRootPath));
947 	if (slen > sizeof (lzMountPoint)) {
948 		_z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED,
949 		    "%s", gzMountPoint+strlen(lzRootPath),
950 		    sizeof (lzMountPoint));
951 		return (B_FALSE);
952 	}
953 
954 	_z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint,
955 	    lzMountPoint);
956 
957 	/* error if the mount point already exists */
958 
959 	if (_z_is_directory(gzMountPoint) == 0) {
960 		_z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint,
961 		    a_zoneName, strerror(errno));
962 		return (B_FALSE);
963 	}
964 
965 	/* create the temporary mount point */
966 
967 	if (mkdir(gzMountPoint, 0600) != 0) {
968 		_z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName,
969 		    strerror(errno));
970 		return (B_FALSE);
971 	}
972 
973 	/* mount the global zone path on the non-global zone root file system */
974 
975 	err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs",
976 	    (char *)NULL, 0, (char *)NULL, 0);
977 	if (err != 0) {
978 		_z_program_error(ERR_GZMOUNT_FAILED, a_gzPath,
979 		    gzMountPoint, a_zoneName, strerror(errno));
980 		return (B_FALSE);
981 	}
982 
983 	/* success - return both mountpoints to caller */
984 
985 	*r_lzMountPoint = _z_strdup(gzMountPoint);
986 
987 	*r_lzRootPath = _z_strdup(lzMountPoint);
988 
989 	/* return success */
990 
991 	return (B_TRUE);
992 }
993 
994 /*
995  * Name:	z_non_global_zones_exist
996  * Description:	Determine if any non-global native zones exist
997  * Arguments:	None.
998  * Returns:	boolean_t
999  *	== B_TRUE - at least one non-global native zone exists
1000  *	== B_FALSE - no non-global native zone exists
1001  */
1002 
1003 boolean_t
z_non_global_zones_exist(void)1004 z_non_global_zones_exist(void)
1005 {
1006 	FILE		*zoneIndexFP;
1007 	boolean_t	anyExist = B_FALSE;
1008 	struct zoneent	*ze;
1009 	zone_spec_t	*zent;
1010 
1011 	/* if zones are not implemented, return FALSE */
1012 
1013 	if (z_zones_are_implemented() == B_FALSE) {
1014 		return (B_FALSE);
1015 	}
1016 
1017 	/* determine if any zones are configured */
1018 	zoneIndexFP = setzoneent();
1019 	if (zoneIndexFP == NULL) {
1020 		return (B_FALSE);
1021 	}
1022 
1023 	/* index file open; scan all zones; see if any are at least installed */
1024 
1025 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1026 		/*
1027 		 * If the user specified an explicit zone list, then ignore any
1028 		 * zones that aren't on that list.
1029 		 */
1030 		if ((zent = _z_global_data._zone_spec) != NULL) {
1031 			while (zent != NULL) {
1032 				if (strcmp(zent->zl_name, ze->zone_name) == 0)
1033 					break;
1034 				zent = zent->zl_next;
1035 			}
1036 			if (zent == NULL) {
1037 				free(ze);
1038 				continue;
1039 			}
1040 		}
1041 
1042 		/* skip the global zone */
1043 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
1044 			free(ze);
1045 			continue;
1046 		}
1047 
1048 		/* skip any branded zones */
1049 		if (z_is_zone_branded(ze->zone_name)) {
1050 			free(ze);
1051 			continue;
1052 		}
1053 
1054 		/* is this zone installed? */
1055 		if (ze->zone_state >= ZONE_STATE_INSTALLED) {
1056 			free(ze);
1057 			anyExist = B_TRUE;
1058 			break;
1059 		}
1060 		free(ze);
1061 	}
1062 
1063 	/* close the index file */
1064 
1065 	endzoneent(zoneIndexFP);
1066 
1067 	/* return results */
1068 
1069 	return (anyExist);
1070 }
1071 
1072 /*
1073  * Name:	z_on_zone_spec
1074  * Description:	Determine if named zone is on the zone_spec list.
1075  * Arguments:	Pointer to name to test.
1076  * Returns:	B_TRUE if named zone is on the list or if the user specified
1077  *		no list at all (all zones is the default), B_FALSE otherwise.
1078  */
1079 
1080 boolean_t
z_on_zone_spec(const char * zonename)1081 z_on_zone_spec(const char *zonename)
1082 {
1083 	zone_spec_t	*zent;
1084 
1085 	/* entry assertions */
1086 
1087 	assert(zonename != NULL);
1088 	assert(*zonename != '\0');
1089 
1090 	/* return true if zones not implemented or no zone spec list defined */
1091 
1092 	if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) {
1093 		return (B_TRUE);
1094 	}
1095 
1096 	/* return true if named zone is on the zone spec list */
1097 
1098 	for (zent = _z_global_data._zone_spec;
1099 	    zent != NULL; zent = zent->zl_next) {
1100 		if (strcmp(zent->zl_name, zonename) == 0)
1101 			return (B_TRUE);
1102 	}
1103 
1104 	/* named zone is not on the zone spec list */
1105 
1106 	return (B_FALSE);
1107 }
1108 
1109 /*
1110  * Name:	z_running_in_global_zone
1111  * Description:	Determine if running in the "global" zone
1112  * Arguments:	void
1113  * Returns:	boolean_t
1114  *			== B_TRUE - running in global zone
1115  *			== B_FALSE - not running in global zone
1116  */
1117 
1118 boolean_t
z_running_in_global_zone(void)1119 z_running_in_global_zone(void)
1120 {
1121 	static	boolean_t	_zoneIdDetermined = B_FALSE;
1122 	static	boolean_t	_zoneIsGlobal = B_FALSE;
1123 
1124 	/* if ID has not been determined, cache it now */
1125 
1126 	if (!_zoneIdDetermined) {
1127 		_zoneIdDetermined = B_TRUE;
1128 		_zoneIsGlobal = _z_running_in_global_zone();
1129 	}
1130 
1131 	return (_zoneIsGlobal);
1132 }
1133 
1134 /*
1135  * Name:	z_set_output_functions
1136  * Description:	Link program specific output functions to this library.
1137  * Arguments:	a_echo_fcn - (_z_printf_fcn_t)
1138  *			Function to call to cause "normal operation" messages
1139  *			to be output/displayed
1140  *		a_echo_debug_fcn - (_z_printf_fcn_t)
1141  *			Function to call to cause "debugging" messages
1142  *			to be output/displayed
1143  *		a_progerr_fcn - (_z_printf_fcn_t)
1144  *			Function to call to cause "program error" messages
1145  *			to be output/displayed
1146  * Returns:	void
1147  * NOTE:	If NULL is specified for any function, then the functionality
1148  *		associated with that function is disabled.
1149  * NOTE:	The function pointers provided must call a function that
1150  *		takes two arguments:
1151  *			function(char *format, char *message)
1152  *		Any registered function will be called like:
1153  *			function("%s", "message")
1154  */
1155 
1156 void
z_set_output_functions(_z_printf_fcn_t a_echo_fcn,_z_printf_fcn_t a_echo_debug_fcn,_z_printf_fcn_t a_progerr_fcn)1157 z_set_output_functions(_z_printf_fcn_t a_echo_fcn,
1158     _z_printf_fcn_t a_echo_debug_fcn,
1159     _z_printf_fcn_t a_progerr_fcn)
1160 {
1161 	_z_global_data._z_echo = a_echo_fcn;
1162 	_z_global_data._z_echo_debug = a_echo_debug_fcn;
1163 	_z_global_data._z_progerr = a_progerr_fcn;
1164 }
1165 
1166 /*
1167  * Name:	z_set_zone_root
1168  * Description:	Set root for zones library operations
1169  * Arguments:	Path to root of boot environment containing zone; must be
1170  *		absolute.
1171  * Returns:	None.
1172  * NOTE:	Must be called before performing any zone-related operations.
1173  *		(Currently called directly by set_inst_root() during -R
1174  *		argument handling.)
1175  */
1176 
1177 void
z_set_zone_root(const char * zroot)1178 z_set_zone_root(const char *zroot)
1179 {
1180 	char *rootdir;
1181 
1182 	/* if zones are not implemented, just return */
1183 
1184 	if (!z_zones_are_implemented())
1185 		return;
1186 
1187 	/* entry assertions */
1188 
1189 	assert(zroot != NULL);
1190 
1191 	rootdir = _z_strdup((char *)zroot);
1192 	z_canoninplace(rootdir);
1193 
1194 	if (strcmp(rootdir, "/") == 0) {
1195 		rootdir[0] = '\0';
1196 	}
1197 
1198 	/* free any existing cached root path */
1199 	if (*_z_global_data._z_root_dir != '\0') {
1200 		free(_z_global_data._z_root_dir);
1201 		_z_global_data._z_root_dir = NULL;
1202 	}
1203 
1204 	/* store duplicate of new zone root path */
1205 
1206 	if (*rootdir != '\0') {
1207 		_z_global_data._z_root_dir = _z_strdup(rootdir);
1208 	} else {
1209 		_z_global_data._z_root_dir = "";
1210 	}
1211 
1212 	/* set zone root path */
1213 
1214 	zonecfg_set_root(rootdir);
1215 
1216 	free(rootdir);
1217 }
1218 
1219 /*
1220  * Name:	z_set_zone_spec
1221  * Description:	Set list of zones on which actions will be performed.
1222  * Arguments:	Whitespace-separated list of zone names.
1223  * Returns:	0 on success, -1 on error.
1224  * NOTES:	Will call _z_program_error if argument can't be parsed or
1225  *		memory not available.
1226  */
1227 
1228 int
z_set_zone_spec(const char * zlist)1229 z_set_zone_spec(const char *zlist)
1230 {
1231 	const char	*zend;
1232 	ptrdiff_t	zlen;
1233 	zone_spec_t	*zent;
1234 	zone_spec_t	*zhead;
1235 	zone_spec_t	**znextp = &zhead;
1236 
1237 	/* entry assertions */
1238 
1239 	assert(zlist != NULL);
1240 
1241 	/* parse list to zone_spec_t list, store in global data */
1242 
1243 	for (;;) {
1244 		while (isspace(*zlist)) {
1245 			zlist++;
1246 		}
1247 		if (*zlist == '\0') {
1248 			break;
1249 		}
1250 		for (zend = zlist; *zend != '\0'; zend++) {
1251 			if (isspace(*zend)) {
1252 				break;
1253 			}
1254 		}
1255 		zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist);
1256 		if (zlen >= ZONENAME_MAX) {
1257 			_z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist);
1258 			return (-1);
1259 		}
1260 		zent = _z_malloc(sizeof (*zent));
1261 		(void) memcpy(zent->zl_name, zlist, zlen);
1262 		zent->zl_name[zlen] = '\0';
1263 		zent->zl_used = B_FALSE;
1264 		*znextp = zent;
1265 		znextp = &zent->zl_next;
1266 		zlist = zend;
1267 	}
1268 	*znextp = NULL;
1269 
1270 	if (zhead == NULL) {
1271 		_z_program_error(ERR_ZONE_LIST_EMPTY);
1272 		return (-1);
1273 	}
1274 
1275 	_z_global_data._zone_spec = zhead;
1276 	return (0);
1277 }
1278 
1279 /*
1280  * Name:	z_umount_lz_mount
1281  * Description:	Unmount directory mounted with z_mount_in_lz
1282  * Arguments:	a_lzMountPointer - pointer to string returned by z_mount_in_lz
1283  * Returns:	boolean_t
1284  *			== B_TRUE - successfully unmounted directory
1285  *			== B_FALSE - failed to unmount directory
1286  */
1287 
1288 boolean_t
z_umount_lz_mount(char * a_lzMountPoint)1289 z_umount_lz_mount(char *a_lzMountPoint)
1290 {
1291 	int	err;
1292 
1293 	/* entry assertions */
1294 
1295 	assert(a_lzMountPoint != (char *)NULL);
1296 	assert(*a_lzMountPoint != '\0');
1297 
1298 	/* entry debugging info */
1299 
1300 	_z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint);
1301 
1302 	/* if zones are not implemented, return TRUE */
1303 
1304 	if (z_zones_are_implemented() == B_FALSE) {
1305 		return (B_FALSE);
1306 	}
1307 
1308 	/* error if global zone path is not absolute */
1309 
1310 	if (*a_lzMountPoint != '/') {
1311 		_z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint);
1312 		return (B_FALSE);
1313 	}
1314 
1315 	/* verify mount point exists */
1316 
1317 	if (_z_is_directory(a_lzMountPoint) != 0) {
1318 		_z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint,
1319 		    strerror(errno));
1320 		return (B_FALSE);
1321 	}
1322 
1323 	/* unmount */
1324 
1325 	err = umount2(a_lzMountPoint, 0);
1326 	if (err != 0) {
1327 		_z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint,
1328 		    strerror(errno));
1329 		return (B_FALSE);
1330 	}
1331 
1332 	/* remove the mount point */
1333 
1334 	(void) remove(a_lzMountPoint);
1335 
1336 	/* return success */
1337 
1338 	return (B_TRUE);
1339 }
1340 
1341 /*
1342  * Name:	z_unlock_this_zone
1343  * Description:	unlock this zone
1344  * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
1345  *			Flags indicating which locks to release
1346  * Returns:	boolean_t
1347  *			== B_TRUE - success specified locks released
1348  *			== B_FALSE - failure specified locks may not be released
1349  * NOTE: the lock objects for "this zone" are maintained internally.
1350  */
1351 
1352 boolean_t
z_unlock_this_zone(ZLOCKS_T a_lflags)1353 z_unlock_this_zone(ZLOCKS_T a_lflags)
1354 {
1355 	boolean_t	b;
1356 	boolean_t	errors = B_FALSE;
1357 	char		*zoneName;
1358 
1359 	/* entry assertions */
1360 
1361 	assert(a_lflags != ZLOCKS_NONE);
1362 
1363 	/* entry debugging info */
1364 
1365 	_z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags);
1366 
1367 	/* return if no objects locked */
1368 
1369 	if ((_z_global_data._z_ObjectLocks == (char *)NULL) ||
1370 	    (*_z_global_data._z_ObjectLocks == '\0')) {
1371 		return (B_TRUE);
1372 	}
1373 
1374 	zoneName = z_get_zonename();
1375 
1376 	/* unlock package administration */
1377 
1378 	if (a_lflags & ZLOCKS_PKG_ADMIN) {
1379 		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1380 		    zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE);
1381 		if (!b) {
1382 			errors = B_TRUE;
1383 		}
1384 	}
1385 
1386 	/* unlock zone administration */
1387 
1388 	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
1389 		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1390 		    zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES);
1391 		if (!b) {
1392 			errors = B_TRUE;
1393 		}
1394 	}
1395 
1396 	(void) free(zoneName);
1397 	return (!errors);
1398 }
1399 
1400 /*
1401  * Name:	z_unlock_zones
1402  * Description:	unlock specified zones
1403  * Arguments:	a_zlst - zoneList_t object describing zones to unlock
1404  *		a_lflags - [RO, *RO] - (ZLOCKS_T)
1405  *			Flags indicating which locks to release
1406  * Returns:	boolean_t
1407  *			== B_TRUE - success, zones unlocked
1408  *			== B_FALSE - failure, zones not unlocked
1409  */
1410 
1411 boolean_t
z_unlock_zones(zoneList_t a_zlst,ZLOCKS_T a_lflags)1412 z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
1413 {
1414 	boolean_t	b;
1415 	boolean_t	errors = B_FALSE;
1416 	int		i;
1417 
1418 	/* entry assertions */
1419 
1420 	assert(a_lflags != ZLOCKS_NONE);
1421 
1422 	/* entry debugging info */
1423 
1424 	_z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags);
1425 
1426 	/* if zones are not implemented, return TRUE */
1427 
1428 	if (z_zones_are_implemented() == B_FALSE) {
1429 		_z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP);
1430 		return (B_TRUE);
1431 	}
1432 
1433 	/* ignore empty list */
1434 
1435 	if (a_zlst == (zoneList_t)NULL) {
1436 		_z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES);
1437 		/* unlock this zone before returning */
1438 		return (z_unlock_this_zone(a_lflags));
1439 	}
1440 
1441 	/* zones exist */
1442 
1443 	_z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST);
1444 
1445 	/*
1446 	 * unlock each listed zone that is currently running
1447 	 */
1448 
1449 	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
1450 		/* ignore zone if not locked */
1451 		if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) {
1452 			continue;
1453 		}
1454 
1455 		/* ignore zone if not running */
1456 		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
1457 		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
1458 			continue;
1459 		}
1460 
1461 		/* unlock this zone */
1462 		b = _z_unlock_zone(&a_zlst[i], a_lflags);
1463 
1464 		if (b != B_TRUE) {
1465 			errors = B_TRUE;
1466 		} else {
1467 			/* mark zone as unlocked */
1468 			a_zlst[i]._zlStatus &= ~ZST_LOCKED;
1469 		}
1470 	}
1471 
1472 	/* unlock this zone */
1473 
1474 	if (z_unlock_this_zone(a_lflags) != B_TRUE) {
1475 		errors = B_TRUE;
1476 	}
1477 
1478 	return (errors);
1479 }
1480 
1481 /*
1482  * Name:	z_verify_zone_spec
1483  * Description:	Verify list of zones on which actions will be performed.
1484  * Arguments:	None.
1485  * Returns:	0 on success, -1 on error.
1486  * NOTES:	Will call _z_program_error if there are zones on the specified
1487  *		list that don't exist on the system. Requires that
1488  *		z_set_zone_root is called first (if it is called at all).
1489  */
1490 
1491 int
z_verify_zone_spec(void)1492 z_verify_zone_spec(void)
1493 {
1494 	FILE		*zoneIndexFP;
1495 	boolean_t	errors;
1496 	char		zoneIndexPath[MAXPATHLEN];
1497 	struct zoneent	*ze;
1498 	zone_spec_t	*zent;
1499 
1500 	if (!z_zones_are_implemented()) {
1501 		_z_program_error(ERR_ZONES_NOT_IMPLEMENTED);
1502 		return (-1);
1503 	}
1504 
1505 	zoneIndexFP = setzoneent();
1506 	if (zoneIndexFP == NULL) {
1507 		_z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath,
1508 		    strerror(errno));
1509 		return (-1);
1510 	}
1511 
1512 	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1513 		for (zent = _z_global_data._zone_spec;
1514 		    zent != NULL; zent = zent->zl_next) {
1515 			if (strcmp(zent->zl_name, ze->zone_name) == 0) {
1516 				zent->zl_used = B_TRUE;
1517 				break;
1518 			}
1519 		}
1520 		free(ze);
1521 	}
1522 	endzoneent(zoneIndexFP);
1523 
1524 	errors = B_FALSE;
1525 	for (zent = _z_global_data._zone_spec;
1526 	    zent != NULL; zent = zent->zl_next) {
1527 		if (!zent->zl_used) {
1528 			_z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name);
1529 			errors = B_TRUE;
1530 		}
1531 	}
1532 	return (errors ? -1 : 0);
1533 }
1534 
1535 /*
1536  * Name:	z_zlist_change_zone_state
1537  * Description:	Change the current state of the specified zone
1538  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1539  *		a_zoneIndex - index into a_zlst of the zone to return the
1540  *		a_newState - the state to put the specified zone in
1541  * Returns:	boolean_t
1542  *			== B_TRUE - the zone is in the new state
1543  *			== B_FALSE - unable to transition the zone to the
1544  *				specified state
1545  * NOTE:	This changes the "current kernel" state of the specified
1546  *		zone. For example, to boot the zone, change the state
1547  *		to "ZONE_STATE_RUNNING". To halt the zone, change the
1548  *		state to "ZONE_STATE_INSTALLED".
1549  */
1550 
1551 boolean_t
z_zlist_change_zone_state(zoneList_t a_zlst,int a_zoneIndex,zone_state_t a_newState)1552 z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex,
1553 	zone_state_t a_newState)
1554 {
1555 	int	i;
1556 
1557 	/* entry debugging info */
1558 
1559 	_z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState);
1560 
1561 	/* ignore empty list */
1562 
1563 	if (a_zlst == (zoneList_t)NULL) {
1564 		return (B_FALSE);
1565 	}
1566 
1567 	/* find the specified zone in the list */
1568 
1569 	for (i = 0; (i != a_zoneIndex) &&
1570 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1571 		;
1572 
1573 	/* return error if the specified zone does not exist */
1574 
1575 	if (a_zlst[i]._zlName == (char *)NULL) {
1576 		return (B_FALSE);
1577 	}
1578 
1579 	/* return success if the zone is already in this state */
1580 
1581 	if (a_zlst[i]._zlCurrKernelStatus == a_newState) {
1582 		return (B_TRUE);
1583 	}
1584 
1585 	/* take action on new state to set zone to */
1586 
1587 	_z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName,
1588 	    a_zlst[i]._zlCurrKernelStatus, a_newState);
1589 
1590 	switch (a_newState) {
1591 	case ZONE_STATE_RUNNING:
1592 	case ZONE_STATE_MOUNTED:
1593 		/* these states mean "boot the zone" */
1594 		return (_z_make_zone_running(&a_zlst[i]));
1595 
1596 	case ZONE_STATE_DOWN:
1597 	case ZONE_STATE_INSTALLED:
1598 		/* these states mean "halt the zone" */
1599 		return (_z_make_zone_down(&a_zlst[i]));
1600 
1601 	case ZONE_STATE_READY:
1602 		return (_z_make_zone_ready(&a_zlst[i]));
1603 
1604 	case ZONE_STATE_CONFIGURED:
1605 	case ZONE_STATE_INCOMPLETE:
1606 	case ZONE_STATE_SHUTTING_DOWN:
1607 	default:
1608 		/* do not know how to change zone to this state */
1609 		return (B_FALSE);
1610 	}
1611 }
1612 
1613 /*
1614  * Name:	z_is_zone_branded
1615  * Description:	Determine whether zone has a non-native brand
1616  * Arguments:	a_zoneName - name of the zone to check for branding
1617  * Returns:	boolean_t
1618  *			== B_TRUE - zone has a non-native brand
1619  *			== B_FALSE - zone is native
1620  */
1621 boolean_t
z_is_zone_branded(char * zoneName)1622 z_is_zone_branded(char *zoneName)
1623 {
1624 	char			brandname[MAXNAMELEN];
1625 	int			err;
1626 
1627 	/* if zones are not implemented, return FALSE */
1628 	if (!z_zones_are_implemented()) {
1629 		return (B_FALSE);
1630 	}
1631 
1632 	/* if brands are not implemented, return FALSE */
1633 	if (!z_brands_are_implemented()) {
1634 		return (B_FALSE);
1635 	}
1636 
1637 	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1638 	if (err != Z_OK) {
1639 		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1640 		return (B_FALSE);
1641 	}
1642 
1643 	/*
1644 	 * Both "native" and "cluster" are native brands
1645 	 * that use the standard facilities in the areas
1646 	 * of packaging/installation/update.
1647 	 */
1648 	if (streq(brandname, NATIVE_BRAND_NAME) ||
1649 	    streq(brandname, CLUSTER_BRAND_NAME)) {
1650 		return (B_FALSE);
1651 	} else {
1652 		return (B_TRUE);
1653 	}
1654 }
1655 
1656 /*
1657  * Name:	z_is_zone_brand_in_list
1658  * Description:	Determine whether zone's brand has a match in the list
1659  *              brands passed in.
1660  * Arguments:	zoneName - name of the zone to check for branding
1661  *              list - list of brands to check the zone against
1662  * Returns:	boolean_t
1663  *			== B_TRUE - zone has a matching brand
1664  *			== B_FALSE - zone brand is not in list
1665  */
1666 boolean_t
z_is_zone_brand_in_list(char * zoneName,zoneBrandList_t * list)1667 z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list)
1668 {
1669 	char			brandname[MAXNAMELEN];
1670 	int			err;
1671 	zoneBrandList_t		*sp;
1672 
1673 	if (zoneName == NULL || list == NULL)
1674 		return (B_FALSE);
1675 
1676 	/* if zones are not implemented, return FALSE */
1677 	if (!z_zones_are_implemented()) {
1678 		return (B_FALSE);
1679 	}
1680 
1681 	/* if brands are not implemented, return FALSE */
1682 	if (!z_brands_are_implemented()) {
1683 		return (B_FALSE);
1684 	}
1685 
1686 	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1687 	if (err != Z_OK) {
1688 		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1689 		return (B_FALSE);
1690 	}
1691 
1692 	for (sp = list; sp != NULL; sp = sp->next) {
1693 		if (sp->string_ptr != NULL &&
1694 		    strcmp(sp->string_ptr, brandname) == 0) {
1695 			return (B_TRUE);
1696 		}
1697 	}
1698 
1699 	return (B_FALSE);
1700 }
1701 
1702 /*
1703  * Name:	z_zlist_get_current_state
1704  * Description:	Determine the current kernel state of the specified zone
1705  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1706  *		a_zoneIndex - index into a_zlst of the zone to return
1707  * Returns:	zone_state_t
1708  *			The current state of the specified zone is returned
1709  */
1710 
1711 zone_state_t
z_zlist_get_current_state(zoneList_t a_zlst,int a_zoneIndex)1712 z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex)
1713 {
1714 	int	i;
1715 
1716 	/* ignore empty list */
1717 
1718 	if (a_zlst == (zoneList_t)NULL) {
1719 		return (ZONE_STATE_INCOMPLETE);
1720 	}
1721 
1722 	/* find the specified zone in the list */
1723 
1724 	for (i = 0; (i != a_zoneIndex) &&
1725 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1726 		;
1727 
1728 	/* return error if the specified zone does not exist */
1729 
1730 	if (a_zlst[i]._zlName == (char *)NULL) {
1731 		return (ZONE_STATE_INCOMPLETE);
1732 	}
1733 
1734 	/* return selected zone's current kernel state */
1735 
1736 	_z_echoDebug(DBG_ZONES_GET_ZONE_STATE,
1737 	    a_zlst[i]._zlName ? a_zlst[i]._zlName : "",
1738 	    a_zlst[i]._zlCurrKernelStatus);
1739 
1740 	return (a_zlst[i]._zlCurrKernelStatus);
1741 }
1742 
1743 /*
1744  * Name:	z_zlist_get_original_state
1745  * Description:	Return the original kernal state of the specified zone
1746  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1747  *		a_zoneIndex - index into a_zlst of the zone to return the
1748  * Returns:	zone_state_t
1749  *			The original state of the specified zone is returned.
1750  *			This is the state of the zone when the zoneList_t
1751  *			object was first generated.
1752  */
1753 
1754 zone_state_t
z_zlist_get_original_state(zoneList_t a_zlst,int a_zoneIndex)1755 z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex)
1756 {
1757 	int	i;
1758 
1759 	/* ignore empty list */
1760 
1761 	if (a_zlst == (zoneList_t)NULL) {
1762 		return (ZONE_STATE_INCOMPLETE);
1763 	}
1764 
1765 	/* find the specified zone in the list */
1766 
1767 	for (i = 0; (i != a_zoneIndex) &&
1768 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1769 		;
1770 
1771 	/* return error if the specified zone does not exist */
1772 
1773 	if (a_zlst[i]._zlName == (char *)NULL) {
1774 		return (ZONE_STATE_INCOMPLETE);
1775 	}
1776 
1777 	/* return selected zone's original kernel state */
1778 
1779 	return (a_zlst[i]._zlOrigKernelStatus);
1780 }
1781 
1782 /*
1783  * Name:	z_zlist_get_scratch
1784  * Description:	Determine name of scratch zone
1785  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1786  *		a_zoneIndex - index into a_zlst of the zone to use
1787  * Return:	char *
1788  *			== NULL - zone name could not be determined
1789  *			!= NULL - pointer to string representing scratch zone
1790  * NOTE:    	Any name returned is placed in static storage that must
1791  *		NEVER be free()ed by the caller.
1792  */
1793 
1794 char *
z_zlist_get_scratch(zoneList_t a_zlst,int a_zoneIndex)1795 z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex)
1796 {
1797 	int	i;
1798 
1799 	/* ignore empty list */
1800 
1801 	if (a_zlst == NULL)
1802 		return (NULL);
1803 
1804 	/* find the specified zone in the list */
1805 
1806 	for (i = 0; i != a_zoneIndex; i++) {
1807 		if (a_zlst[i]._zlName == NULL)
1808 			return (NULL);
1809 	}
1810 
1811 	/* return selected zone's scratch name */
1812 
1813 	return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName :
1814 	    a_zlst[i]._zlScratchName);
1815 }
1816 
1817 /*
1818  * Name:	z_zlist_get_zonename
1819  * Description:	Determine name of specified zone
1820  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1821  *		a_zoneIndex - index into a_zlst of the zone to return the
1822  * Return:	char *
1823  *			== NULL - zone name could not be determined
1824  *			!= NULL - pointer to string representing zone name
1825  * NOTE:    	Any zoneList_t returned is placed in static storage that must
1826  *		NEVER be free()ed by the caller.
1827  */
1828 
1829 char *
z_zlist_get_zonename(zoneList_t a_zlst,int a_zoneIndex)1830 z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex)
1831 {
1832 	int	i;
1833 
1834 	/* ignore empty list */
1835 
1836 	if (a_zlst == (zoneList_t)NULL) {
1837 		return ((char *)NULL);
1838 	}
1839 
1840 	/* find the specified zone in the list */
1841 
1842 	for (i = 0; (i != a_zoneIndex) &&
1843 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1844 		;
1845 
1846 	/* return error if the specified zone does not exist */
1847 
1848 	if (a_zlst[i]._zlName == (char *)NULL) {
1849 		return (NULL);
1850 	}
1851 
1852 	/* return selected zone's name */
1853 
1854 	return (a_zlst[i]._zlName);
1855 }
1856 
1857 /*
1858  * Name:	z_zlist_get_zonepath
1859  * Description:	Determine zonepath of specified zone
1860  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1861  *		a_zoneIndex - index into a_zlst of the zone to return
1862  * Return:	char *
1863  *			== NULL - zonepath could not be determined
1864  *			!= NULL - pointer to string representing zonepath
1865  * NOTE:    	Any zoneList_t returned is placed in static storage that must
1866  *		NEVER be free()ed by the caller.
1867  */
1868 
1869 char *
z_zlist_get_zonepath(zoneList_t a_zlst,int a_zoneIndex)1870 z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex)
1871 {
1872 	int	i;
1873 
1874 	/* ignore empty list */
1875 
1876 	if (a_zlst == (zoneList_t)NULL) {
1877 		return ((char *)NULL);
1878 	}
1879 
1880 	/* find the specified zone in the list */
1881 
1882 	for (i = 0; (i != a_zoneIndex) &&
1883 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1884 		;
1885 
1886 	/* return error if the specified zone does not exist */
1887 
1888 	if (a_zlst[i]._zlName == (char *)NULL) {
1889 		return (NULL);
1890 	}
1891 
1892 	/* return selected zone's zonepath */
1893 
1894 	return (a_zlst[i]._zlPath);
1895 }
1896 
1897 boolean_t
z_zlist_is_zone_runnable(zoneList_t a_zlst,int a_zoneIndex)1898 z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex)
1899 {
1900 	int	i;
1901 
1902 	/* if zones are not implemented, return error */
1903 
1904 	if (z_zones_are_implemented() == B_FALSE) {
1905 		return (B_FALSE);
1906 	}
1907 
1908 	/* ignore empty list */
1909 
1910 	if (a_zlst == (zoneList_t)NULL) {
1911 		return (B_FALSE);
1912 	}
1913 
1914 	/* find the specified zone in the list */
1915 
1916 	for (i = 0; (i != a_zoneIndex) &&
1917 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1918 		;
1919 
1920 	/* return error if the specified zone does not exist */
1921 
1922 	if (a_zlst[i]._zlName == (char *)NULL) {
1923 		return (B_FALSE);
1924 	}
1925 
1926 	/* choose based on current state */
1927 
1928 	switch (a_zlst[i]._zlCurrKernelStatus) {
1929 	case ZONE_STATE_RUNNING:
1930 	case ZONE_STATE_MOUNTED:
1931 		/* already running */
1932 		return (B_TRUE);
1933 
1934 	case ZONE_STATE_INSTALLED:
1935 	case ZONE_STATE_DOWN:
1936 	case ZONE_STATE_READY:
1937 	case ZONE_STATE_SHUTTING_DOWN:
1938 		/* return false if the zone cannot be booted */
1939 
1940 		if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) {
1941 			return (B_FALSE);
1942 		}
1943 
1944 		return (B_TRUE);
1945 
1946 	case ZONE_STATE_CONFIGURED:
1947 	case ZONE_STATE_INCOMPLETE:
1948 	default:
1949 		/* cannot transition (boot) these states */
1950 		return (B_FALSE);
1951 	}
1952 }
1953 
1954 /*
1955  * Name:	z_zlist_restore_zone_state
1956  * Description:	Return the zone to the state it was originally in
1957  * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1958  *		a_zoneIndex - index into a_zlst of the zone to return the
1959  * Returns:	boolean_t
1960  *			== B_TRUE - the zone's state has been restored
1961  *			== B_FALSE - unable to transition the zone to its
1962  *				original state
1963  */
1964 
1965 boolean_t
z_zlist_restore_zone_state(zoneList_t a_zlst,int a_zoneIndex)1966 z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex)
1967 {
1968 	int		i;
1969 
1970 	/* ignore empty list */
1971 
1972 	if (a_zlst == (zoneList_t)NULL) {
1973 		return (B_FALSE);
1974 	}
1975 
1976 	/* find the specified zone in the list */
1977 
1978 	for (i = 0; (i != a_zoneIndex) &&
1979 	    (a_zlst[i]._zlName != (char *)NULL); i++)
1980 		;
1981 
1982 	/* return error if the specified zone does not exist */
1983 
1984 	if (a_zlst[i]._zlName == (char *)NULL) {
1985 		return (B_FALSE);
1986 	}
1987 
1988 	/* transition the zone back to its original state */
1989 
1990 	return (z_zlist_change_zone_state(a_zlst,
1991 	    a_zoneIndex, a_zlst[i]._zlOrigKernelStatus));
1992 }
1993 
1994 /*
1995  * Name:	z_zone_exec
1996  * Description:	Execute a Unix command in a specified zone and return results
1997  * Arguments:	a_zoneName - pointer to string representing the name of the zone
1998  *			to execute the specified command in
1999  *		a_path - pointer to string representing the full path *in the
2000  *			non-global zone named by a_zoneName* of the Unix command
2001  *			to be executed
2002  *		a_argv[] - Pointer to array of character strings representing
2003  *			the arguments to be passed to the Unix command. The list
2004  *			must be termianted with an element that is (char *)NULL
2005  *		NOTE: a_argv[0] is the "command name" passed to the command
2006  *		a_stdoutPath - Pointer to string representing the path to a file
2007  *			into which all output to "stdout" from the Unix command
2008  *			is placed.
2009  *			== (char *)NULL - leave stdout open and pass through
2010  *			== "/dev/null" - discard stdout output
2011  *		a_strerrPath - Pointer to string representing the path to a file
2012  *			into which all output to "stderr" from the Unix command
2013  *			is placed.
2014  *			== (char *)NULL - leave stderr open and pass through
2015  *			== "/dev/null" - discard stderr output
2016  *		a_fds - Pointer to array of integers representing file
2017  *			descriptors to remain open during the call - all
2018  *			file descriptors above STDERR_FILENO not in this
2019  *			list will be closed.
2020  * Returns:	int
2021  *			The return (exit) code from the specified Unix command
2022  *			Special return codes:
2023  *			-1 : failure to exec process
2024  *			-2 : could not create contract for greenline
2025  *			-3 : fork() failed
2026  *			-4 : could not open stdout capture file
2027  *			-5 : error from 'waitpid' other than EINTR
2028  *			-6 : zones are not supported
2029  * NOTE:	All file descriptores other than 0, 1 and 2 are closed except
2030  *		for those file descriptors listed in the a_fds array.
2031  */
2032 
2033 int
z_zone_exec(const char * a_zoneName,const char * a_path,char * a_argv[],char * a_stdoutPath,char * a_stderrPath,int * a_fds)2034 z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[],
2035 	char *a_stdoutPath, char *a_stderrPath, int *a_fds)
2036 {
2037 	int			final_status;
2038 	int			lerrno;
2039 	int			status;
2040 	int			tmpl_fd;
2041 	pid_t			child_pid;
2042 	pid_t			result_pid;
2043 	struct sigaction	nact;
2044 	struct sigaction	oact;
2045 	void			(*funcSighup)();
2046 	void			(*funcSigint)();
2047 
2048 	/* if zones are not implemented, return TRUE */
2049 
2050 	if (z_zones_are_implemented() == B_FALSE) {
2051 		return (-6);	/* -6 : zones are not supported */
2052 	}
2053 
2054 	if ((tmpl_fd = _zexec_init_template()) == -1) {
2055 		_z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
2056 		return (-2);	/* -2 : could not create greenline contract */
2057 	}
2058 
2059 	/*
2060 	 * hold SIGINT/SIGHUP signals and reset signal received counter;
2061 	 * after the fork1() the parent and child need to setup their respective
2062 	 * interrupt handling and release the hold on the signals
2063 	 */
2064 
2065 	(void) sighold(SIGINT);
2066 	(void) sighold(SIGHUP);
2067 
2068 	_z_global_data._z_SigReceived = 0;	/* no signals received */
2069 
2070 	/*
2071 	 * fork off a new process to execute command in;
2072 	 * fork1() is used instead of vfork() so the child process can
2073 	 * perform operations that would modify the parent process if
2074 	 * vfork() were used
2075 	 */
2076 
2077 	child_pid = fork1();
2078 
2079 	if (child_pid < 0) {
2080 		/*
2081 		 * *************************************************************
2082 		 * fork failed!
2083 		 * *************************************************************
2084 		 */
2085 
2086 		(void) ct_tmpl_clear(tmpl_fd);
2087 		(void) close(tmpl_fd);
2088 		_z_program_error(ERR_FORK, strerror(errno));
2089 
2090 		/* release hold on signals */
2091 
2092 		(void) sigrelse(SIGHUP);
2093 		(void) sigrelse(SIGINT);
2094 
2095 		return (-3);	/* -3 : fork() failed */
2096 	}
2097 
2098 	if (child_pid == 0) {
2099 		int	i;
2100 
2101 		/*
2102 		 * *************************************************************
2103 		 * This is the forked (child) process
2104 		 * *************************************************************
2105 		 */
2106 
2107 		(void) ct_tmpl_clear(tmpl_fd);
2108 		(void) close(tmpl_fd);
2109 
2110 		/* reset any signals to default */
2111 
2112 		for (i = 0; i < NSIG; i++) {
2113 			(void) sigset(i, SIG_DFL);
2114 		}
2115 
2116 		/*
2117 		 * close all file descriptors not in the a_fds list
2118 		 */
2119 
2120 		(void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
2121 
2122 		/*
2123 		 * if a file for stdout is present, open the file and use the
2124 		 * file to capture stdout from the _zexec process
2125 		 */
2126 
2127 		if (a_stdoutPath != (char *)NULL) {
2128 			int	stdoutfd;
2129 
2130 			stdoutfd = open(a_stdoutPath,
2131 			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2132 			if (stdoutfd < 0) {
2133 				_z_program_error(ERR_CAPTURE_FILE, a_stdoutPath,
2134 				    strerror(errno));
2135 				return (-4);
2136 			}
2137 
2138 			(void) dup2(stdoutfd, STDOUT_FILENO);
2139 			(void) close(stdoutfd);
2140 		}
2141 
2142 		/*
2143 		 * if a file for stderr is present, open the file and use the
2144 		 * file to capture stderr from the _zexec process
2145 		 */
2146 
2147 		if (a_stderrPath != (char *)NULL) {
2148 			int	stderrfd;
2149 
2150 			stderrfd = open(a_stderrPath,
2151 			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2152 			if (stderrfd < 0) {
2153 				_z_program_error(ERR_CAPTURE_FILE, a_stderrPath,
2154 				    strerror(errno));
2155 				return (-4);
2156 			}
2157 
2158 			(void) dup2(stderrfd, STDERR_FILENO);
2159 			(void) close(stderrfd);
2160 		}
2161 
2162 		/* release all held signals */
2163 
2164 		(void) sigrelse(SIGHUP);
2165 		(void) sigrelse(SIGINT);
2166 
2167 		/* execute command in the specified non-global zone */
2168 
2169 		_exit(_zexec(a_zoneName, a_path, a_argv));
2170 	}
2171 
2172 	/*
2173 	 * *********************************************************************
2174 	 * This is the forking (parent) process
2175 	 * *********************************************************************
2176 	 */
2177 
2178 	/* register child process i.d. so signal handlers can pass signal on */
2179 
2180 	_z_global_data._z_ChildProcessId = child_pid;
2181 
2182 	/*
2183 	 * setup signal handlers for SIGINT and SIGHUP and release hold
2184 	 */
2185 
2186 	/* hook SIGINT to _z_sig_trap() */
2187 
2188 	nact.sa_handler = _z_sig_trap;
2189 	nact.sa_flags = SA_RESTART;
2190 	(void) sigemptyset(&nact.sa_mask);
2191 
2192 	if (sigaction(SIGINT, &nact, &oact) < 0) {
2193 		funcSigint = SIG_DFL;
2194 	} else {
2195 		funcSigint = oact.sa_handler;
2196 	}
2197 
2198 	/* hook SIGHUP to _z_sig_trap() */
2199 
2200 	nact.sa_handler = _z_sig_trap;
2201 	nact.sa_flags = SA_RESTART;
2202 	(void) sigemptyset(&nact.sa_mask);
2203 
2204 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
2205 		funcSighup = SIG_DFL;
2206 	} else {
2207 		funcSighup = oact.sa_handler;
2208 	}
2209 
2210 	/* release hold on signals */
2211 
2212 	(void) sigrelse(SIGHUP);
2213 	(void) sigrelse(SIGINT);
2214 
2215 	(void) ct_tmpl_clear(tmpl_fd);
2216 	(void) close(tmpl_fd);
2217 
2218 	/*
2219 	 * wait for the process to exit, reap child exit status
2220 	 */
2221 
2222 	for (;;) {
2223 		result_pid = waitpid(child_pid, &status, 0L);
2224 		lerrno = (result_pid == -1 ? errno : 0);
2225 
2226 		/* break loop if child process status reaped */
2227 
2228 		if (result_pid != -1) {
2229 			break;
2230 		}
2231 
2232 		/* break loop if not interrupted out of waitpid */
2233 
2234 		if (errno != EINTR) {
2235 			break;
2236 		}
2237 	}
2238 
2239 	/* reset child process i.d. so signal handlers do not pass signals on */
2240 
2241 	_z_global_data._z_ChildProcessId = -1;
2242 
2243 	/*
2244 	 * If the child process terminated due to a call to exit(), then
2245 	 * set results equal to the 8-bit exit status of the child process;
2246 	 * otherwise, set the exit status to "-1" indicating that the child
2247 	 * exited via a signal.
2248 	 */
2249 
2250 	if (WIFEXITED(status)) {
2251 		final_status = WEXITSTATUS(status);
2252 		if ((_z_global_data._z_SigReceived != 0) &&
2253 		    (final_status == 0)) {
2254 			final_status = 1;
2255 		}
2256 	} else {
2257 		final_status = -1;	/* -1 : failure to exec process */
2258 	}
2259 
2260 	/* determine proper exit code */
2261 
2262 	if (result_pid == -1) {
2263 		final_status = -5;	/* -5 : error from waitpid not EINTR */
2264 	} else if (_z_global_data._z_SigReceived != 0) {
2265 		final_status = -7;	/* -7 : interrupt received */
2266 	}
2267 
2268 	/*
2269 	 * reset signal handlers
2270 	 */
2271 
2272 	/* reset SIGINT */
2273 
2274 	nact.sa_handler = funcSigint;
2275 	nact.sa_flags = SA_RESTART;
2276 	(void) sigemptyset(&nact.sa_mask);
2277 
2278 	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2279 
2280 	/* reset SIGHUP */
2281 
2282 	nact.sa_handler = funcSighup;
2283 	nact.sa_flags = SA_RESTART;
2284 	(void) sigemptyset(&nact.sa_mask);
2285 
2286 	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2287 
2288 	/*
2289 	 * if signal received during command execution, interrupt
2290 	 * this process now.
2291 	 */
2292 
2293 	if (_z_global_data._z_SigReceived != 0) {
2294 		(void) kill(getpid(), SIGINT);
2295 	}
2296 
2297 	/* set errno and return */
2298 
2299 	errno = lerrno;
2300 
2301 	return (final_status);
2302 }
2303 
2304 /*
2305  * Name:	z_zones_are_implemented
2306  * Description:	Determine if any zone operations can be performed
2307  * Arguments:	void
2308  * Returns:	boolean_t
2309  *			== B_TRUE - zone operations are available
2310  *			== B_FALSE - no zone operations can be done
2311  */
2312 
2313 boolean_t
z_zones_are_implemented(void)2314 z_zones_are_implemented(void)
2315 {
2316 	static	boolean_t	_zonesImplementedDetermined = B_FALSE;
2317 	static	boolean_t	_zonesAreImplemented = B_FALSE;
2318 
2319 	/* if availability has not been determined, cache it now */
2320 
2321 	if (!_zonesImplementedDetermined) {
2322 		_zonesImplementedDetermined = B_TRUE;
2323 		_zonesAreImplemented = _z_zones_are_implemented();
2324 		if (!_zonesAreImplemented) {
2325 			_z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED);
2326 		} else {
2327 			_z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED);
2328 		}
2329 	}
2330 
2331 	return (_zonesAreImplemented);
2332 }
2333