Print this page
OS-200 need a better mechanism for storing persistent zone_did
Small comment-out because we don't include OS-200
OS-4019 zoneadm is slow with 1000s of zones
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-3429 Expose zone's init exit status
OS-399 zone phys. mem. cap should be a rctl and have associated kstat


   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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2015 by Delphix. All rights reserved.

  26  */
  27 
  28 /*
  29  * zoneadm is a command interpreter for zone administration.  It is all in
  30  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
  31  * main() calls parse_and_run() which calls cmd_match(), then invokes the
  32  * appropriate command's handler function.  The rest of the program is the
  33  * handler functions and their helper functions.
  34  *
  35  * Some of the helper functions are used largely to simplify I18N: reducing
  36  * the need for translation notes.  This is particularly true of many of
  37  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
  38  * than zerror(gettext("foo failed")) with a translation note indicating
  39  * that "foo" need not be translated.
  40  */
  41 
  42 #include <stdio.h>
  43 #include <errno.h>
  44 #include <unistd.h>
  45 #include <signal.h>


  84 #include <pwd.h>
  85 #include <auth_list.h>
  86 #include <auth_attr.h>
  87 #include <secdb.h>
  88 
  89 #include "zoneadm.h"
  90 
  91 #define MAXARGS 8
  92 #define SOURCE_ZONE (CMD_MAX + 1)
  93 
  94 /* Reflects kernel zone entries */
  95 typedef struct zone_entry {
  96         zoneid_t        zid;
  97         char            zname[ZONENAME_MAX];
  98         char            *zstate_str;
  99         zone_state_t    zstate_num;
 100         char            zbrand[MAXNAMELEN];
 101         char            zroot[MAXPATHLEN];
 102         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 103         zone_iptype_t   ziptype;

 104 } zone_entry_t;
 105 
 106 #define CLUSTER_BRAND_NAME      "cluster"
 107 
 108 static zone_entry_t *zents;
 109 static size_t nzents;
 110 
 111 #define LOOPBACK_IF     "lo0"
 112 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 113 
 114 struct net_if {
 115         char    *name;
 116         int     af;
 117 };
 118 
 119 /* 0755 is the default directory mode. */
 120 #define DEFAULT_DIR_MODE \
 121         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 122 
 123 struct cmd {


 426         char *ip_type_str;
 427 
 428         /* Skip a zone that shutdown while we were collecting data. */
 429         if (zent->zname[0] == '\0')
 430                 return;
 431 
 432         if (zent->ziptype == ZS_EXCLUSIVE)
 433                 ip_type_str = "excl";
 434         else
 435                 ip_type_str = "shared";
 436 
 437         assert(!(verbose && parsable));
 438         if (firsttime && verbose) {
 439                 firsttime = B_FALSE;
 440                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 441                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 442                     "IP");
 443         }
 444         if (!verbose) {
 445                 char *cp, *clim;

 446 
 447                 if (!parsable) {
 448                         (void) printf("%s\n", zent->zname);
 449                         return;
 450                 }
 451                 if (zent->zid == ZONE_ID_UNDEFINED)
 452                         (void) printf("-");
 453                 else
 454                         (void) printf("%lu", zent->zid);
 455                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 456                 cp = zent->zroot;
 457                 while ((clim = strchr(cp, ':')) != NULL) {
 458                         (void) printf("%.*s\\:", clim - cp, cp);
 459                         cp = clim + 1;
 460                 }
 461                 (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 462                     ip_type_str);




 463                 return;
 464         }
 465         if (zent->zstate_str != NULL) {
 466                 if (zent->zid == ZONE_ID_UNDEFINED)
 467                         (void) printf("%*s", ZONEID_WIDTH, "-");
 468                 else
 469                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 470                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 471                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 472         }
 473 }
 474 
 475 static int
 476 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 477 {
 478         char root[MAXPATHLEN], *cp;
 479         int err;
 480         uuid_t uuid;
 481         zone_dochandle_t handle;
 482 


 537          */
 538         if (getzoneid() != GLOBAL_ZONEID) {
 539                 assert(is_system_labeled() != 0);
 540                 (void) strlcpy(zent->zbrand, default_brand,
 541                     sizeof (zent->zbrand));
 542         } else if (zone_get_brand(zent->zname, zent->zbrand,
 543             sizeof (zent->zbrand)) != Z_OK) {
 544                 zperror2(zent->zname, gettext("could not get brand name"));
 545                 return (Z_ERR);
 546         }
 547 
 548         /*
 549          * Get ip type of the zone.
 550          * Note for global zone, ZS_SHARED is set always.
 551          */
 552         if (zid == GLOBAL_ZONEID) {
 553                 zent->ziptype = ZS_SHARED;
 554                 return (Z_OK);
 555         }
 556 
















 557         /*
 558          * There is a race condition where the zone could boot while
 559          * we're walking the index file.  In this case the zone state
 560          * could be seen as running from the call above, but the zoneid
 561          * would be undefined.
 562          *
 563          * There is also a race condition where the zone could shutdown after
 564          * we got its running state above.  This is also not an error and
 565          * we fall back to getting the ziptype from the zone configuration.
 566          */
 567         if (zent->zstate_num == ZONE_STATE_RUNNING &&
 568             zid != ZONE_ID_UNDEFINED) {
 569                 ushort_t flags;
 570 
 571                 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 572                     sizeof (flags)) >= 0) {
 573                         if (flags & ZF_NET_EXCL)
 574                                 zent->ziptype = ZS_EXCLUSIVE;
 575                         else
 576                                 zent->ziptype = ZS_SHARED;
 577                         return (Z_OK);
 578                 }
 579         }
 580 
 581         if ((handle = zonecfg_init_handle()) == NULL) {
 582                 zperror2(zent->zname, gettext("could not init handle"));
 583                 return (Z_ERR);
 584         }
 585         if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
 586                 zperror2(zent->zname, gettext("could not get handle"));
 587                 zonecfg_fini_handle(handle);
 588                 return (Z_ERR);
 589         }
 590 
 591         if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
 592                 zperror2(zent->zname, gettext("could not get ip-type"));
 593                 zonecfg_fini_handle(handle);
 594                 return (Z_ERR);
 595         }
 596         zonecfg_fini_handle(handle);
 597 
 598         return (Z_OK);
 599 }
 600 
 601 /*
 602  * fetch_zents() calls zone_list(2) to find out how many zones are running
 603  * (which is stored in the global nzents), then calls zone_list(2) again
 604  * to fetch the list of running zones (stored in the global zents).  This
 605  * function may be called multiple times, so if zents is already set, we
 606  * return immediately to save work.
 607  *
 608  * Note that the data about running zones can change while this function
 609  * is running, so its possible that the list of zones will have empty slots
 610  * at the end.
 611  */
 612 
 613 static int
 614 fetch_zents(void)
 615 {
 616         zoneid_t *zids = NULL;


 749                 if (i < nzents) {
 750                         free(name);
 751                         continue;
 752                 }
 753                 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
 754                         free(name);
 755                         continue;
 756                 }
 757                 free(name);
 758                 if (zent.zstate_num >= min_state)
 759                         zone_print(&zent, verbose, parsable);
 760         }
 761         endzoneent(cookie);
 762         return (Z_OK);
 763 }
 764 
 765 /*
 766  * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
 767  */
 768 static zone_entry_t *
 769 lookup_running_zone(const char *str)
 770 {
 771         int i;

 772 
 773         if (fetch_zents() != Z_OK)
 774                 return (NULL);
 775 
 776         for (i = 0; i < nzents; i++) {
 777                 if (strcmp(str, zents[i].zname) == 0)
 778                         return (&zents[i]);
 779         }
 780         return (NULL);






 781 }
 782 
 783 /*
 784  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
 785  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
 786  */
 787 static boolean_t
 788 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
 789 {
 790         char *str;
 791 
 792         assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
 793             bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
 794             bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
 795         /*
 796          * TRANSLATION_NOTE
 797          * The strings below will be used as part of a larger message,
 798          * either:
 799          * (file name) must be (owner|group|world) (read|writ|execut)able
 800          * or


2766                 return_code = Z_ERR;
2767         if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2768                 return_code = Z_ERR;
2769         if (!in_alt_root && verify_datasets(handle) != Z_OK)
2770                 return_code = Z_ERR;
2771 
2772         /*
2773          * As the "mount" command is used for patching/upgrading of zones
2774          * or other maintenance processes, the zone's privilege set is not
2775          * checked in this case.  Instead, the default, safe set of
2776          * privileges will be used when this zone is created in the
2777          * kernel.
2778          */
2779         if (!in_alt_root && cmd_num != CMD_MOUNT &&
2780             verify_limitpriv(handle) != Z_OK)
2781                 return_code = Z_ERR;
2782 
2783         return (return_code);
2784 }
2785 























































