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 /* lock patch administration always */
697
698 if (a_lflags & ZLOCKS_PATCH_ADMIN) {
699 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
700 zoneName, LOBJ_PATCHADMIN, pid,
701 MSG_ZONES_LCK_THIS_PATCHADM,
702 ERR_ZONES_LCK_THIS_PATCHADM);
703 if (!b) {
704 (void) z_unlock_this_zone(a_lflags);
705 (void) free(zoneName);
706 return (B_FALSE);
707 }
708 }
709
710 (void) free(zoneName);
711
712 return (B_TRUE);
713 }
714
715 /*
716 * Name: z_lock_zones
717 * Description: lock specified zones
718 * Arguments: a_zlst - zoneList_t object describing zones to lock
719 * a_lflags - [RO, *RO] - (ZLOCKS_T)
720 * Flags indicating which locks to acquire
721 * Returns: boolean_t
722 * == B_TRUE - success, zones locked
723 * == B_FALSE - failure, zones not locked
724 */
725
726 boolean_t
z_lock_zones(zoneList_t a_zlst,ZLOCKS_T a_lflags)727 z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
728 {
729 boolean_t b;
730 int i;
731
732 /* entry assertions */
733
734 assert(a_lflags != ZLOCKS_NONE);
735
736 /* entry debugging info */
737
738 _z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags);
739
740 /* if zones are not implemented, return TRUE */
741
742 if (z_zones_are_implemented() == B_FALSE) {
743 _z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP);
744 return (B_TRUE);
745 }
746
747 /* lock this zone first before locking other zones */
748
749 b = z_lock_this_zone(a_lflags);
750 if (b == B_FALSE) {
751 return (b);
752 }
753
754 /* ignore empty list */
755
756 if (a_zlst == (zoneList_t)NULL) {
757 _z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES);
758 return (B_FALSE);
759 }
760
761 /* zones exist */
762
763 _z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST);
764
765 /*
766 * lock each listed zone that is currently running
767 */
768
769 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
770 /* ignore zone if already locked */
771 if (a_zlst[i]._zlStatus & ZST_LOCKED) {
772 continue;
773 }
774
775 /* ignore zone if not running */
776 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
777 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
778 continue;
779 }
780
781 /*
782 * mark zone locked - if interrupted out during lock, an attempt
783 * will be made to release the lock
784 */
785 a_zlst[i]._zlStatus |= ZST_LOCKED;
786
787 /* lock this zone */
788 b = _z_lock_zone(&a_zlst[i], a_lflags);
789
790 /* on failure unlock all zones and return error */
791 if (b != B_TRUE) {
792 _z_program_error(ERR_ZONES_LCK_ZONES_FAILED,
793 a_zlst[i]._zlName);
794 (void) z_unlock_zones(a_zlst, a_lflags);
795 return (B_FALSE);
796 }
797 }
798
799 /* success */
800
801 return (B_TRUE);
802 }
803
804 /*
805 * Name: z_mount_in_lz
806 * Description: Mount global zone directory in specified zone's root file system
807 * Arguments: r_lzMountPoint - pointer to handle to string - on success, the
808 * full path to the mount point relative to the global zone
809 * root file system is returned here - this is needed to
810 * unmount the directory when it is no longer needed
811 * r_lzRootPath - pointer to handle to string - on success, the
812 * full path to the mount point relative to the specified
813 * zone's root file system is returned here - this is
814 * passed to any command executing in the specified zone to
815 * access the directory mounted
816 * a_zoneName - pointer to string representing the name of the zone
817 * to mount the specified global zone directory in
818 * a_gzPath - pointer to string representing the full absolute path
819 * of the global zone directory to LOFS mount inside of the
820 * specified non-global zone
821 * a_mountPointPrefix - pointer to string representing the prefix
822 * to be used when creating the mount point name in the
823 * specified zone's root directory
824 * Returns: boolean_t
825 * == B_TRUE - global zone directory mounted successfully
826 * == B_FALSE - failed to mount directory in specified zone
827 * NOTE: Any strings returned is placed in new storage for the
828 * calling function. The caller must use 'Free' to dispose
829 * of the storage once the strings are no longer needed.
830 */
831
832 boolean_t
z_mount_in_lz(char ** r_lzMountPoint,char ** r_lzRootPath,char * a_zoneName,char * a_gzPath,char * a_mountPointPrefix)833 z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName,
834 char *a_gzPath, char *a_mountPointPrefix)
835 {
836 char lzRootPath[MAXPATHLEN] = {'\0'};
837 char uuid[MAXPATHLEN] = {'\0'};
838 char gzMountPoint[MAXPATHLEN] = {'\0'};
839 char lzMountPoint[MAXPATHLEN] = {'\0'};
840 hrtime_t hretime;
841 int err;
842 int slen;
843 struct tm tstruct;
844 time_t thetime;
845 zoneid_t zid;
846
847 /* entry assertions */
848
849 assert(a_zoneName != (char *)NULL);
850 assert(*a_zoneName != '\0');
851 assert(a_gzPath != (char *)NULL);
852 assert(*a_gzPath != '\0');
853 assert(r_lzMountPoint != (char **)NULL);
854 assert(r_lzRootPath != (char **)NULL);
855
856 /* entry debugging info */
857
858 _z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath);
859
860 /* reset returned non-global zone mount point path handle */
861
862 *r_lzMountPoint = (char *)NULL;
863 *r_lzRootPath = (char *)NULL;
864
865 /* if zones are not implemented, return FALSE */
866
867 if (z_zones_are_implemented() == B_FALSE) {
868 return (B_FALSE);
869 }
870
871 /* error if global zone path is not absolute */
872
873 if (*a_gzPath != '/') {
874 _z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath);
875 return (B_FALSE);
876 }
877
878 /* error if global zone path does not exist */
879
880 if (_z_is_directory(a_gzPath) != 0) {
881 _z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno));
882 return (B_FALSE);
883 }
884
885 /* verify that specified non-global zone exists */
886
887 err = zone_get_id(a_zoneName, &zid);
888 if (err != Z_OK) {
889 _z_program_error(ERR_GET_ZONEID, a_zoneName,
890 zonecfg_strerror(err));
891 return (B_FALSE);
892 }
893
894 /* obtain global zone path to non-global zones root file system */
895
896 err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath));
897 if (err != Z_OK) {
898 _z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName,
899 zonecfg_strerror(err));
900 return (B_FALSE);
901 }
902
903 if (lzRootPath[0] == '\0') {
904 _z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName);
905 return (B_FALSE);
906 }
907
908 /*
909 * lofs resolve the non-global zone's root path first in case
910 * its in a path that's been lofs mounted read-only.
911 * (e.g. This happens when we're tyring to patch a zone in an ABE
912 * that lives on a filesystem that the ABE shares with the currently
913 * running BE.)
914 */
915 z_resolve_lofs(lzRootPath, sizeof (lzRootPath));
916
917 /* verify that the root path exists */
918
919 if (_z_is_directory(lzRootPath) != 0) {
920 _z_program_error(ERR_LZROOT_NOTDIR, lzRootPath,
921 strerror(errno));
922 return (B_FALSE);
923 }
924
925 /*
926 * generate a unique key - the key is the same length as unique uid
927 * but contains different information that is as unique as can be made;
928 * include current hires time (nanosecond real timer). Such a unique
929 * i.d. will look like:
930 * 0203104092-1145345-0004e94d6af481a0
931 */
932
933 hretime = gethrtime();
934
935 thetime = time((time_t *)NULL);
936 (void) localtime_r(&thetime, &tstruct);
937
938 slen = snprintf(uuid, sizeof (uuid),
939 UUID_FORMAT,
940 tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year,
941 tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min,
942 tstruct.tm_sec, tstruct.tm_wday, hretime);
943 if (slen > sizeof (uuid)) {
944 _z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED,
945 UUID_FORMAT, sizeof (uuid));
946 return (B_FALSE);
947 }
948
949 /* create the global zone mount point */
950
951 slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s",
952 lzRootPath,
953 a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid);
954 if (slen > sizeof (gzMountPoint)) {
955 _z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED,
956 "%s/.SUNW_%s_%s", lzRootPath,
957 a_mountPointPrefix ? a_mountPointPrefix : "zones",
958 uuid, sizeof (gzMountPoint));
959 return (B_FALSE);
960 }
961
962 slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s",
963 gzMountPoint+strlen(lzRootPath));
964 if (slen > sizeof (lzMountPoint)) {
965 _z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED,
966 "%s", gzMountPoint+strlen(lzRootPath),
967 sizeof (lzMountPoint));
968 return (B_FALSE);
969 }
970
971 _z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint,
972 lzMountPoint);
973
974 /* error if the mount point already exists */
975
976 if (_z_is_directory(gzMountPoint) == 0) {
977 _z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint,
978 a_zoneName, strerror(errno));
979 return (B_FALSE);
980 }
981
982 /* create the temporary mount point */
983
984 if (mkdir(gzMountPoint, 0600) != 0) {
985 _z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName,
986 strerror(errno));
987 return (B_FALSE);
988 }
989
990 /* mount the global zone path on the non-global zone root file system */
991
992 err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs",
993 (char *)NULL, 0, (char *)NULL, 0);
994 if (err != 0) {
995 _z_program_error(ERR_GZMOUNT_FAILED, a_gzPath,
996 gzMountPoint, a_zoneName, strerror(errno));
997 return (B_FALSE);
998 }
999
1000 /* success - return both mountpoints to caller */
1001
1002 *r_lzMountPoint = _z_strdup(gzMountPoint);
1003
1004 *r_lzRootPath = _z_strdup(lzMountPoint);
1005
1006 /* return success */
1007
1008 return (B_TRUE);
1009 }
1010
1011 /*
1012 * Name: z_non_global_zones_exist
1013 * Description: Determine if any non-global native zones exist
1014 * Arguments: None.
1015 * Returns: boolean_t
1016 * == B_TRUE - at least one non-global native zone exists
1017 * == B_FALSE - no non-global native zone exists
1018 */
1019
1020 boolean_t
z_non_global_zones_exist(void)1021 z_non_global_zones_exist(void)
1022 {
1023 FILE *zoneIndexFP;
1024 boolean_t anyExist = B_FALSE;
1025 struct zoneent *ze;
1026 zone_spec_t *zent;
1027
1028 /* if zones are not implemented, return FALSE */
1029
1030 if (z_zones_are_implemented() == B_FALSE) {
1031 return (B_FALSE);
1032 }
1033
1034 /* determine if any zones are configured */
1035 zoneIndexFP = setzoneent();
1036 if (zoneIndexFP == NULL) {
1037 return (B_FALSE);
1038 }
1039
1040 /* index file open; scan all zones; see if any are at least installed */
1041
1042 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1043 /*
1044 * If the user specified an explicit zone list, then ignore any
1045 * zones that aren't on that list.
1046 */
1047 if ((zent = _z_global_data._zone_spec) != NULL) {
1048 while (zent != NULL) {
1049 if (strcmp(zent->zl_name, ze->zone_name) == 0)
1050 break;
1051 zent = zent->zl_next;
1052 }
1053 if (zent == NULL) {
1054 free(ze);
1055 continue;
1056 }
1057 }
1058
1059 /* skip the global zone */
1060 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
1061 free(ze);
1062 continue;
1063 }
1064
1065 /* skip any branded zones */
1066 if (z_is_zone_branded(ze->zone_name)) {
1067 free(ze);
1068 continue;
1069 }
1070
1071 /* is this zone installed? */
1072 if (ze->zone_state >= ZONE_STATE_INSTALLED) {
1073 free(ze);
1074 anyExist = B_TRUE;
1075 break;
1076 }
1077 free(ze);
1078 }
1079
1080 /* close the index file */
1081
1082 endzoneent(zoneIndexFP);
1083
1084 /* return results */
1085
1086 return (anyExist);
1087 }
1088
1089 /*
1090 * Name: z_on_zone_spec
1091 * Description: Determine if named zone is on the zone_spec list.
1092 * Arguments: Pointer to name to test.
1093 * Returns: B_TRUE if named zone is on the list or if the user specified
1094 * no list at all (all zones is the default), B_FALSE otherwise.
1095 */
1096
1097 boolean_t
z_on_zone_spec(const char * zonename)1098 z_on_zone_spec(const char *zonename)
1099 {
1100 zone_spec_t *zent;
1101
1102 /* entry assertions */
1103
1104 assert(zonename != NULL);
1105 assert(*zonename != '\0');
1106
1107 /* return true if zones not implemented or no zone spec list defined */
1108
1109 if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) {
1110 return (B_TRUE);
1111 }
1112
1113 /* return true if named zone is on the zone spec list */
1114
1115 for (zent = _z_global_data._zone_spec;
1116 zent != NULL; zent = zent->zl_next) {
1117 if (strcmp(zent->zl_name, zonename) == 0)
1118 return (B_TRUE);
1119 }
1120
1121 /* named zone is not on the zone spec list */
1122
1123 return (B_FALSE);
1124 }
1125
1126 /*
1127 * Name: z_running_in_global_zone
1128 * Description: Determine if running in the "global" zone
1129 * Arguments: void
1130 * Returns: boolean_t
1131 * == B_TRUE - running in global zone
1132 * == B_FALSE - not running in global zone
1133 */
1134
1135 boolean_t
z_running_in_global_zone(void)1136 z_running_in_global_zone(void)
1137 {
1138 static boolean_t _zoneIdDetermined = B_FALSE;
1139 static boolean_t _zoneIsGlobal = B_FALSE;
1140
1141 /* if ID has not been determined, cache it now */
1142
1143 if (!_zoneIdDetermined) {
1144 _zoneIdDetermined = B_TRUE;
1145 _zoneIsGlobal = _z_running_in_global_zone();
1146 }
1147
1148 return (_zoneIsGlobal);
1149 }
1150
1151 /*
1152 * Name: z_set_output_functions
1153 * Description: Link program specific output functions to this library.
1154 * Arguments: a_echo_fcn - (_z_printf_fcn_t)
1155 * Function to call to cause "normal operation" messages
1156 * to be output/displayed
1157 * a_echo_debug_fcn - (_z_printf_fcn_t)
1158 * Function to call to cause "debugging" messages
1159 * to be output/displayed
1160 * a_progerr_fcn - (_z_printf_fcn_t)
1161 * Function to call to cause "program error" messages
1162 * to be output/displayed
1163 * Returns: void
1164 * NOTE: If NULL is specified for any function, then the functionality
1165 * associated with that function is disabled.
1166 * NOTE: The function pointers provided must call a function that
1167 * takes two arguments:
1168 * function(char *format, char *message)
1169 * Any registered function will be called like:
1170 * function("%s", "message")
1171 */
1172
1173 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)1174 z_set_output_functions(_z_printf_fcn_t a_echo_fcn,
1175 _z_printf_fcn_t a_echo_debug_fcn,
1176 _z_printf_fcn_t a_progerr_fcn)
1177 {
1178 _z_global_data._z_echo = a_echo_fcn;
1179 _z_global_data._z_echo_debug = a_echo_debug_fcn;
1180 _z_global_data._z_progerr = a_progerr_fcn;
1181 }
1182
1183 /*
1184 * Name: z_set_zone_root
1185 * Description: Set root for zones library operations
1186 * Arguments: Path to root of boot environment containing zone; must be
1187 * absolute.
1188 * Returns: None.
1189 * NOTE: Must be called before performing any zone-related operations.
1190 * (Currently called directly by set_inst_root() during -R
1191 * argument handling.)
1192 */
1193
1194 void
z_set_zone_root(const char * zroot)1195 z_set_zone_root(const char *zroot)
1196 {
1197 char *rootdir;
1198
1199 /* if zones are not implemented, just return */
1200
1201 if (!z_zones_are_implemented())
1202 return;
1203
1204 /* entry assertions */
1205
1206 assert(zroot != NULL);
1207
1208 rootdir = _z_strdup((char *)zroot);
1209 z_canoninplace(rootdir);
1210
1211 if (strcmp(rootdir, "/") == 0) {
1212 rootdir[0] = '\0';
1213 }
1214
1215 /* free any existing cached root path */
1216 if (*_z_global_data._z_root_dir != '\0') {
1217 free(_z_global_data._z_root_dir);
1218 _z_global_data._z_root_dir = NULL;
1219 }
1220
1221 /* store duplicate of new zone root path */
1222
1223 if (*rootdir != '\0') {
1224 _z_global_data._z_root_dir = _z_strdup(rootdir);
1225 } else {
1226 _z_global_data._z_root_dir = "";
1227 }
1228
1229 /* set zone root path */
1230
1231 zonecfg_set_root(rootdir);
1232
1233 free(rootdir);
1234 }
1235
1236 /*
1237 * Name: z_set_zone_spec
1238 * Description: Set list of zones on which actions will be performed.
1239 * Arguments: Whitespace-separated list of zone names.
1240 * Returns: 0 on success, -1 on error.
1241 * NOTES: Will call _z_program_error if argument can't be parsed or
1242 * memory not available.
1243 */
1244
1245 int
z_set_zone_spec(const char * zlist)1246 z_set_zone_spec(const char *zlist)
1247 {
1248 const char *zend;
1249 ptrdiff_t zlen;
1250 zone_spec_t *zent;
1251 zone_spec_t *zhead;
1252 zone_spec_t **znextp = &zhead;
1253
1254 /* entry assertions */
1255
1256 assert(zlist != NULL);
1257
1258 /* parse list to zone_spec_t list, store in global data */
1259
1260 for (;;) {
1261 while (isspace(*zlist)) {
1262 zlist++;
1263 }
1264 if (*zlist == '\0') {
1265 break;
1266 }
1267 for (zend = zlist; *zend != '\0'; zend++) {
1268 if (isspace(*zend)) {
1269 break;
1270 }
1271 }
1272 zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist);
1273 if (zlen >= ZONENAME_MAX) {
1274 _z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist);
1275 return (-1);
1276 }
1277 zent = _z_malloc(sizeof (*zent));
1278 (void) memcpy(zent->zl_name, zlist, zlen);
1279 zent->zl_name[zlen] = '\0';
1280 zent->zl_used = B_FALSE;
1281 *znextp = zent;
1282 znextp = &zent->zl_next;
1283 zlist = zend;
1284 }
1285 *znextp = NULL;
1286
1287 if (zhead == NULL) {
1288 _z_program_error(ERR_ZONE_LIST_EMPTY);
1289 return (-1);
1290 }
1291
1292 _z_global_data._zone_spec = zhead;
1293 return (0);
1294 }
1295
1296 /*
1297 * Name: z_umount_lz_mount
1298 * Description: Unmount directory mounted with z_mount_in_lz
1299 * Arguments: a_lzMountPointer - pointer to string returned by z_mount_in_lz
1300 * Returns: boolean_t
1301 * == B_TRUE - successfully unmounted directory
1302 * == B_FALSE - failed to unmount directory
1303 */
1304
1305 boolean_t
z_umount_lz_mount(char * a_lzMountPoint)1306 z_umount_lz_mount(char *a_lzMountPoint)
1307 {
1308 int err;
1309
1310 /* entry assertions */
1311
1312 assert(a_lzMountPoint != (char *)NULL);
1313 assert(*a_lzMountPoint != '\0');
1314
1315 /* entry debugging info */
1316
1317 _z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint);
1318
1319 /* if zones are not implemented, return TRUE */
1320
1321 if (z_zones_are_implemented() == B_FALSE) {
1322 return (B_FALSE);
1323 }
1324
1325 /* error if global zone path is not absolute */
1326
1327 if (*a_lzMountPoint != '/') {
1328 _z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint);
1329 return (B_FALSE);
1330 }
1331
1332 /* verify mount point exists */
1333
1334 if (_z_is_directory(a_lzMountPoint) != 0) {
1335 _z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint,
1336 strerror(errno));
1337 return (B_FALSE);
1338 }
1339
1340 /* unmount */
1341
1342 err = umount2(a_lzMountPoint, 0);
1343 if (err != 0) {
1344 _z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint,
1345 strerror(errno));
1346 return (B_FALSE);
1347 }
1348
1349 /* remove the mount point */
1350
1351 (void) remove(a_lzMountPoint);
1352
1353 /* return success */
1354
1355 return (B_TRUE);
1356 }
1357
1358 /*
1359 * Name: z_unlock_this_zone
1360 * Description: unlock this zone
1361 * Arguments: a_lflags - [RO, *RO] - (ZLOCKS_T)
1362 * Flags indicating which locks to release
1363 * Returns: boolean_t
1364 * == B_TRUE - success specified locks released
1365 * == B_FALSE - failure specified locks may not be released
1366 * NOTE: the lock objects for "this zone" are maintained internally.
1367 */
1368
1369 boolean_t
z_unlock_this_zone(ZLOCKS_T a_lflags)1370 z_unlock_this_zone(ZLOCKS_T a_lflags)
1371 {
1372 boolean_t b;
1373 boolean_t errors = B_FALSE;
1374 char *zoneName;
1375
1376 /* entry assertions */
1377
1378 assert(a_lflags != ZLOCKS_NONE);
1379
1380 /* entry debugging info */
1381
1382 _z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags);
1383
1384 /* return if no objects locked */
1385
1386 if ((_z_global_data._z_ObjectLocks == (char *)NULL) ||
1387 (*_z_global_data._z_ObjectLocks == '\0')) {
1388 return (B_TRUE);
1389 }
1390
1391 zoneName = z_get_zonename();
1392
1393 /* unlock patch administration */
1394
1395 if (a_lflags & ZLOCKS_PATCH_ADMIN) {
1396 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1397 zoneName, LOBJ_PATCHADMIN, ERR_ZONES_ULK_THIS_PATCH);
1398 if (!b) {
1399 errors = B_TRUE;
1400 }
1401 }
1402
1403 /* unlock package administration */
1404
1405 if (a_lflags & ZLOCKS_PKG_ADMIN) {
1406 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1407 zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE);
1408 if (!b) {
1409 errors = B_TRUE;
1410 }
1411 }
1412
1413 /* unlock zone administration */
1414
1415 if (a_lflags & ZLOCKS_ZONE_ADMIN) {
1416 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1417 zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES);
1418 if (!b) {
1419 errors = B_TRUE;
1420 }
1421 }
1422
1423 (void) free(zoneName);
1424 return (!errors);
1425 }
1426
1427 /*
1428 * Name: z_unlock_zones
1429 * Description: unlock specified zones
1430 * Arguments: a_zlst - zoneList_t object describing zones to unlock
1431 * a_lflags - [RO, *RO] - (ZLOCKS_T)
1432 * Flags indicating which locks to release
1433 * Returns: boolean_t
1434 * == B_TRUE - success, zones unlocked
1435 * == B_FALSE - failure, zones not unlocked
1436 */
1437
1438 boolean_t
z_unlock_zones(zoneList_t a_zlst,ZLOCKS_T a_lflags)1439 z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
1440 {
1441 boolean_t b;
1442 boolean_t errors = B_FALSE;
1443 int i;
1444
1445 /* entry assertions */
1446
1447 assert(a_lflags != ZLOCKS_NONE);
1448
1449 /* entry debugging info */
1450
1451 _z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags);
1452
1453 /* if zones are not implemented, return TRUE */
1454
1455 if (z_zones_are_implemented() == B_FALSE) {
1456 _z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP);
1457 return (B_TRUE);
1458 }
1459
1460 /* ignore empty list */
1461
1462 if (a_zlst == (zoneList_t)NULL) {
1463 _z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES);
1464 /* unlock this zone before returning */
1465 return (z_unlock_this_zone(a_lflags));
1466 }
1467
1468 /* zones exist */
1469
1470 _z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST);
1471
1472 /*
1473 * unlock each listed zone that is currently running
1474 */
1475
1476 for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
1477 /* ignore zone if not locked */
1478 if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) {
1479 continue;
1480 }
1481
1482 /* ignore zone if not running */
1483 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
1484 a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
1485 continue;
1486 }
1487
1488 /* unlock this zone */
1489 b = _z_unlock_zone(&a_zlst[i], a_lflags);
1490
1491 if (b != B_TRUE) {
1492 errors = B_TRUE;
1493 } else {
1494 /* mark zone as unlocked */
1495 a_zlst[i]._zlStatus &= ~ZST_LOCKED;
1496 }
1497 }
1498
1499 /* unlock this zone */
1500
1501 if (z_unlock_this_zone(a_lflags) != B_TRUE) {
1502 errors = B_TRUE;
1503 }
1504
1505 return (errors);
1506 }
1507
1508 /*
1509 * Name: z_verify_zone_spec
1510 * Description: Verify list of zones on which actions will be performed.
1511 * Arguments: None.
1512 * Returns: 0 on success, -1 on error.
1513 * NOTES: Will call _z_program_error if there are zones on the specified
1514 * list that don't exist on the system. Requires that
1515 * z_set_zone_root is called first (if it is called at all).
1516 */
1517
1518 int
z_verify_zone_spec(void)1519 z_verify_zone_spec(void)
1520 {
1521 FILE *zoneIndexFP;
1522 boolean_t errors;
1523 char zoneIndexPath[MAXPATHLEN];
1524 struct zoneent *ze;
1525 zone_spec_t *zent;
1526
1527 if (!z_zones_are_implemented()) {
1528 _z_program_error(ERR_ZONES_NOT_IMPLEMENTED);
1529 return (-1);
1530 }
1531
1532 zoneIndexFP = setzoneent();
1533 if (zoneIndexFP == NULL) {
1534 _z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath,
1535 strerror(errno));
1536 return (-1);
1537 }
1538
1539 while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1540 for (zent = _z_global_data._zone_spec;
1541 zent != NULL; zent = zent->zl_next) {
1542 if (strcmp(zent->zl_name, ze->zone_name) == 0) {
1543 zent->zl_used = B_TRUE;
1544 break;
1545 }
1546 }
1547 free(ze);
1548 }
1549 endzoneent(zoneIndexFP);
1550
1551 errors = B_FALSE;
1552 for (zent = _z_global_data._zone_spec;
1553 zent != NULL; zent = zent->zl_next) {
1554 if (!zent->zl_used) {
1555 _z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name);
1556 errors = B_TRUE;
1557 }
1558 }
1559 return (errors ? -1 : 0);
1560 }
1561
1562 /*
1563 * Name: z_zlist_change_zone_state
1564 * Description: Change the current state of the specified zone
1565 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1566 * a_zoneIndex - index into a_zlst of the zone to return the
1567 * a_newState - the state to put the specified zone in
1568 * Returns: boolean_t
1569 * == B_TRUE - the zone is in the new state
1570 * == B_FALSE - unable to transition the zone to the
1571 * specified state
1572 * NOTE: This changes the "current kernel" state of the specified
1573 * zone. For example, to boot the zone, change the state
1574 * to "ZONE_STATE_RUNNING". To halt the zone, change the
1575 * state to "ZONE_STATE_INSTALLED".
1576 */
1577
1578 boolean_t
z_zlist_change_zone_state(zoneList_t a_zlst,int a_zoneIndex,zone_state_t a_newState)1579 z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex,
1580 zone_state_t a_newState)
1581 {
1582 int i;
1583
1584 /* entry debugging info */
1585
1586 _z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState);
1587
1588 /* ignore empty list */
1589
1590 if (a_zlst == (zoneList_t)NULL) {
1591 return (B_FALSE);
1592 }
1593
1594 /* find the specified zone in the list */
1595
1596 for (i = 0; (i != a_zoneIndex) &&
1597 (a_zlst[i]._zlName != (char *)NULL); i++)
1598 ;
1599
1600 /* return error if the specified zone does not exist */
1601
1602 if (a_zlst[i]._zlName == (char *)NULL) {
1603 return (B_FALSE);
1604 }
1605
1606 /* return success if the zone is already in this state */
1607
1608 if (a_zlst[i]._zlCurrKernelStatus == a_newState) {
1609 return (B_TRUE);
1610 }
1611
1612 /* take action on new state to set zone to */
1613
1614 _z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName,
1615 a_zlst[i]._zlCurrKernelStatus, a_newState);
1616
1617 switch (a_newState) {
1618 case ZONE_STATE_RUNNING:
1619 case ZONE_STATE_MOUNTED:
1620 /* these states mean "boot the zone" */
1621 return (_z_make_zone_running(&a_zlst[i]));
1622
1623 case ZONE_STATE_DOWN:
1624 case ZONE_STATE_INSTALLED:
1625 /* these states mean "halt the zone" */
1626 return (_z_make_zone_down(&a_zlst[i]));
1627
1628 case ZONE_STATE_READY:
1629 return (_z_make_zone_ready(&a_zlst[i]));
1630
1631 case ZONE_STATE_CONFIGURED:
1632 case ZONE_STATE_INCOMPLETE:
1633 case ZONE_STATE_SHUTTING_DOWN:
1634 default:
1635 /* do not know how to change zone to this state */
1636 return (B_FALSE);
1637 }
1638 }
1639
1640 /*
1641 * Name: z_is_zone_branded
1642 * Description: Determine whether zone has a non-native brand
1643 * Arguments: a_zoneName - name of the zone to check for branding
1644 * Returns: boolean_t
1645 * == B_TRUE - zone has a non-native brand
1646 * == B_FALSE - zone is native
1647 */
1648 boolean_t
z_is_zone_branded(char * zoneName)1649 z_is_zone_branded(char *zoneName)
1650 {
1651 char brandname[MAXNAMELEN];
1652 int err;
1653
1654 /* if zones are not implemented, return FALSE */
1655 if (!z_zones_are_implemented()) {
1656 return (B_FALSE);
1657 }
1658
1659 /* if brands are not implemented, return FALSE */
1660 if (!z_brands_are_implemented()) {
1661 return (B_FALSE);
1662 }
1663
1664 err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1665 if (err != Z_OK) {
1666 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1667 return (B_FALSE);
1668 }
1669
1670 /*
1671 * Both "native" and "cluster" are native brands
1672 * that use the standard facilities in the areas
1673 * of packaging/installation/patching/update.
1674 */
1675 if (streq(brandname, NATIVE_BRAND_NAME) ||
1676 streq(brandname, CLUSTER_BRAND_NAME)) {
1677 return (B_FALSE);
1678 } else {
1679 return (B_TRUE);
1680 }
1681 }
1682
1683 /*
1684 * Name: z_is_zone_brand_in_list
1685 * Description: Determine whether zone's brand has a match in the list
1686 * brands passed in.
1687 * Arguments: zoneName - name of the zone to check for branding
1688 * list - list of brands to check the zone against
1689 * Returns: boolean_t
1690 * == B_TRUE - zone has a matching brand
1691 * == B_FALSE - zone brand is not in list
1692 */
1693 boolean_t
z_is_zone_brand_in_list(char * zoneName,zoneBrandList_t * list)1694 z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list)
1695 {
1696 char brandname[MAXNAMELEN];
1697 int err;
1698 zoneBrandList_t *sp;
1699
1700 if (zoneName == NULL || list == NULL)
1701 return (B_FALSE);
1702
1703 /* if zones are not implemented, return FALSE */
1704 if (!z_zones_are_implemented()) {
1705 return (B_FALSE);
1706 }
1707
1708 /* if brands are not implemented, return FALSE */
1709 if (!z_brands_are_implemented()) {
1710 return (B_FALSE);
1711 }
1712
1713 err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1714 if (err != Z_OK) {
1715 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1716 return (B_FALSE);
1717 }
1718
1719 for (sp = list; sp != NULL; sp = sp->next) {
1720 if (sp->string_ptr != NULL &&
1721 strcmp(sp->string_ptr, brandname) == 0) {
1722 return (B_TRUE);
1723 }
1724 }
1725
1726 return (B_FALSE);
1727 }
1728
1729 /*
1730 * Name: z_zlist_get_current_state
1731 * Description: Determine the current kernel state of the specified zone
1732 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1733 * a_zoneIndex - index into a_zlst of the zone to return
1734 * Returns: zone_state_t
1735 * The current state of the specified zone is returned
1736 */
1737
1738 zone_state_t
z_zlist_get_current_state(zoneList_t a_zlst,int a_zoneIndex)1739 z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex)
1740 {
1741 int i;
1742
1743 /* ignore empty list */
1744
1745 if (a_zlst == (zoneList_t)NULL) {
1746 return (ZONE_STATE_INCOMPLETE);
1747 }
1748
1749 /* find the specified zone in the list */
1750
1751 for (i = 0; (i != a_zoneIndex) &&
1752 (a_zlst[i]._zlName != (char *)NULL); i++)
1753 ;
1754
1755 /* return error if the specified zone does not exist */
1756
1757 if (a_zlst[i]._zlName == (char *)NULL) {
1758 return (ZONE_STATE_INCOMPLETE);
1759 }
1760
1761 /* return selected zone's current kernel state */
1762
1763 _z_echoDebug(DBG_ZONES_GET_ZONE_STATE,
1764 a_zlst[i]._zlName ? a_zlst[i]._zlName : "",
1765 a_zlst[i]._zlCurrKernelStatus);
1766
1767 return (a_zlst[i]._zlCurrKernelStatus);
1768 }
1769
1770 /*
1771 * Name: z_zlist_get_original_state
1772 * Description: Return the original kernal state of the specified zone
1773 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1774 * a_zoneIndex - index into a_zlst of the zone to return the
1775 * Returns: zone_state_t
1776 * The original state of the specified zone is returned.
1777 * This is the state of the zone when the zoneList_t
1778 * object was first generated.
1779 */
1780
1781 zone_state_t
z_zlist_get_original_state(zoneList_t a_zlst,int a_zoneIndex)1782 z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex)
1783 {
1784 int i;
1785
1786 /* ignore empty list */
1787
1788 if (a_zlst == (zoneList_t)NULL) {
1789 return (ZONE_STATE_INCOMPLETE);
1790 }
1791
1792 /* find the specified zone in the list */
1793
1794 for (i = 0; (i != a_zoneIndex) &&
1795 (a_zlst[i]._zlName != (char *)NULL); i++)
1796 ;
1797
1798 /* return error if the specified zone does not exist */
1799
1800 if (a_zlst[i]._zlName == (char *)NULL) {
1801 return (ZONE_STATE_INCOMPLETE);
1802 }
1803
1804 /* return selected zone's original kernel state */
1805
1806 return (a_zlst[i]._zlOrigKernelStatus);
1807 }
1808
1809 /*
1810 * Name: z_zlist_get_scratch
1811 * Description: Determine name of scratch zone
1812 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1813 * a_zoneIndex - index into a_zlst of the zone to use
1814 * Return: char *
1815 * == NULL - zone name could not be determined
1816 * != NULL - pointer to string representing scratch zone
1817 * NOTE: Any name returned is placed in static storage that must
1818 * NEVER be free()ed by the caller.
1819 */
1820
1821 char *
z_zlist_get_scratch(zoneList_t a_zlst,int a_zoneIndex)1822 z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex)
1823 {
1824 int i;
1825
1826 /* ignore empty list */
1827
1828 if (a_zlst == NULL)
1829 return (NULL);
1830
1831 /* find the specified zone in the list */
1832
1833 for (i = 0; i != a_zoneIndex; i++) {
1834 if (a_zlst[i]._zlName == NULL)
1835 return (NULL);
1836 }
1837
1838 /* return selected zone's scratch name */
1839
1840 return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName :
1841 a_zlst[i]._zlScratchName);
1842 }
1843
1844 /*
1845 * Name: z_zlist_get_zonename
1846 * Description: Determine name of specified zone
1847 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1848 * a_zoneIndex - index into a_zlst of the zone to return the
1849 * Return: char *
1850 * == NULL - zone name could not be determined
1851 * != NULL - pointer to string representing zone name
1852 * NOTE: Any zoneList_t returned is placed in static storage that must
1853 * NEVER be free()ed by the caller.
1854 */
1855
1856 char *
z_zlist_get_zonename(zoneList_t a_zlst,int a_zoneIndex)1857 z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex)
1858 {
1859 int i;
1860
1861 /* ignore empty list */
1862
1863 if (a_zlst == (zoneList_t)NULL) {
1864 return ((char *)NULL);
1865 }
1866
1867 /* find the specified zone in the list */
1868
1869 for (i = 0; (i != a_zoneIndex) &&
1870 (a_zlst[i]._zlName != (char *)NULL); i++)
1871 ;
1872
1873 /* return error if the specified zone does not exist */
1874
1875 if (a_zlst[i]._zlName == (char *)NULL) {
1876 return (NULL);
1877 }
1878
1879 /* return selected zone's name */
1880
1881 return (a_zlst[i]._zlName);
1882 }
1883
1884 /*
1885 * Name: z_zlist_get_zonepath
1886 * Description: Determine zonepath of specified zone
1887 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1888 * a_zoneIndex - index into a_zlst of the zone to return
1889 * Return: char *
1890 * == NULL - zonepath could not be determined
1891 * != NULL - pointer to string representing zonepath
1892 * NOTE: Any zoneList_t returned is placed in static storage that must
1893 * NEVER be free()ed by the caller.
1894 */
1895
1896 char *
z_zlist_get_zonepath(zoneList_t a_zlst,int a_zoneIndex)1897 z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex)
1898 {
1899 int i;
1900
1901 /* ignore empty list */
1902
1903 if (a_zlst == (zoneList_t)NULL) {
1904 return ((char *)NULL);
1905 }
1906
1907 /* find the specified zone in the list */
1908
1909 for (i = 0; (i != a_zoneIndex) &&
1910 (a_zlst[i]._zlName != (char *)NULL); i++)
1911 ;
1912
1913 /* return error if the specified zone does not exist */
1914
1915 if (a_zlst[i]._zlName == (char *)NULL) {
1916 return (NULL);
1917 }
1918
1919 /* return selected zone's zonepath */
1920
1921 return (a_zlst[i]._zlPath);
1922 }
1923
1924 boolean_t
z_zlist_is_zone_runnable(zoneList_t a_zlst,int a_zoneIndex)1925 z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex)
1926 {
1927 int i;
1928
1929 /* if zones are not implemented, return error */
1930
1931 if (z_zones_are_implemented() == B_FALSE) {
1932 return (B_FALSE);
1933 }
1934
1935 /* ignore empty list */
1936
1937 if (a_zlst == (zoneList_t)NULL) {
1938 return (B_FALSE);
1939 }
1940
1941 /* find the specified zone in the list */
1942
1943 for (i = 0; (i != a_zoneIndex) &&
1944 (a_zlst[i]._zlName != (char *)NULL); i++)
1945 ;
1946
1947 /* return error if the specified zone does not exist */
1948
1949 if (a_zlst[i]._zlName == (char *)NULL) {
1950 return (B_FALSE);
1951 }
1952
1953 /* choose based on current state */
1954
1955 switch (a_zlst[i]._zlCurrKernelStatus) {
1956 case ZONE_STATE_RUNNING:
1957 case ZONE_STATE_MOUNTED:
1958 /* already running */
1959 return (B_TRUE);
1960
1961 case ZONE_STATE_INSTALLED:
1962 case ZONE_STATE_DOWN:
1963 case ZONE_STATE_READY:
1964 case ZONE_STATE_SHUTTING_DOWN:
1965 /* return false if the zone cannot be booted */
1966
1967 if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) {
1968 return (B_FALSE);
1969 }
1970
1971 return (B_TRUE);
1972
1973 case ZONE_STATE_CONFIGURED:
1974 case ZONE_STATE_INCOMPLETE:
1975 default:
1976 /* cannot transition (boot) these states */
1977 return (B_FALSE);
1978 }
1979 }
1980
1981 /*
1982 * Name: z_zlist_restore_zone_state
1983 * Description: Return the zone to the state it was originally in
1984 * Arguments: a_zlst - handle to zoneList_t object describing all zones
1985 * a_zoneIndex - index into a_zlst of the zone to return the
1986 * Returns: boolean_t
1987 * == B_TRUE - the zone's state has been restored
1988 * == B_FALSE - unable to transition the zone to its
1989 * original state
1990 */
1991
1992 boolean_t
z_zlist_restore_zone_state(zoneList_t a_zlst,int a_zoneIndex)1993 z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex)
1994 {
1995 int i;
1996
1997 /* ignore empty list */
1998
1999 if (a_zlst == (zoneList_t)NULL) {
2000 return (B_FALSE);
2001 }
2002
2003 /* find the specified zone in the list */
2004
2005 for (i = 0; (i != a_zoneIndex) &&
2006 (a_zlst[i]._zlName != (char *)NULL); i++)
2007 ;
2008
2009 /* return error if the specified zone does not exist */
2010
2011 if (a_zlst[i]._zlName == (char *)NULL) {
2012 return (B_FALSE);
2013 }
2014
2015 /* transition the zone back to its original state */
2016
2017 return (z_zlist_change_zone_state(a_zlst,
2018 a_zoneIndex, a_zlst[i]._zlOrigKernelStatus));
2019 }
2020
2021 /*
2022 * Name: z_zone_exec
2023 * Description: Execute a Unix command in a specified zone and return results
2024 * Arguments: a_zoneName - pointer to string representing the name of the zone
2025 * to execute the specified command in
2026 * a_path - pointer to string representing the full path *in the
2027 * non-global zone named by a_zoneName* of the Unix command
2028 * to be executed
2029 * a_argv[] - Pointer to array of character strings representing
2030 * the arguments to be passed to the Unix command. The list
2031 * must be termianted with an element that is (char *)NULL
2032 * NOTE: a_argv[0] is the "command name" passed to the command
2033 * a_stdoutPath - Pointer to string representing the path to a file
2034 * into which all output to "stdout" from the Unix command
2035 * is placed.
2036 * == (char *)NULL - leave stdout open and pass through
2037 * == "/dev/null" - discard stdout output
2038 * a_strerrPath - Pointer to string representing the path to a file
2039 * into which all output to "stderr" from the Unix command
2040 * is placed.
2041 * == (char *)NULL - leave stderr open and pass through
2042 * == "/dev/null" - discard stderr output
2043 * a_fds - Pointer to array of integers representing file
2044 * descriptors to remain open during the call - all
2045 * file descriptors above STDERR_FILENO not in this
2046 * list will be closed.
2047 * Returns: int
2048 * The return (exit) code from the specified Unix command
2049 * Special return codes:
2050 * -1 : failure to exec process
2051 * -2 : could not create contract for greenline
2052 * -3 : fork() failed
2053 * -4 : could not open stdout capture file
2054 * -5 : error from 'waitpid' other than EINTR
2055 * -6 : zones are not supported
2056 * NOTE: All file descriptores other than 0, 1 and 2 are closed except
2057 * for those file descriptors listed in the a_fds array.
2058 */
2059
2060 int
z_zone_exec(const char * a_zoneName,const char * a_path,char * a_argv[],char * a_stdoutPath,char * a_stderrPath,int * a_fds)2061 z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[],
2062 char *a_stdoutPath, char *a_stderrPath, int *a_fds)
2063 {
2064 int final_status;
2065 int lerrno;
2066 int status;
2067 int tmpl_fd;
2068 pid_t child_pid;
2069 pid_t result_pid;
2070 struct sigaction nact;
2071 struct sigaction oact;
2072 void (*funcSighup)();
2073 void (*funcSigint)();
2074
2075 /* if zones are not implemented, return TRUE */
2076
2077 if (z_zones_are_implemented() == B_FALSE) {
2078 return (-6); /* -6 : zones are not supported */
2079 }
2080
2081 if ((tmpl_fd = _zexec_init_template()) == -1) {
2082 _z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
2083 return (-2); /* -2 : could not create greenline contract */
2084 }
2085
2086 /*
2087 * hold SIGINT/SIGHUP signals and reset signal received counter;
2088 * after the fork1() the parent and child need to setup their respective
2089 * interrupt handling and release the hold on the signals
2090 */
2091
2092 (void) sighold(SIGINT);
2093 (void) sighold(SIGHUP);
2094
2095 _z_global_data._z_SigReceived = 0; /* no signals received */
2096
2097 /*
2098 * fork off a new process to execute command in;
2099 * fork1() is used instead of vfork() so the child process can
2100 * perform operations that would modify the parent process if
2101 * vfork() were used
2102 */
2103
2104 child_pid = fork1();
2105
2106 if (child_pid < 0) {
2107 /*
2108 * *************************************************************
2109 * fork failed!
2110 * *************************************************************
2111 */
2112
2113 (void) ct_tmpl_clear(tmpl_fd);
2114 (void) close(tmpl_fd);
2115 _z_program_error(ERR_FORK, strerror(errno));
2116
2117 /* release hold on signals */
2118
2119 (void) sigrelse(SIGHUP);
2120 (void) sigrelse(SIGINT);
2121
2122 return (-3); /* -3 : fork() failed */
2123 }
2124
2125 if (child_pid == 0) {
2126 int i;
2127
2128 /*
2129 * *************************************************************
2130 * This is the forked (child) process
2131 * *************************************************************
2132 */
2133
2134 (void) ct_tmpl_clear(tmpl_fd);
2135 (void) close(tmpl_fd);
2136
2137 /* reset any signals to default */
2138
2139 for (i = 0; i < NSIG; i++) {
2140 (void) sigset(i, SIG_DFL);
2141 }
2142
2143 /*
2144 * close all file descriptors not in the a_fds list
2145 */
2146
2147 (void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
2148
2149 /*
2150 * if a file for stdout is present, open the file and use the
2151 * file to capture stdout from the _zexec process
2152 */
2153
2154 if (a_stdoutPath != (char *)NULL) {
2155 int stdoutfd;
2156
2157 stdoutfd = open(a_stdoutPath,
2158 O_WRONLY|O_CREAT|O_TRUNC, 0600);
2159 if (stdoutfd < 0) {
2160 _z_program_error(ERR_CAPTURE_FILE, a_stdoutPath,
2161 strerror(errno));
2162 return (-4);
2163 }
2164
2165 (void) dup2(stdoutfd, STDOUT_FILENO);
2166 (void) close(stdoutfd);
2167 }
2168
2169 /*
2170 * if a file for stderr is present, open the file and use the
2171 * file to capture stderr from the _zexec process
2172 */
2173
2174 if (a_stderrPath != (char *)NULL) {
2175 int stderrfd;
2176
2177 stderrfd = open(a_stderrPath,
2178 O_WRONLY|O_CREAT|O_TRUNC, 0600);
2179 if (stderrfd < 0) {
2180 _z_program_error(ERR_CAPTURE_FILE, a_stderrPath,
2181 strerror(errno));
2182 return (-4);
2183 }
2184
2185 (void) dup2(stderrfd, STDERR_FILENO);
2186 (void) close(stderrfd);
2187 }
2188
2189 /* release all held signals */
2190
2191 (void) sigrelse(SIGHUP);
2192 (void) sigrelse(SIGINT);
2193
2194 /* execute command in the specified non-global zone */
2195
2196 _exit(_zexec(a_zoneName, a_path, a_argv));
2197 }
2198
2199 /*
2200 * *********************************************************************
2201 * This is the forking (parent) process
2202 * *********************************************************************
2203 */
2204
2205 /* register child process i.d. so signal handlers can pass signal on */
2206
2207 _z_global_data._z_ChildProcessId = child_pid;
2208
2209 /*
2210 * setup signal handlers for SIGINT and SIGHUP and release hold
2211 */
2212
2213 /* hook SIGINT to _z_sig_trap() */
2214
2215 nact.sa_handler = _z_sig_trap;
2216 nact.sa_flags = SA_RESTART;
2217 (void) sigemptyset(&nact.sa_mask);
2218
2219 if (sigaction(SIGINT, &nact, &oact) < 0) {
2220 funcSigint = SIG_DFL;
2221 } else {
2222 funcSigint = oact.sa_handler;
2223 }
2224
2225 /* hook SIGHUP to _z_sig_trap() */
2226
2227 nact.sa_handler = _z_sig_trap;
2228 nact.sa_flags = SA_RESTART;
2229 (void) sigemptyset(&nact.sa_mask);
2230
2231 if (sigaction(SIGHUP, &nact, &oact) < 0) {
2232 funcSighup = SIG_DFL;
2233 } else {
2234 funcSighup = oact.sa_handler;
2235 }
2236
2237 /* release hold on signals */
2238
2239 (void) sigrelse(SIGHUP);
2240 (void) sigrelse(SIGINT);
2241
2242 (void) ct_tmpl_clear(tmpl_fd);
2243 (void) close(tmpl_fd);
2244
2245 /*
2246 * wait for the process to exit, reap child exit status
2247 */
2248
2249 for (;;) {
2250 result_pid = waitpid(child_pid, &status, 0L);
2251 lerrno = (result_pid == -1 ? errno : 0);
2252
2253 /* break loop if child process status reaped */
2254
2255 if (result_pid != -1) {
2256 break;
2257 }
2258
2259 /* break loop if not interrupted out of waitpid */
2260
2261 if (errno != EINTR) {
2262 break;
2263 }
2264 }
2265
2266 /* reset child process i.d. so signal handlers do not pass signals on */
2267
2268 _z_global_data._z_ChildProcessId = -1;
2269
2270 /*
2271 * If the child process terminated due to a call to exit(), then
2272 * set results equal to the 8-bit exit status of the child process;
2273 * otherwise, set the exit status to "-1" indicating that the child
2274 * exited via a signal.
2275 */
2276
2277 if (WIFEXITED(status)) {
2278 final_status = WEXITSTATUS(status);
2279 if ((_z_global_data._z_SigReceived != 0) &&
2280 (final_status == 0)) {
2281 final_status = 1;
2282 }
2283 } else {
2284 final_status = -1; /* -1 : failure to exec process */
2285 }
2286
2287 /* determine proper exit code */
2288
2289 if (result_pid == -1) {
2290 final_status = -5; /* -5 : error from waitpid not EINTR */
2291 } else if (_z_global_data._z_SigReceived != 0) {
2292 final_status = -7; /* -7 : interrupt received */
2293 }
2294
2295 /*
2296 * reset signal handlers
2297 */
2298
2299 /* reset SIGINT */
2300
2301 nact.sa_handler = funcSigint;
2302 nact.sa_flags = SA_RESTART;
2303 (void) sigemptyset(&nact.sa_mask);
2304
2305 (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2306
2307 /* reset SIGHUP */
2308
2309 nact.sa_handler = funcSighup;
2310 nact.sa_flags = SA_RESTART;
2311 (void) sigemptyset(&nact.sa_mask);
2312
2313 (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2314
2315 /*
2316 * if signal received during command execution, interrupt
2317 * this process now.
2318 */
2319
2320 if (_z_global_data._z_SigReceived != 0) {
2321 (void) kill(getpid(), SIGINT);
2322 }
2323
2324 /* set errno and return */
2325
2326 errno = lerrno;
2327
2328 return (final_status);
2329 }
2330
2331 /*
2332 * Name: z_zones_are_implemented
2333 * Description: Determine if any zone operations can be performed
2334 * Arguments: void
2335 * Returns: boolean_t
2336 * == B_TRUE - zone operations are available
2337 * == B_FALSE - no zone operations can be done
2338 */
2339
2340 boolean_t
z_zones_are_implemented(void)2341 z_zones_are_implemented(void)
2342 {
2343 static boolean_t _zonesImplementedDetermined = B_FALSE;
2344 static boolean_t _zonesAreImplemented = B_FALSE;
2345
2346 /* if availability has not been determined, cache it now */
2347
2348 if (!_zonesImplementedDetermined) {
2349 _zonesImplementedDetermined = B_TRUE;
2350 _zonesAreImplemented = _z_zones_are_implemented();
2351 if (!_zonesAreImplemented) {
2352 _z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED);
2353 } else {
2354 _z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED);
2355 }
2356 }
2357
2358 return (_zonesAreImplemented);
2359 }
2360