Print this page
OS-200 need a better mechanism for storing persistent zone_did


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


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

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




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


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
















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


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























































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


2833                 (void) fprintf(stderr, gettext("The XML repository has "
2834                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2835                     "These must match, so fix the incorrect entry.\n"),
2836                     zonepath, checkpath);
2837                 zonecfg_fini_handle(handle);
2838                 return (Z_ERR);
2839         }
2840         if (cmd_num != CMD_ATTACH &&
2841             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2842                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2843                     "because of the above errors.\n"), zonepath);
2844                 return_code = Z_ERR;
2845         }
2846 
2847         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2848                 return_code = Z_ERR;
2849 
2850         if (cmd_num == CMD_READY || cmd_num == CMD_BOOT) {
2851                 int vcommit = 0, obscommit = 0;
2852 
2853 #if 0 /* XXX KEBE not yet */
2854                 vcommit = verify_fix_did(handle);
2855 #endif /* XXX KEBE not yet */
2856                 obscommit = zonecfg_fix_obsolete(handle);
2857 
2858                 if (vcommit || obscommit)
2859                         if (zonecfg_save(handle) != Z_OK)
2860                                 (void) fprintf(stderr, gettext("Could not save "
2861                                     "updated configuration.\n"));
2862         }
2863 
2864         zonecfg_fini_handle(handle);
2865         if (return_code == Z_ERR)
2866                 (void) fprintf(stderr,
2867                     gettext("%s: zone %s failed to verify\n"),
2868                     execname, target_zone);
2869         return (return_code);
2870 }
2871 
2872 static int
2873 verify_func(int argc, char *argv[])
2874 {
2875         int arg;




  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;


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) {


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;