2786 static int
2787 verify_details(int cmd_num, char *argv[])
2788 {
2789         zone_dochandle_t handle;
2790         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2791         int return_code = Z_OK;
2792         int err;
2793 
2794         if ((handle = zonecfg_init_handle()) == NULL) {
2795                 zperror(cmd_to_str(cmd_num), B_TRUE);
2796                 return (Z_ERR);
2797         }
2798         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2799                 errno = err;
2800                 zperror(cmd_to_str(cmd_num), B_TRUE);
2801                 zonecfg_fini_handle(handle);
2802                 return (Z_ERR);
2803         }
2804         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2805             Z_OK) {


2825                  * TRANSLATION_NOTE
2826                  * XML and zonepath are literals that should not be translated.
2827                  */
2828                 (void) fprintf(stderr, gettext("The XML repository has "
2829                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2830                     "These must match, so fix the incorrect entry.\n"),
2831                     zonepath, checkpath);
2832                 zonecfg_fini_handle(handle);
2833                 return (Z_ERR);
2834         }
2835         if (cmd_num != CMD_ATTACH &&
2836             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2837                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2838                     "because of the above errors.\n"), zonepath);
2839                 return_code = Z_ERR;
2840         }
2841 
2842         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2843                 return_code = Z_ERR;
2844 












