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