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