2845         zonecfg_fini_handle(handle);
2846         if (return_code == Z_ERR)
2847                 (void) fprintf(stderr,
2848                     gettext("%s: zone %s failed to verify\n"),
2849                     execname, target_zone);
2850         return (return_code);
2851 }
2852 
2853 static int
2854 verify_func(int argc, char *argv[])
2855 {
2856         int arg;
2857 
2858         optind = 0;
2859         if ((arg = getopt(argc, argv, "?")) != EOF) {
2860                 switch (arg) {
2861                 case '?':
2862                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2863                         return (optopt == '?' ? Z_OK : Z_USAGE);
2864                 default:


3848  * If the "all" parameter is true then we should remove the whole zonepath
3849  * even if it has non-standard files/directories in it.  This can be used when
3850  * we need to cleanup after moving the zonepath across file systems.
3851  *
3852  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
3853  * and not the shell.
3854  */
3855 static int
3856 cleanup_zonepath(char *zonepath, boolean_t all)
3857 {
3858         int             status;
3859         int             i;
3860         boolean_t       non_std = B_FALSE;
3861         struct dirent   *dp;
3862         DIR             *dirp;
3863                         /*
3864                          * The SUNWattached.xml file is expected since it might
3865                          * exist if the zone was force-attached after a
3866                          * migration.
3867                          */
3868         char            *std_entries[] = {"dev", "lu", "root",
3869                             "SUNWattached.xml", NULL};
3870                         /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
3871         char            cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
3872 
3873         /*
3874          * We shouldn't need these checks but lets be paranoid since we
3875          * could blow away the whole system here if we got the wrong zonepath.
3876          */
3877         if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
3878                 (void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
3879                 return (Z_INVAL);
3880         }
3881 
3882         /*
3883          * If the dirpath is already gone (maybe it was manually removed) then
3884          * we just return Z_OK so that the cleanup is successful.
3885          */
3886         if ((dirp = opendir(zonepath)) == NULL)
3887                 return (Z_OK);
3888 
3889         /*
3890          * Look through the zonepath directory to see if there are any
3891          * non-standard files/dirs.  Also skip .zfs since that might be


5358 /*
5359  * This is an undocumented interface which is currently only used to apply
5360  * the global zone resource management settings when the system boots.
5361  * This function does not yet properly handle updating a running system so
5362  * any projects running in the zone would be trashed if this function
5363  * were to run after the zone had booted.  It also does not reset any
5364  * rctl settings that were removed from zonecfg.  There is still work to be
5365  * done before we can properly support dynamically updating the resource
5366  * management settings for a running zone (global or non-global).  Thus, this
5367  * functionality is undocumented for now.
5368  */
5369 /* ARGSUSED */
5370 static int
5371 apply_func(int argc, char *argv[])
5372 {
5373         int err;
5374         int res = Z_OK;
5375         priv_set_t *privset;
5376         zoneid_t zoneid;
5377         zone_dochandle_t handle;
5378         struct zone_mcaptab mcap;
5379         char pool_err[128];
5380 
5381         zoneid = getzoneid();
5382 
5383         if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
5384             target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
5385                 return (usage(B_FALSE));
5386 
5387         if ((privset = priv_allocset()) == NULL) {
5388                 zerror(gettext("%s failed"), "priv_allocset");
5389                 return (Z_ERR);
5390         }
5391 
5392         if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5393                 zerror(gettext("%s failed"), "getppriv");
5394                 priv_freeset(privset);
5395                 return (Z_ERR);
5396         }
5397 
5398         if (priv_isfullset(privset) == B_FALSE) {


5449                                             pool_err);
5450                                 else
5451                                         zerror(gettext("could not bind zone to "
5452                                             "temporary pool: %s"),
5453                                             zonecfg_strerror(err));
5454                                 res = Z_ERR;
5455                         }
5456 
5457                         if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
5458                             sizeof (pool_err))) != Z_OK) {
5459                                 if (err == Z_POOL || err == Z_POOL_BIND)
5460                                         zerror("%s: %s", zonecfg_strerror(err),
5461                                             pool_err);
5462                                 else
5463                                         zerror("%s", zonecfg_strerror(err));
5464                         }
5465                 }
5466         }
5467 
5468         /*
5469          * If a memory cap is configured, set the cap in the kernel using
5470          * zone_setattr() and make sure the rcapd SMF service is enabled.
5471          */
5472         if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
5473                 uint64_t num;
5474                 char smf_err[128];
5475 
5476                 num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
5477                 if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
5478                         zerror(gettext("could not set zone memory cap"));
5479                         res = Z_ERR;
5480                 }
5481 
5482                 if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
5483                         zerror(gettext("enabling system/rcap service failed: "
5484                             "%s"), smf_err);
5485                         res = Z_ERR;
5486                 }
5487         }
5488 
5489         zonecfg_fini_handle(handle);
5490 
5491         return (res);
5492 }
5493 
5494 /*
5495  * This is an undocumented interface that is invoked by the zones SMF service
5496  * for installed zones that won't automatically boot.
5497  */
5498 /* ARGSUSED */
5499 static int
5500 sysboot_func(int argc, char *argv[])
5501 {




   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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2015 by Delphix. All rights reserved.
  26  * Copyright 2015, Joyent Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * zoneadm is a command interpreter for zone administration.  It is all in
  31  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
  32  * main() calls parse_and_run() which calls cmd_match(), then invokes the
  33  * appropriate command's handler function.  The rest of the program is the
  34  * handler functions and their helper functions.
  35  *
  36  * Some of the helper functions are used largely to simplify I18N: reducing
  37  * the need for translation notes.  This is particularly true of many of
  38  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
  39  * than zerror(gettext("foo failed")) with a translation note indicating
  40  * that "foo" need not be translated.
  41  */
  42 
  43 #include <stdio.h>
  44 #include <errno.h>
  45 #include <unistd.h>
  46 #include <signal.h>


  85 #include <pwd.h>
  86 #include <auth_list.h>
  87 #include <auth_attr.h>
  88 #include <secdb.h>
  89 
  90 #include "zoneadm.h"
  91 
  92 #define MAXARGS 8
  93 #define SOURCE_ZONE (CMD_MAX + 1)
  94 
  95 /* Reflects kernel zone entries */
  96 typedef struct zone_entry {
  97         zoneid_t        zid;
  98         char            zname[ZONENAME_MAX];
  99         char            *zstate_str;
 100         zone_state_t    zstate_num;
 101         char            zbrand[MAXNAMELEN];
 102         char            zroot[MAXPATHLEN];
 103         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 104         zone_iptype_t   ziptype;
 105         zoneid_t        zdid;
 106 } zone_entry_t;
 107 
 108 #define CLUSTER_BRAND_NAME      "cluster"
 109 
 110 static zone_entry_t *zents;
 111 static size_t nzents;
 112 
 113 #define LOOPBACK_IF     "lo0"
 114 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 115 
 116 struct net_if {
 117         char    *name;
 118         int     af;
 119 };
 120 
 121 /* 0755 is the default directory mode. */
 122 #define DEFAULT_DIR_MODE \
 123         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 124 
 125 struct cmd {


 428         char *ip_type_str;
 429 
 430         /* Skip a zone that shutdown while we were collecting data. */
 431         if (zent->zname[0] == '\0')
 432                 return;
 433 
 434         if (zent->ziptype == ZS_EXCLUSIVE)
 435                 ip_type_str = "excl";
 436         else
 437                 ip_type_str = "shared";
 438 
 439         assert(!(verbose && parsable));
 440         if (firsttime && verbose) {
 441                 firsttime = B_FALSE;
 442                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 443                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 444                     "IP");
 445         }
 446         if (!verbose) {
 447                 char *cp, *clim;
 448                 char zdid[80];
 449 
 450                 if (!parsable) {
 451                         (void) printf("%s\n", zent->zname);
 452                         return;
 453                 }
 454                 if (zent->zid == ZONE_ID_UNDEFINED)
 455                         (void) printf("-");
 456                 else
 457                         (void) printf("%lu", zent->zid);
 458                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 459                 cp = zent->zroot;
 460                 while ((clim = strchr(cp, ':')) != NULL) {
 461                         (void) printf("%.*s\\:", clim - cp, cp);
 462                         cp = clim + 1;
 463                 }
 464                 if (zent->zdid == -1)
 465                         zdid[0] = '\0';
 466                 else
 467                         (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid);
 468                 (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 469                     ip_type_str, zdid);
 470                 return;
 471         }
 472         if (zent->zstate_str != NULL) {
 473                 if (zent->zid == ZONE_ID_UNDEFINED)
 474                         (void) printf("%*s", ZONEID_WIDTH, "-");
 475                 else
 476                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 477                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 478                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 479         }
 480 }
 481 
 482 static int
 483 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 484 {
 485         char root[MAXPATHLEN], *cp;
 486         int err;
 487         uuid_t uuid;
 488         zone_dochandle_t handle;
 489 


 544          */
 545         if (getzoneid() != GLOBAL_ZONEID) {
 546                 assert(is_system_labeled() != 0);
 547                 (void) strlcpy(zent->zbrand, default_brand,
 548                     sizeof (zent->zbrand));
 549         } else if (zone_get_brand(zent->zname, zent->zbrand,
 550             sizeof (zent->zbrand)) != Z_OK) {
 551                 zperror2(zent->zname, gettext("could not get brand name"));
 552                 return (Z_ERR);
 553         }
 554 
 555         /*
 556          * Get ip type of the zone.
 557          * Note for global zone, ZS_SHARED is set always.
 558          */
 559         if (zid == GLOBAL_ZONEID) {
 560                 zent->ziptype = ZS_SHARED;
 561                 return (Z_OK);
 562         }
 563 
 564         if ((handle = zonecfg_init_handle()) == NULL) {
 565                 zperror2(zent->zname, gettext("could not init handle"));
 566                 return (Z_ERR);
 567         }
 568         if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
 569                 zperror2(zent->zname, gettext("could not get handle"));
 570                 zonecfg_fini_handle(handle);
 571                 return (Z_ERR);
 572         }
 573 
 574         if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
 575                 zperror2(zent->zname, gettext("could not get ip-type"));
 576                 zonecfg_fini_handle(handle);
 577                 return (Z_ERR);
 578         }
 579 
 580         /*
 581          * There is a race condition where the zone could boot while
 582          * we're walking the index file.  In this case the zone state
 583          * could be seen as running from the call above, but the zoneid
 584          * would be undefined.
 585          *
 586          * There is also a race condition where the zone could shutdown after
 587          * we got its running state above.  This is also not an error and
 588          * we fall back to getting the ziptype from the zone configuration.
 589          */
 590         if (zent->zstate_num == ZONE_STATE_RUNNING &&
 591             zid != ZONE_ID_UNDEFINED) {
 592                 ushort_t flags;
 593 
 594                 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 595                     sizeof (flags)) >= 0) {
 596                         if (flags & ZF_NET_EXCL)
 597                                 zent->ziptype = ZS_EXCLUSIVE;
 598                         else
 599                                 zent->ziptype = ZS_SHARED;

 600                 }
 601         }
 602 
 603         zent->zdid = zonecfg_get_did(handle);








 604 


 605         zonecfg_fini_handle(handle);



 606 
 607         return (Z_OK);
 608 }
 609 
 610 /*
 611  * fetch_zents() calls zone_list(2) to find out how many zones are running
 612  * (which is stored in the global nzents), then calls zone_list(2) again
 613  * to fetch the list of running zones (stored in the global zents).  This
 614  * function may be called multiple times, so if zents is already set, we
 615  * return immediately to save work.
 616  *
 617  * Note that the data about running zones can change while this function
 618  * is running, so its possible that the list of zones will have empty slots
 619  * at the end.
 620  */
 621 
 622 static int
 623 fetch_zents(void)
 624 {
 625         zoneid_t *zids = NULL;


 758                 if (i < nzents) {
 759                         free(name);
 760                         continue;
 761                 }
 762                 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
 763                         free(name);
 764                         continue;
 765                 }
 766                 free(name);
 767                 if (zent.zstate_num >= min_state)
 768                         zone_print(&zent, verbose, parsable);
 769         }
 770         endzoneent(cookie);
 771         return (Z_OK);
 772 }
 773 
 774 /*
 775  * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
 776  */
 777 static zone_entry_t *
 778 lookup_running_zone(const char *name)
 779 {
 780         zoneid_t zid;
 781         zone_entry_t *zent;
 782 
 783         if ((zid = getzoneidbyname(name)) == -1)
 784                 return (NULL);
 785 
 786         if ((zent = malloc(sizeof (zone_entry_t))) == NULL)



 787                 return (NULL);
 788 
 789         if (lookup_zone_info(name, zid, zent) != Z_OK) {
 790                 free(zent);
 791                 return (NULL);
 792         }
 793         return (zent);
 794 }
 795 
 796 /*
 797  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
 798  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
 799  */
 800 static boolean_t
 801 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
 802 {
 803         char *str;
 804 
 805         assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
 806             bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
 807             bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
 808         /*
 809          * TRANSLATION_NOTE
 810          * The strings below will be used as part of a larger message,
 811          * either:
 812          * (file name) must be (owner|group|world) (read|writ|execut)able
 813          * or


2779                 return_code = Z_ERR;
2780         if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2781                 return_code = Z_ERR;
2782         if (!in_alt_root && verify_datasets(handle) != Z_OK)
2783                 return_code = Z_ERR;
2784 
2785         /*
2786          * As the "mount" command is used for patching/upgrading of zones
2787          * or other maintenance processes, the zone's privilege set is not
2788          * checked in this case.  Instead, the default, safe set of
2789          * privileges will be used when this zone is created in the
2790          * kernel.
2791          */
2792         if (!in_alt_root && cmd_num != CMD_MOUNT &&
2793             verify_limitpriv(handle) != Z_OK)
2794                 return_code = Z_ERR;
2795 
2796         return (return_code);
2797 }
2798 
2799 /*
2800  * Called when readying or booting a zone.  We double check that the zone's
2801  * debug ID is set and is unique.  This covers the case of pre-existing zones
2802  * with no ID.  Also, its possible that a zone was migrated to this host
2803  * and as a result it has a duplicate ID.  In this case we preserve the ID
2804  * of the first zone we match on in the index file (since it was there before
2805  * the current zone) and we assign a new unique ID to the current zone.
2806  * Return true if we assigned a new ID, indicating that the zone configuration
2807  * needs to be saved.
2808  */
2809 static boolean_t
2810 verify_fix_did(zone_dochandle_t handle)
2811 {
2812         zoneid_t mydid;
2813         zone_entry_t zent;
2814         FILE *cookie;
2815         char *name;
2816         boolean_t fix = B_FALSE;
2817 
2818         mydid = zonecfg_get_did(handle);
2819         if (mydid == -1) {
2820                 zonecfg_set_did(handle);
2821                 return (B_TRUE);
2822         }
2823 
2824         /* Get the full list of zones from the configuration. */
2825         cookie = setzoneent();
2826         while ((name = getzoneent(cookie)) != NULL) {
2827                 if (strcmp(target_zone, name) == 0) {
2828                         free(name);
2829                         break;  /* Once we find our entry, stop. */
2830                 }
2831 
2832                 if (strcmp(name, "global") == 0 ||
2833                     lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
2834                         free(name);
2835                         continue;
2836                 }
2837 
2838                 free(name);
2839                 if (zent.zdid == mydid) {
2840                         fix = B_TRUE;
2841                         break;
2842                 }
2843         }
2844         endzoneent(cookie);
2845 
2846         if (fix) {
2847                 zonecfg_set_did(handle);
2848                 return (B_TRUE);
2849         }
2850 
2851         return (B_FALSE);
2852 }
2853 
2854 static int
2855 verify_details(int cmd_num, char *argv[])
2856 {
2857         zone_dochandle_t handle;
2858         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2859         int return_code = Z_OK;
2860         int err;
2861 
2862         if ((handle = zonecfg_init_handle()) == NULL) {
2863                 zperror(cmd_to_str(cmd_num), B_TRUE);
2864                 return (Z_ERR);
2865         }
2866         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2867                 errno = err;
2868                 zperror(cmd_to_str(cmd_num), B_TRUE);
2869                 zonecfg_fini_handle(handle);
2870                 return (Z_ERR);
2871         }
2872         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2873             Z_OK) {


2893                  * TRANSLATION_NOTE
2894                  * XML and zonepath are literals that should not be translated.
2895                  */
2896                 (void) fprintf(stderr, gettext("The XML repository has "
2897                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2898                     "These must match, so fix the incorrect entry.\n"),
2899                     zonepath, checkpath);
2900                 zonecfg_fini_handle(handle);
2901                 return (Z_ERR);
2902         }
2903         if (cmd_num != CMD_ATTACH &&
2904             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2905                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2906                     "because of the above errors.\n"), zonepath);
2907                 return_code = Z_ERR;
2908         }
2909 
2910         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2911                 return_code = Z_ERR;
2912 
2913         if (cmd_num == CMD_READY || cmd_num == CMD_BOOT) {
2914                 int vcommit = 0, obscommit = 0;
2915 
2916                 vcommit = verify_fix_did(handle);
2917                 obscommit = zonecfg_fix_obsolete(handle);
2918 
2919                 if (vcommit || obscommit)
2920                         if (zonecfg_save(handle) != Z_OK)
2921                                 (void) fprintf(stderr, gettext("Could not save "
2922                                     "updated configuration.\n"));
2923         }
2924 
2925         zonecfg_fini_handle(handle);
2926         if (return_code == Z_ERR)
2927                 (void) fprintf(stderr,
2928                     gettext("%s: zone %s failed to verify\n"),
2929                     execname, target_zone);
2930         return (return_code);
2931 }
2932 
2933 static int
2934 verify_func(int argc, char *argv[])
2935 {
2936         int arg;
2937 
2938         optind = 0;
2939         if ((arg = getopt(argc, argv, "?")) != EOF) {
2940                 switch (arg) {
2941                 case '?':
2942                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2943                         return (optopt == '?' ? Z_OK : Z_USAGE);
2944                 default:


3928  * If the "all" parameter is true then we should remove the whole zonepath
3929  * even if it has non-standard files/directories in it.  This can be used when
3930  * we need to cleanup after moving the zonepath across file systems.
3931  *
3932  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
3933  * and not the shell.
3934  */
3935 static int
3936 cleanup_zonepath(char *zonepath, boolean_t all)
3937 {
3938         int             status;
3939         int             i;
3940         boolean_t       non_std = B_FALSE;
3941         struct dirent   *dp;
3942         DIR             *dirp;
3943                         /*
3944                          * The SUNWattached.xml file is expected since it might
3945                          * exist if the zone was force-attached after a
3946                          * migration.
3947                          */
3948         char            *std_entries[] = {"dev", "lastexited", "logs", "lu",
3949                             "root", "SUNWattached.xml", NULL};
3950                         /* (MAXPATHLEN * 5) is for the 5 std_entries dirs */
3951         char            cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 5) + 64];
3952 
3953         /*
3954          * We shouldn't need these checks but lets be paranoid since we
3955          * could blow away the whole system here if we got the wrong zonepath.
3956          */
3957         if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
3958                 (void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
3959                 return (Z_INVAL);
3960         }
3961 
3962         /*
3963          * If the dirpath is already gone (maybe it was manually removed) then
3964          * we just return Z_OK so that the cleanup is successful.
3965          */
3966         if ((dirp = opendir(zonepath)) == NULL)
3967                 return (Z_OK);
3968 
3969         /*
3970          * Look through the zonepath directory to see if there are any
3971          * non-standard files/dirs.  Also skip .zfs since that might be


5438 /*
5439  * This is an undocumented interface which is currently only used to apply
5440  * the global zone resource management settings when the system boots.
5441  * This function does not yet properly handle updating a running system so
5442  * any projects running in the zone would be trashed if this function
5443  * were to run after the zone had booted.  It also does not reset any
5444  * rctl settings that were removed from zonecfg.  There is still work to be
5445  * done before we can properly support dynamically updating the resource
5446  * management settings for a running zone (global or non-global).  Thus, this
5447  * functionality is undocumented for now.
5448  */
5449 /* ARGSUSED */
5450 static int
5451 apply_func(int argc, char *argv[])
5452 {
5453         int err;
5454         int res = Z_OK;
5455         priv_set_t *privset;
5456         zoneid_t zoneid;
5457         zone_dochandle_t handle;
5458         uint64_t mcap;
5459         char pool_err[128];
5460 
5461         zoneid = getzoneid();
5462 
5463         if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
5464             target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
5465                 return (usage(B_FALSE));
5466 
5467         if ((privset = priv_allocset()) == NULL) {
5468                 zerror(gettext("%s failed"), "priv_allocset");
5469                 return (Z_ERR);
5470         }
5471 
5472         if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5473                 zerror(gettext("%s failed"), "getppriv");
5474                 priv_freeset(privset);
5475                 return (Z_ERR);
5476         }
5477 
5478         if (priv_isfullset(privset) == B_FALSE) {


5529                                             pool_err);
5530                                 else
5531                                         zerror(gettext("could not bind zone to "
5532                                             "temporary pool: %s"),
5533                                             zonecfg_strerror(err));
5534                                 res = Z_ERR;
5535                         }
5536 
5537                         if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
5538                             sizeof (pool_err))) != Z_OK) {
5539                                 if (err == Z_POOL || err == Z_POOL_BIND)
5540                                         zerror("%s: %s", zonecfg_strerror(err),
5541                                             pool_err);
5542                                 else
5543                                         zerror("%s", zonecfg_strerror(err));
5544                         }
5545                 }
5546         }
5547 
5548         /*
5549          * If a memory cap is configured, make sure the rcapd SMF service is
5550          * enabled.
5551          */
5552         if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &mcap) == Z_OK) {

5553                 char smf_err[128];
5554 






5555                 if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
5556                         zerror(gettext("enabling system/rcap service failed: "
5557                             "%s"), smf_err);
5558                         res = Z_ERR;
5559                 }
5560         }
5561 
5562         zonecfg_fini_handle(handle);
5563 
5564         return (res);
5565 }
5566 
5567 /*
5568  * This is an undocumented interface that is invoked by the zones SMF service
5569  * for installed zones that won't automatically boot.
5570  */
5571 /* ARGSUSED */
5572 static int
5573 sysboot_func(int argc, char *argv[])
5574 {