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 }