xref: /titanic_41/usr/src/cmd/zoneadm/zoneadm.c (revision 058561cbaa119a6f2659bc27ef343e1b47266bb2)
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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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>
47 #include <stdarg.h>
48 #include <ctype.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <wait.h>
52 #include <zone.h>
53 #include <priv.h>
54 #include <locale.h>
55 #include <libintl.h>
56 #include <libzonecfg.h>
57 #include <bsm/adt.h>
58 #include <sys/brand.h>
59 #include <sys/param.h>
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <sys/statvfs.h>
63 #include <assert.h>
64 #include <sys/sockio.h>
65 #include <sys/mntent.h>
66 #include <limits.h>
67 #include <dirent.h>
68 #include <uuid/uuid.h>
69 
70 #include <fcntl.h>
71 #include <door.h>
72 #include <macros.h>
73 #include <libgen.h>
74 #include <fnmatch.h>
75 #include <sys/modctl.h>
76 #include <libbrand.h>
77 #include <libscf.h>
78 #include <procfs.h>
79 
80 #include <pool.h>
81 #include <sys/pool.h>
82 #include <sys/priocntl.h>
83 #include <sys/fsspriocntl.h>
84 
85 #include "zoneadm.h"
86 
87 #define	MAXARGS	8
88 
89 /* Reflects kernel zone entries */
90 typedef struct zone_entry {
91 	zoneid_t	zid;
92 	char		zname[ZONENAME_MAX];
93 	char		*zstate_str;
94 	zone_state_t	zstate_num;
95 	char		zbrand[MAXNAMELEN];
96 	char		zroot[MAXPATHLEN];
97 	char		zuuid[UUID_PRINTABLE_STRING_LENGTH];
98 	zone_iptype_t	ziptype;
99 } zone_entry_t;
100 
101 static zone_entry_t *zents;
102 static size_t nzents;
103 static boolean_t is_native_zone = B_TRUE;
104 
105 #define	LOOPBACK_IF	"lo0"
106 #define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
107 
108 struct net_if {
109 	char	*name;
110 	int	af;
111 };
112 
113 /* 0755 is the default directory mode. */
114 #define	DEFAULT_DIR_MODE \
115 	(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
116 
117 struct cmd {
118 	uint_t	cmd_num;				/* command number */
119 	char	*cmd_name;				/* command name */
120 	char	*short_usage;				/* short form help */
121 	int	(*handler)(int argc, char *argv[]);	/* function to call */
122 
123 };
124 
125 #define	SHELP_HELP	"help"
126 #define	SHELP_BOOT	"boot [-- boot_arguments]"
127 #define	SHELP_HALT	"halt"
128 #define	SHELP_READY	"ready"
129 #define	SHELP_REBOOT	"reboot [-- boot_arguments]"
130 #define	SHELP_LIST	"list [-cipv]"
131 #define	SHELP_VERIFY	"verify"
132 #define	SHELP_INSTALL	"install [-x nodataset] [brand-specific args]"
133 #define	SHELP_UNINSTALL	"uninstall [-F]"
134 #define	SHELP_CLONE	"clone [-m method] [-s <ZFS snapshot>] zonename"
135 #define	SHELP_MOVE	"move zonepath"
136 #define	SHELP_DETACH	"detach [-n]"
137 #define	SHELP_ATTACH	"attach [-F] [-n <path>]"
138 #define	SHELP_MARK	"mark incomplete"
139 
140 #define	EXEC_PREFIX	"exec "
141 #define	EXEC_LEN	(strlen(EXEC_PREFIX))
142 #define	RMCOMMAND	"/usr/bin/rm -rf"
143 
144 static int cleanup_zonepath(char *, boolean_t);
145 
146 extern int ifname_open(char *);
147 
148 static int help_func(int argc, char *argv[]);
149 static int ready_func(int argc, char *argv[]);
150 static int boot_func(int argc, char *argv[]);
151 static int halt_func(int argc, char *argv[]);
152 static int reboot_func(int argc, char *argv[]);
153 static int list_func(int argc, char *argv[]);
154 static int verify_func(int argc, char *argv[]);
155 static int install_func(int argc, char *argv[]);
156 static int uninstall_func(int argc, char *argv[]);
157 static int mount_func(int argc, char *argv[]);
158 static int unmount_func(int argc, char *argv[]);
159 static int clone_func(int argc, char *argv[]);
160 static int move_func(int argc, char *argv[]);
161 static int detach_func(int argc, char *argv[]);
162 static int attach_func(int argc, char *argv[]);
163 static int mark_func(int argc, char *argv[]);
164 static int apply_func(int argc, char *argv[]);
165 static int sanity_check(char *zone, int cmd_num, boolean_t running,
166     boolean_t unsafe_when_running, boolean_t force);
167 static int cmd_match(char *cmd);
168 static int verify_details(int, char *argv[]);
169 static int verify_brand(zone_dochandle_t, int, char *argv[]);
170 static int invoke_brand_handler(int, char *argv[]);
171 
172 static struct cmd cmdtab[] = {
173 	{ CMD_HELP,		"help",		SHELP_HELP,	help_func },
174 	{ CMD_BOOT,		"boot",		SHELP_BOOT,	boot_func },
175 	{ CMD_HALT,		"halt",		SHELP_HALT,	halt_func },
176 	{ CMD_READY,		"ready",	SHELP_READY,	ready_func },
177 	{ CMD_REBOOT,		"reboot",	SHELP_REBOOT,	reboot_func },
178 	{ CMD_LIST,		"list",		SHELP_LIST,	list_func },
179 	{ CMD_VERIFY,		"verify",	SHELP_VERIFY,	verify_func },
180 	{ CMD_INSTALL,		"install",	SHELP_INSTALL,	install_func },
181 	{ CMD_UNINSTALL,	"uninstall",	SHELP_UNINSTALL,
182 	    uninstall_func },
183 	/* mount and unmount are private commands for admin/install */
184 	{ CMD_MOUNT,		"mount",	NULL,		mount_func },
185 	{ CMD_UNMOUNT,		"unmount",	NULL,		unmount_func },
186 	{ CMD_CLONE,		"clone",	SHELP_CLONE,	clone_func },
187 	{ CMD_MOVE,		"move",		SHELP_MOVE,	move_func },
188 	{ CMD_DETACH,		"detach",	SHELP_DETACH,	detach_func },
189 	{ CMD_ATTACH,		"attach",	SHELP_ATTACH,	attach_func },
190 	{ CMD_MARK,		"mark",		SHELP_MARK,	mark_func },
191 	{ CMD_APPLY,		"apply",	NULL,		apply_func }
192 };
193 
194 /* global variables */
195 
196 /* set early in main(), never modified thereafter, used all over the place */
197 static char *execname;
198 static char target_brand[MAXNAMELEN];
199 static char *locale;
200 char *target_zone;
201 static char *target_uuid;
202 
203 /* used in do_subproc() and signal handler */
204 static volatile boolean_t child_killed;
205 static int do_subproc_cnt = 0;
206 
207 /*
208  * Used to indicate whether this zoneadm instance has another zoneadm
209  * instance in its ancestry.
210  */
211 static boolean_t zoneadm_is_nested = B_FALSE;
212 
213 /* used to track nested zone-lock operations */
214 static int zone_lock_cnt = 0;
215 
216 /* used to communicate lock status to children */
217 #define	LOCK_ENV_VAR	"_ZONEADM_LOCK_HELD"
218 static char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
219 static char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
220 
221 char *
222 cmd_to_str(int cmd_num)
223 {
224 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
225 	return (cmdtab[cmd_num].cmd_name);
226 }
227 
228 /* This is a separate function because of gettext() wrapping. */
229 static char *
230 long_help(int cmd_num)
231 {
232 	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
233 	switch (cmd_num) {
234 	case CMD_HELP:
235 		return (gettext("Print usage message."));
236 	case CMD_BOOT:
237 		return (gettext("Activates (boots) specified zone.  See "
238 		    "zoneadm(1m) for valid boot\n\targuments."));
239 	case CMD_HALT:
240 		return (gettext("Halts specified zone, bypassing shutdown "
241 		    "scripts and removing runtime\n\tresources of the zone."));
242 	case CMD_READY:
243 		return (gettext("Prepares a zone for running applications but "
244 		    "does not start any user\n\tprocesses in the zone."));
245 	case CMD_REBOOT:
246 		return (gettext("Restarts the zone (equivalent to a halt / "
247 		    "boot sequence).\n\tFails if the zone is not active.  "
248 		    "See zoneadm(1m) for valid boot\n\targuments."));
249 	case CMD_LIST:
250 		return (gettext("Lists the current zones, or a "
251 		    "specific zone if indicated.  By default,\n\tall "
252 		    "running zones are listed, though this can be "
253 		    "expanded to all\n\tinstalled zones with the -i "
254 		    "option or all configured zones with the\n\t-c "
255 		    "option.  When used with the general -z <zone> and/or -u "
256 		    "<uuid-match>\n\toptions, lists only the specified "
257 		    "matching zone, but lists it\n\tregardless of its state, "
258 		    "and the -i and -c options are disallowed.  The\n\t-v "
259 		    "option can be used to display verbose information: zone "
260 		    "name, id,\n\tcurrent state, root directory and options.  "
261 		    "The -p option can be used\n\tto request machine-parsable "
262 		    "output.  The -v and -p options are mutually\n\texclusive."
263 		    "  If neither -v nor -p is used, just the zone name is "
264 		    "listed."));
265 	case CMD_VERIFY:
266 		return (gettext("Check to make sure the configuration "
267 		    "can safely be instantiated\n\ton the machine: "
268 		    "physical network interfaces exist, etc."));
269 	case CMD_INSTALL:
270 		return (gettext("Install the configuration on to the system.  "
271 		    "The -x nodataset option\n\tcan be used to prevent the "
272 		    "creation of a new ZFS file system for the\n\tzone "
273 		    "(assuming the zonepath is within a ZFS file system).\n\t"
274 		    "All other arguments are passed to the brand installation "
275 		    "function;\n\tsee brand(4) for more information."));
276 	case CMD_UNINSTALL:
277 		return (gettext("Uninstall the configuration from the system.  "
278 		    "The -F flag can be used\n\tto force the action."));
279 	case CMD_CLONE:
280 		return (gettext("Clone the installation of another zone.  "
281 		    "The -m option can be used to\n\tspecify 'copy' which "
282 		    "forces a copy of the source zone.  The -s option\n\t"
283 		    "can be used to specify the name of a ZFS snapshot "
284 		    "that was taken from\n\ta previous clone command.  The "
285 		    "snapshot will be used as the source\n\tinstead of "
286 		    "creating a new ZFS snapshot."));
287 	case CMD_MOVE:
288 		return (gettext("Move the zone to a new zonepath."));
289 	case CMD_DETACH:
290 		return (gettext("Detach the zone from the system. The zone "
291 		    "state is changed to\n\t'configured' (but the files under "
292 		    "the zonepath are untouched).\n\tThe zone can subsequently "
293 		    "be attached, or can be moved to another\n\tsystem and "
294 		    "attached there.  The -n option can be used to specify\n\t"
295 		    "'no-execute' mode.  When -n is used, the information "
296 		    "needed to attach\n\tthe zone is sent to standard output "
297 		    "but the zone is not actually\n\tdetached."));
298 	case CMD_ATTACH:
299 		return (gettext("Attach the zone to the system.  The zone "
300 		    "state must be 'configured'\n\tprior to attach; upon "
301 		    "successful completion, the zone state will be\n\t"
302 		    "'installed'.  The system software on the current "
303 		    "system must be\n\tcompatible with the software on the "
304 		    "zone's original system.\n\tSpecify -F to force the attach "
305 		    "and skip software compatibility tests.\n\tThe -n option "
306 		    "can be used to specify 'no-execute' mode.  When -n is\n\t"
307 		    "used, the information needed to attach the zone is read "
308 		    "from the\n\tspecified path and the configuration is only "
309 		    "validated.  The path can\n\tbe '-' to specify standard "
310 		    "input."));
311 	case CMD_MARK:
312 		return (gettext("Set the state of the zone.  This can be used "
313 		    "to force the zone\n\tstate to 'incomplete' "
314 		    "administratively if some activity has rendered\n\tthe "
315 		    "zone permanently unusable.  The only valid state that "
316 		    "may be\n\tspecified is 'incomplete'."));
317 	default:
318 		return ("");
319 	}
320 	/* NOTREACHED */
321 	return (NULL);
322 }
323 
324 /*
325  * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
326  * unexpected errors.
327  */
328 
329 static int
330 usage(boolean_t explicit)
331 {
332 	int i;
333 	FILE *fd = explicit ? stdout : stderr;
334 
335 	(void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
336 	(void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
337 	    execname);
338 	(void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
339 	    gettext("subcommand"));
340 	(void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
341 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
342 		if (cmdtab[i].short_usage == NULL)
343 			continue;
344 		(void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
345 		if (explicit)
346 			(void) fprintf(fd, "\t%s\n\n", long_help(i));
347 	}
348 	if (!explicit)
349 		(void) fputs("\n", fd);
350 	return (Z_USAGE);
351 }
352 
353 static void
354 sub_usage(char *short_usage, int cmd_num)
355 {
356 	(void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
357 	(void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
358 }
359 
360 /*
361  * zperror() is like perror(3c) except that this also prints the executable
362  * name at the start of the message, and takes a boolean indicating whether
363  * to call libc'c strerror() or that from libzonecfg.
364  */
365 
366 void
367 zperror(const char *str, boolean_t zonecfg_error)
368 {
369 	(void) fprintf(stderr, "%s: %s: %s\n", execname, str,
370 	    zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
371 }
372 
373 /*
374  * zperror2() is very similar to zperror() above, except it also prints a
375  * supplied zone name after the executable.
376  *
377  * All current consumers of this function want libzonecfg's strerror() rather
378  * than libc's; if this ever changes, this function can be made more generic
379  * like zperror() above.
380  */
381 
382 void
383 zperror2(const char *zone, const char *str)
384 {
385 	(void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
386 	    zonecfg_strerror(errno));
387 }
388 
389 /* PRINTFLIKE1 */
390 void
391 zerror(const char *fmt, ...)
392 {
393 	va_list alist;
394 
395 	va_start(alist, fmt);
396 	(void) fprintf(stderr, "%s: ", execname);
397 	if (target_zone != NULL)
398 		(void) fprintf(stderr, "zone '%s': ", target_zone);
399 	(void) vfprintf(stderr, fmt, alist);
400 	(void) fprintf(stderr, "\n");
401 	va_end(alist);
402 }
403 
404 static void *
405 safe_calloc(size_t nelem, size_t elsize)
406 {
407 	void *r = calloc(nelem, elsize);
408 
409 	if (r == NULL) {
410 		zerror(gettext("failed to allocate %lu bytes: %s"),
411 		    (ulong_t)nelem * elsize, strerror(errno));
412 		exit(Z_ERR);
413 	}
414 	return (r);
415 }
416 
417 static void
418 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
419 {
420 	static boolean_t firsttime = B_TRUE;
421 	char *ip_type_str;
422 
423 	if (zent->ziptype == ZS_EXCLUSIVE)
424 		ip_type_str = "excl";
425 	else
426 		ip_type_str = "shared";
427 
428 	assert(!(verbose && parsable));
429 	if (firsttime && verbose) {
430 		firsttime = B_FALSE;
431 		(void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
432 		    ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
433 		    "IP");
434 	}
435 	if (!verbose) {
436 		char *cp, *clim;
437 
438 		if (!parsable) {
439 			(void) printf("%s\n", zent->zname);
440 			return;
441 		}
442 		if (zent->zid == ZONE_ID_UNDEFINED)
443 			(void) printf("-");
444 		else
445 			(void) printf("%lu", zent->zid);
446 		(void) printf(":%s:%s:", zent->zname, zent->zstate_str);
447 		cp = zent->zroot;
448 		while ((clim = strchr(cp, ':')) != NULL) {
449 			(void) printf("%.*s\\:", clim - cp, cp);
450 			cp = clim + 1;
451 		}
452 		(void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
453 		    ip_type_str);
454 		return;
455 	}
456 	if (zent->zstate_str != NULL) {
457 		if (zent->zid == ZONE_ID_UNDEFINED)
458 			(void) printf("%*s", ZONEID_WIDTH, "-");
459 		else
460 			(void) printf("%*lu", ZONEID_WIDTH, zent->zid);
461 		(void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
462 		    zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
463 	}
464 }
465 
466 static int
467 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
468 {
469 	char root[MAXPATHLEN], *cp;
470 	int err;
471 	uuid_t uuid;
472 
473 	(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
474 	(void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
475 	(void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand));
476 	zent->zstate_str = "???";
477 
478 	zent->zid = zid;
479 
480 	if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
481 	    !uuid_is_null(uuid))
482 		uuid_unparse(uuid, zent->zuuid);
483 	else
484 		zent->zuuid[0] = '\0';
485 
486 	/*
487 	 * For labeled zones which query the zone path of lower-level
488 	 * zones, the path needs to be adjusted to drop the final
489 	 * "/root" component. This adjusted path is then useful
490 	 * for reading down any exported directories from the
491 	 * lower-level zone.
492 	 */
493 	if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
494 		if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
495 		    sizeof (zent->zroot)) == -1) {
496 			zperror2(zent->zname,
497 			    gettext("could not get zone path."));
498 			return (Z_ERR);
499 		}
500 		cp = zent->zroot + strlen(zent->zroot) - 5;
501 		if (cp > zent->zroot && strcmp(cp, "/root") == 0)
502 			*cp = 0;
503 	} else {
504 		if ((err = zone_get_zonepath(zent->zname, root,
505 		    sizeof (root))) != Z_OK) {
506 			errno = err;
507 			zperror2(zent->zname,
508 			    gettext("could not get zone path."));
509 			return (Z_ERR);
510 		}
511 		(void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
512 	}
513 
514 	if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
515 		errno = err;
516 		zperror2(zent->zname, gettext("could not get state"));
517 		return (Z_ERR);
518 	}
519 	zent->zstate_str = zone_state_str(zent->zstate_num);
520 
521 	/*
522 	 * A zone's brand is only available in the .xml file describing it,
523 	 * which is only visible to the global zone.  This causes
524 	 * zone_get_brand() to fail when called from within a non-global
525 	 * zone.  Fortunately we only do this on labeled systems, where we
526 	 * know all zones are native.
527 	 */
528 	if (getzoneid() != GLOBAL_ZONEID) {
529 		assert(is_system_labeled() != 0);
530 		(void) strlcpy(zent->zbrand, NATIVE_BRAND_NAME,
531 		    sizeof (zent->zbrand));
532 	} else if (zone_get_brand(zent->zname, zent->zbrand,
533 	    sizeof (zent->zbrand)) != Z_OK) {
534 		zperror2(zent->zname, gettext("could not get brand name"));
535 		return (Z_ERR);
536 	}
537 
538 	/*
539 	 * Get ip type of the zone.
540 	 * Note for global zone, ZS_SHARED is set always.
541 	 */
542 	if (zid == GLOBAL_ZONEID) {
543 		zent->ziptype = ZS_SHARED;
544 	} else {
545 
546 		if (zent->zstate_num == ZONE_STATE_RUNNING) {
547 			ushort_t flags;
548 
549 			if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
550 			    sizeof (flags)) < 0) {
551 				zperror2(zent->zname,
552 				    gettext("could not get zone flags"));
553 				return (Z_ERR);
554 			}
555 			if (flags & ZF_NET_EXCL)
556 				zent->ziptype = ZS_EXCLUSIVE;
557 			else
558 				zent->ziptype = ZS_SHARED;
559 		} else {
560 			zone_dochandle_t handle;
561 
562 			if ((handle = zonecfg_init_handle()) == NULL) {
563 				zperror2(zent->zname,
564 				    gettext("could not init handle"));
565 				return (Z_ERR);
566 			}
567 			if ((err = zonecfg_get_handle(zent->zname, handle))
568 			    != Z_OK) {
569 				zperror2(zent->zname,
570 				    gettext("could not get handle"));
571 				zonecfg_fini_handle(handle);
572 				return (Z_ERR);
573 			}
574 
575 			if ((err = zonecfg_get_iptype(handle, &zent->ziptype))
576 			    != Z_OK) {
577 				zperror2(zent->zname,
578 				    gettext("could not get ip-type"));
579 				zonecfg_fini_handle(handle);
580 				return (Z_ERR);
581 			}
582 			zonecfg_fini_handle(handle);
583 		}
584 	}
585 
586 	return (Z_OK);
587 }
588 
589 /*
590  * fetch_zents() calls zone_list(2) to find out how many zones are running
591  * (which is stored in the global nzents), then calls zone_list(2) again
592  * to fetch the list of running zones (stored in the global zents).  This
593  * function may be called multiple times, so if zents is already set, we
594  * return immediately to save work.
595  */
596 
597 static int
598 fetch_zents(void)
599 {
600 	zoneid_t *zids = NULL;
601 	uint_t nzents_saved;
602 	int i, retv;
603 	FILE *fp;
604 	boolean_t inaltroot;
605 	zone_entry_t *zentp;
606 
607 	if (nzents > 0)
608 		return (Z_OK);
609 
610 	if (zone_list(NULL, &nzents) != 0) {
611 		zperror(gettext("failed to get zoneid list"), B_FALSE);
612 		return (Z_ERR);
613 	}
614 
615 again:
616 	if (nzents == 0)
617 		return (Z_OK);
618 
619 	zids = safe_calloc(nzents, sizeof (zoneid_t));
620 	nzents_saved = nzents;
621 
622 	if (zone_list(zids, &nzents) != 0) {
623 		zperror(gettext("failed to get zone list"), B_FALSE);
624 		free(zids);
625 		return (Z_ERR);
626 	}
627 	if (nzents != nzents_saved) {
628 		/* list changed, try again */
629 		free(zids);
630 		goto again;
631 	}
632 
633 	zents = safe_calloc(nzents, sizeof (zone_entry_t));
634 
635 	inaltroot = zonecfg_in_alt_root();
636 	if (inaltroot)
637 		fp = zonecfg_open_scratch("", B_FALSE);
638 	else
639 		fp = NULL;
640 	zentp = zents;
641 	retv = Z_OK;
642 	for (i = 0; i < nzents; i++) {
643 		char name[ZONENAME_MAX];
644 		char altname[ZONENAME_MAX];
645 
646 		if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
647 			zperror(gettext("failed to get zone name"), B_FALSE);
648 			retv = Z_ERR;
649 			continue;
650 		}
651 		if (zonecfg_is_scratch(name)) {
652 			/* Ignore scratch zones by default */
653 			if (!inaltroot)
654 				continue;
655 			if (fp == NULL ||
656 			    zonecfg_reverse_scratch(fp, name, altname,
657 			    sizeof (altname), NULL, 0) == -1) {
658 				zerror(gettext("could not resolve scratch "
659 				    "zone %s"), name);
660 				retv = Z_ERR;
661 				continue;
662 			}
663 			(void) strcpy(name, altname);
664 		} else {
665 			/* Ignore non-scratch when in an alternate root */
666 			if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
667 				continue;
668 		}
669 		if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
670 			zerror(gettext("failed to get zone data"));
671 			retv = Z_ERR;
672 			continue;
673 		}
674 		zentp++;
675 	}
676 	nzents = zentp - zents;
677 	if (fp != NULL)
678 		zonecfg_close_scratch(fp);
679 
680 	free(zids);
681 	return (retv);
682 }
683 
684 static int
685 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable)
686 {
687 	int i;
688 	zone_entry_t zent;
689 	FILE *cookie;
690 	char *name;
691 
692 	/*
693 	 * First get the list of running zones from the kernel and print them.
694 	 * If that is all we need, then return.
695 	 */
696 	if ((i = fetch_zents()) != Z_OK) {
697 		/*
698 		 * No need for error messages; fetch_zents() has already taken
699 		 * care of this.
700 		 */
701 		return (i);
702 	}
703 	for (i = 0; i < nzents; i++)
704 		zone_print(&zents[i], verbose, parsable);
705 	if (min_state >= ZONE_STATE_RUNNING)
706 		return (Z_OK);
707 	/*
708 	 * Next, get the full list of zones from the configuration, skipping
709 	 * any we have already printed.
710 	 */
711 	cookie = setzoneent();
712 	while ((name = getzoneent(cookie)) != NULL) {
713 		for (i = 0; i < nzents; i++) {
714 			if (strcmp(zents[i].zname, name) == 0)
715 				break;
716 		}
717 		if (i < nzents) {
718 			free(name);
719 			continue;
720 		}
721 		if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
722 			free(name);
723 			continue;
724 		}
725 		free(name);
726 		if (zent.zstate_num >= min_state)
727 			zone_print(&zent, verbose, parsable);
728 	}
729 	endzoneent(cookie);
730 	return (Z_OK);
731 }
732 
733 static zone_entry_t *
734 lookup_running_zone(char *str)
735 {
736 	zoneid_t zoneid;
737 	char *cp;
738 	int i;
739 
740 	if (fetch_zents() != Z_OK)
741 		return (NULL);
742 
743 	for (i = 0; i < nzents; i++) {
744 		if (strcmp(str, zents[i].zname) == 0)
745 			return (&zents[i]);
746 	}
747 	errno = 0;
748 	zoneid = strtol(str, &cp, 0);
749 	if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID ||
750 	    errno != 0 || *cp != '\0')
751 		return (NULL);
752 	for (i = 0; i < nzents; i++) {
753 		if (zoneid == zents[i].zid)
754 			return (&zents[i]);
755 	}
756 	return (NULL);
757 }
758 
759 /*
760  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
761  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
762  */
763 static boolean_t
764 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
765 {
766 	char *str;
767 
768 	assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
769 	    bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
770 	    bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
771 	/*
772 	 * TRANSLATION_NOTE
773 	 * The strings below will be used as part of a larger message,
774 	 * either:
775 	 * (file name) must be (owner|group|world) (read|writ|execut)able
776 	 * or
777 	 * (file name) must not be (owner|group|world) (read|writ|execut)able
778 	 */
779 	switch (bit) {
780 	case S_IRUSR:
781 		str = gettext("owner readable");
782 		break;
783 	case S_IWUSR:
784 		str = gettext("owner writable");
785 		break;
786 	case S_IXUSR:
787 		str = gettext("owner executable");
788 		break;
789 	case S_IRGRP:
790 		str = gettext("group readable");
791 		break;
792 	case S_IWGRP:
793 		str = gettext("group writable");
794 		break;
795 	case S_IXGRP:
796 		str = gettext("group executable");
797 		break;
798 	case S_IROTH:
799 		str = gettext("world readable");
800 		break;
801 	case S_IWOTH:
802 		str = gettext("world writable");
803 		break;
804 	case S_IXOTH:
805 		str = gettext("world executable");
806 		break;
807 	}
808 	if ((mode & bit) == (on ? 0 : bit)) {
809 		/*
810 		 * TRANSLATION_NOTE
811 		 * The first parameter below is a file name; the second
812 		 * is one of the "(owner|group|world) (read|writ|execut)able"
813 		 * strings from above.
814 		 */
815 		/*
816 		 * The code below could be simplified but not in a way
817 		 * that would easily translate to non-English locales.
818 		 */
819 		if (on) {
820 			(void) fprintf(stderr, gettext("%s must be %s.\n"),
821 			    file, str);
822 		} else {
823 			(void) fprintf(stderr, gettext("%s must not be %s.\n"),
824 			    file, str);
825 		}
826 		return (B_TRUE);
827 	}
828 	return (B_FALSE);
829 }
830 
831 /*
832  * We want to make sure that no zone has its zone path as a child node
833  * (in the directory sense) of any other.  We do that by comparing this
834  * zone's path to the path of all other (non-global) zones.  The comparison
835  * in each case is simple: add '/' to the end of the path, then do a
836  * strncmp() of the two paths, using the length of the shorter one.
837  */
838 
839 static int
840 crosscheck_zonepaths(char *path)
841 {
842 	char rpath[MAXPATHLEN];		/* resolved path */
843 	char path_copy[MAXPATHLEN];	/* copy of original path */
844 	char rpath_copy[MAXPATHLEN];	/* copy of original rpath */
845 	struct zoneent *ze;
846 	int res, err;
847 	FILE *cookie;
848 
849 	cookie = setzoneent();
850 	while ((ze = getzoneent_private(cookie)) != NULL) {
851 		/* Skip zones which are not installed. */
852 		if (ze->zone_state < ZONE_STATE_INSTALLED) {
853 			free(ze);
854 			continue;
855 		}
856 		/* Skip the global zone and the current target zone. */
857 		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
858 		    strcmp(ze->zone_name, target_zone) == 0) {
859 			free(ze);
860 			continue;
861 		}
862 		if (strlen(ze->zone_path) == 0) {
863 			/* old index file without path, fall back */
864 			if ((err = zone_get_zonepath(ze->zone_name,
865 			    ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
866 				errno = err;
867 				zperror2(ze->zone_name,
868 				    gettext("could not get zone path"));
869 				free(ze);
870 				continue;
871 			}
872 		}
873 		(void) snprintf(path_copy, sizeof (path_copy), "%s%s",
874 		    zonecfg_get_root(), ze->zone_path);
875 		res = resolvepath(path_copy, rpath, sizeof (rpath));
876 		if (res == -1) {
877 			if (errno != ENOENT) {
878 				zperror(path_copy, B_FALSE);
879 				free(ze);
880 				return (Z_ERR);
881 			}
882 			(void) printf(gettext("WARNING: zone %s is installed, "
883 			    "but its %s %s does not exist.\n"), ze->zone_name,
884 			    "zonepath", path_copy);
885 			free(ze);
886 			continue;
887 		}
888 		rpath[res] = '\0';
889 		(void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
890 		(void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
891 		if (strncmp(path_copy, rpath_copy,
892 		    min(strlen(path_copy), strlen(rpath_copy))) == 0) {
893 			/*
894 			 * TRANSLATION_NOTE
895 			 * zonepath is a literal that should not be translated.
896 			 */
897 			(void) fprintf(stderr, gettext("%s zonepath (%s) and "
898 			    "%s zonepath (%s) overlap.\n"),
899 			    target_zone, path, ze->zone_name, rpath);
900 			free(ze);
901 			return (Z_ERR);
902 		}
903 		free(ze);
904 	}
905 	endzoneent(cookie);
906 	return (Z_OK);
907 }
908 
909 static int
910 validate_zonepath(char *path, int cmd_num)
911 {
912 	int res;			/* result of last library/system call */
913 	boolean_t err = B_FALSE;	/* have we run into an error? */
914 	struct stat stbuf;
915 	struct statvfs64 vfsbuf;
916 	char rpath[MAXPATHLEN];		/* resolved path */
917 	char ppath[MAXPATHLEN];		/* parent path */
918 	char rppath[MAXPATHLEN];	/* resolved parent path */
919 	char rootpath[MAXPATHLEN];	/* root path */
920 	zone_state_t state;
921 
922 	if (path[0] != '/') {
923 		(void) fprintf(stderr,
924 		    gettext("%s is not an absolute path.\n"), path);
925 		return (Z_ERR);
926 	}
927 	if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
928 		if ((errno != ENOENT) ||
929 		    (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
930 		    cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
931 			zperror(path, B_FALSE);
932 			return (Z_ERR);
933 		}
934 		if (cmd_num == CMD_VERIFY) {
935 			/*
936 			 * TRANSLATION_NOTE
937 			 * zoneadm is a literal that should not be translated.
938 			 */
939 			(void) fprintf(stderr, gettext("WARNING: %s does not "
940 			    "exist, so it could not be verified.\nWhen "
941 			    "'zoneadm %s' is run, '%s' will try to create\n%s, "
942 			    "and '%s' will be tried again,\nbut the '%s' may "
943 			    "fail if:\nthe parent directory of %s is group- or "
944 			    "other-writable\nor\n%s overlaps with any other "
945 			    "installed zones.\n"), path,
946 			    cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
947 			    path, cmd_to_str(CMD_VERIFY),
948 			    cmd_to_str(CMD_VERIFY), path, path);
949 			return (Z_OK);
950 		}
951 		/*
952 		 * The zonepath is supposed to be mode 700 but its
953 		 * parent(s) 755.  So use 755 on the mkdirp() then
954 		 * chmod() the zonepath itself to 700.
955 		 */
956 		if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
957 			zperror(path, B_FALSE);
958 			return (Z_ERR);
959 		}
960 		/*
961 		 * If the chmod() fails, report the error, but might
962 		 * as well continue the verify procedure.
963 		 */
964 		if (chmod(path, S_IRWXU) != 0)
965 			zperror(path, B_FALSE);
966 		/*
967 		 * Since the mkdir() succeeded, we should not have to
968 		 * worry about a subsequent ENOENT, thus this should
969 		 * only recurse once.
970 		 */
971 		return (validate_zonepath(path, cmd_num));
972 	}
973 	rpath[res] = '\0';
974 	if (strcmp(path, rpath) != 0) {
975 		errno = Z_RESOLVED_PATH;
976 		zperror(path, B_TRUE);
977 		return (Z_ERR);
978 	}
979 	if ((res = stat(rpath, &stbuf)) != 0) {
980 		zperror(rpath, B_FALSE);
981 		return (Z_ERR);
982 	}
983 	if (!S_ISDIR(stbuf.st_mode)) {
984 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
985 		    rpath);
986 		return (Z_ERR);
987 	}
988 	if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) {
989 		(void) printf(gettext("WARNING: %s is on a temporary "
990 		    "file system.\n"), rpath);
991 	}
992 	if (crosscheck_zonepaths(rpath) != Z_OK)
993 		return (Z_ERR);
994 	/*
995 	 * Try to collect and report as many minor errors as possible
996 	 * before returning, so the user can learn everything that needs
997 	 * to be fixed up front.
998 	 */
999 	if (stbuf.st_uid != 0) {
1000 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1001 		    rpath);
1002 		err = B_TRUE;
1003 	}
1004 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
1005 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
1006 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
1007 	err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
1008 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
1009 	err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
1010 	err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
1011 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
1012 	err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
1013 
1014 	(void) snprintf(ppath, sizeof (ppath), "%s/..", path);
1015 	if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
1016 		zperror(ppath, B_FALSE);
1017 		return (Z_ERR);
1018 	}
1019 	rppath[res] = '\0';
1020 	if ((res = stat(rppath, &stbuf)) != 0) {
1021 		zperror(rppath, B_FALSE);
1022 		return (Z_ERR);
1023 	}
1024 	/* theoretically impossible */
1025 	if (!S_ISDIR(stbuf.st_mode)) {
1026 		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
1027 		    rppath);
1028 		return (Z_ERR);
1029 	}
1030 	if (stbuf.st_uid != 0) {
1031 		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1032 		    rppath);
1033 		err = B_TRUE;
1034 	}
1035 	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
1036 	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
1037 	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
1038 	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
1039 	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
1040 	if (strcmp(rpath, rppath) == 0) {
1041 		(void) fprintf(stderr, gettext("%s is its own parent.\n"),
1042 		    rppath);
1043 		err = B_TRUE;
1044 	}
1045 
1046 	if (statvfs64(rpath, &vfsbuf) != 0) {
1047 		zperror(rpath, B_FALSE);
1048 		return (Z_ERR);
1049 	}
1050 	if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
1051 		/*
1052 		 * TRANSLATION_NOTE
1053 		 * Zonepath and NFS are literals that should not be translated.
1054 		 */
1055 		(void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
1056 		    "mounted file system.\n"
1057 		    "\tA local file system must be used.\n"), rpath);
1058 		return (Z_ERR);
1059 	}
1060 	if (vfsbuf.f_flag & ST_NOSUID) {
1061 		/*
1062 		 * TRANSLATION_NOTE
1063 		 * Zonepath and nosuid are literals that should not be
1064 		 * translated.
1065 		 */
1066 		(void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
1067 		    "file system.\n"), rpath);
1068 		return (Z_ERR);
1069 	}
1070 
1071 	if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
1072 		errno = res;
1073 		zperror2(target_zone, gettext("could not get state"));
1074 		return (Z_ERR);
1075 	}
1076 	/*
1077 	 * The existence of the root path is only bad in the configured state,
1078 	 * as it is *supposed* to be there at the installed and later states.
1079 	 * However, the root path is expected to be there if the zone is
1080 	 * detached.
1081 	 * State/command mismatches are caught earlier in verify_details().
1082 	 */
1083 	if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1084 		if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1085 		    sizeof (rootpath)) {
1086 			/*
1087 			 * TRANSLATION_NOTE
1088 			 * Zonepath is a literal that should not be translated.
1089 			 */
1090 			(void) fprintf(stderr,
1091 			    gettext("Zonepath %s is too long.\n"), rpath);
1092 			return (Z_ERR);
1093 		}
1094 		if ((res = stat(rootpath, &stbuf)) == 0) {
1095 			if (zonecfg_detached(rpath))
1096 				(void) fprintf(stderr,
1097 				    gettext("Cannot %s detached "
1098 				    "zone.\nUse attach or remove %s "
1099 				    "directory.\n"), cmd_to_str(cmd_num),
1100 				    rpath);
1101 			else
1102 				(void) fprintf(stderr,
1103 				    gettext("Rootpath %s exists; "
1104 				    "remove or move aside prior to %s.\n"),
1105 				    rootpath, cmd_to_str(cmd_num));
1106 			return (Z_ERR);
1107 		}
1108 	}
1109 
1110 	return (err ? Z_ERR : Z_OK);
1111 }
1112 
1113 /*
1114  * The following two routines implement a simple locking mechanism to
1115  * ensure that only one instance of zoneadm at a time is able to manipulate
1116  * a given zone.  The lock is built on top of an fcntl(2) lock of
1117  * [<altroot>]/var/run/zones/<zonename>.zoneadm.lock.  If a zoneadm instance
1118  * can grab that lock, it is allowed to manipulate the zone.
1119  *
1120  * Since zoneadm may call external applications which in turn invoke
1121  * zoneadm again, we introduce the notion of "lock inheritance".  Any
1122  * instance of zoneadm that has another instance in its ancestry is assumed
1123  * to be acting on behalf of the original zoneadm, and is thus allowed to
1124  * manipulate its zone.
1125  *
1126  * This inheritance is implemented via the _ZONEADM_LOCK_HELD environment
1127  * variable.  When zoneadm is granted a lock on its zone, this environment
1128  * variable is set to 1.  When it releases the lock, the variable is set to
1129  * 0.  Since a child process inherits its parent's environment, checking
1130  * the state of this variable indicates whether or not any ancestor owns
1131  * the lock.
1132  */
1133 static void
1134 release_lock_file(int lockfd)
1135 {
1136 	/*
1137 	 * If we are cleaning up from a failed attempt to lock the zone for
1138 	 * the first time, we might have a zone_lock_cnt of 0.  In that
1139 	 * error case, we don't want to do anything but close the lock
1140 	 * file.
1141 	 */
1142 	assert(zone_lock_cnt >= 0);
1143 	if (zone_lock_cnt > 0) {
1144 		assert(getenv(LOCK_ENV_VAR) != NULL);
1145 		assert(atoi(getenv(LOCK_ENV_VAR)) == 1);
1146 		if (--zone_lock_cnt > 0) {
1147 			assert(lockfd == -1);
1148 			return;
1149 		}
1150 		if (putenv(zoneadm_lock_not_held) != 0) {
1151 			zperror(target_zone, B_TRUE);
1152 			exit(Z_ERR);
1153 		}
1154 	}
1155 	assert(lockfd >= 0);
1156 	(void) close(lockfd);
1157 }
1158 
1159 static int
1160 grab_lock_file(const char *zone_name, int *lockfd)
1161 {
1162 	char pathbuf[PATH_MAX];
1163 	struct flock flock;
1164 
1165 	/*
1166 	 * If we already have the lock, we can skip this expensive song
1167 	 * and dance.
1168 	 */
1169 	if (zone_lock_cnt > 0) {
1170 		zone_lock_cnt++;
1171 		*lockfd = -1;
1172 		return (Z_OK);
1173 	}
1174 	assert(getenv(LOCK_ENV_VAR) != NULL);
1175 	assert(atoi(getenv(LOCK_ENV_VAR)) == 0);
1176 
1177 	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(),
1178 	    ZONES_TMPDIR) >= sizeof (pathbuf)) {
1179 		zerror(gettext("alternate root path is too long"));
1180 		return (Z_ERR);
1181 	}
1182 	if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) {
1183 		zerror(gettext("could not mkdir %s: %s"), pathbuf,
1184 		    strerror(errno));
1185 		return (Z_ERR);
1186 	}
1187 	(void) chmod(pathbuf, S_IRWXU);
1188 
1189 	/*
1190 	 * One of these lock files is created for each zone (when needed).
1191 	 * The lock files are not cleaned up (except on system reboot),
1192 	 * but since there is only one per zone, there is no resource
1193 	 * starvation issue.
1194 	 */
1195 	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock",
1196 	    zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) {
1197 		zerror(gettext("alternate root path is too long"));
1198 		return (Z_ERR);
1199 	}
1200 	if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
1201 		zerror(gettext("could not open %s: %s"), pathbuf,
1202 		    strerror(errno));
1203 		return (Z_ERR);
1204 	}
1205 	/*
1206 	 * Lock the file to synchronize with other zoneadmds
1207 	 */
1208 	flock.l_type = F_WRLCK;
1209 	flock.l_whence = SEEK_SET;
1210 	flock.l_start = (off_t)0;
1211 	flock.l_len = (off_t)0;
1212 	if ((fcntl(*lockfd, F_SETLKW, &flock) < 0) ||
1213 	    (putenv(zoneadm_lock_held) != 0)) {
1214 		zerror(gettext("unable to lock %s: %s"), pathbuf,
1215 		    strerror(errno));
1216 		release_lock_file(*lockfd);
1217 		return (Z_ERR);
1218 	}
1219 	zone_lock_cnt = 1;
1220 	return (Z_OK);
1221 }
1222 
1223 static boolean_t
1224 get_doorname(const char *zone_name, char *buffer)
1225 {
1226 	return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH,
1227 	    zonecfg_get_root(), zone_name) < PATH_MAX);
1228 }
1229 
1230 /*
1231  * system daemons are not audited.  For the global zone, this occurs
1232  * "naturally" since init is started with the default audit
1233  * characteristics.  Since zoneadmd is a system daemon and it starts
1234  * init for a zone, it is necessary to clear out the audit
1235  * characteristics inherited from whomever started zoneadmd.  This is
1236  * indicated by the audit id, which is set from the ruid parameter of
1237  * adt_set_user(), below.
1238  */
1239 
1240 static void
1241 prepare_audit_context()
1242 {
1243 	adt_session_data_t	*ah;
1244 	char			*failure = gettext("audit failure: %s");
1245 
1246 	if (adt_start_session(&ah, NULL, 0)) {
1247 		zerror(failure, strerror(errno));
1248 		return;
1249 	}
1250 	if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT,
1251 	    ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) {
1252 		zerror(failure, strerror(errno));
1253 		(void) adt_end_session(ah);
1254 		return;
1255 	}
1256 	if (adt_set_proc(ah))
1257 		zerror(failure, strerror(errno));
1258 
1259 	(void) adt_end_session(ah);
1260 }
1261 
1262 static int
1263 start_zoneadmd(const char *zone_name)
1264 {
1265 	char doorpath[PATH_MAX];
1266 	pid_t child_pid;
1267 	int error = Z_ERR;
1268 	int doorfd, lockfd;
1269 	struct door_info info;
1270 
1271 	if (!get_doorname(zone_name, doorpath))
1272 		return (Z_ERR);
1273 
1274 	if (grab_lock_file(zone_name, &lockfd) != Z_OK)
1275 		return (Z_ERR);
1276 
1277 	/*
1278 	 * Now that we have the lock, re-confirm that the daemon is
1279 	 * *not* up and working fine.  If it is still down, we have a green
1280 	 * light to start it.
1281 	 */
1282 	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1283 		if (errno != ENOENT) {
1284 			zperror(doorpath, B_FALSE);
1285 			goto out;
1286 		}
1287 	} else {
1288 		if (door_info(doorfd, &info) == 0 &&
1289 		    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1290 			error = Z_OK;
1291 			(void) close(doorfd);
1292 			goto out;
1293 		}
1294 		(void) close(doorfd);
1295 	}
1296 
1297 	if ((child_pid = fork()) == -1) {
1298 		zperror(gettext("could not fork"), B_FALSE);
1299 		goto out;
1300 	} else if (child_pid == 0) {
1301 		const char *argv[6], **ap;
1302 
1303 		/* child process */
1304 		prepare_audit_context();
1305 
1306 		ap = argv;
1307 		*ap++ = "zoneadmd";
1308 		*ap++ = "-z";
1309 		*ap++ = zone_name;
1310 		if (zonecfg_in_alt_root()) {
1311 			*ap++ = "-R";
1312 			*ap++ = zonecfg_get_root();
1313 		}
1314 		*ap = NULL;
1315 
1316 		(void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
1317 		/*
1318 		 * TRANSLATION_NOTE
1319 		 * zoneadmd is a literal that should not be translated.
1320 		 */
1321 		zperror(gettext("could not exec zoneadmd"), B_FALSE);
1322 		_exit(Z_ERR);
1323 	} else {
1324 		/* parent process */
1325 		pid_t retval;
1326 		int pstatus = 0;
1327 
1328 		do {
1329 			retval = waitpid(child_pid, &pstatus, 0);
1330 		} while (retval != child_pid);
1331 		if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) &&
1332 		    WEXITSTATUS(pstatus) != 0)) {
1333 			zerror(gettext("could not start %s"), "zoneadmd");
1334 			goto out;
1335 		}
1336 	}
1337 	error = Z_OK;
1338 out:
1339 	release_lock_file(lockfd);
1340 	return (error);
1341 }
1342 
1343 static int
1344 ping_zoneadmd(const char *zone_name)
1345 {
1346 	char doorpath[PATH_MAX];
1347 	int doorfd;
1348 	struct door_info info;
1349 
1350 	if (!get_doorname(zone_name, doorpath))
1351 		return (Z_ERR);
1352 
1353 	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1354 		return (Z_ERR);
1355 	}
1356 	if (door_info(doorfd, &info) == 0 &&
1357 	    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1358 		(void) close(doorfd);
1359 		return (Z_OK);
1360 	}
1361 	(void) close(doorfd);
1362 	return (Z_ERR);
1363 }
1364 
1365 static int
1366 call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg)
1367 {
1368 	char doorpath[PATH_MAX];
1369 	int doorfd, result;
1370 	door_arg_t darg;
1371 
1372 	zoneid_t zoneid;
1373 	uint64_t uniqid = 0;
1374 
1375 	zone_cmd_rval_t *rvalp;
1376 	size_t rlen;
1377 	char *cp, *errbuf;
1378 
1379 	rlen = getpagesize();
1380 	if ((rvalp = malloc(rlen)) == NULL) {
1381 		zerror(gettext("failed to allocate %lu bytes: %s"), rlen,
1382 		    strerror(errno));
1383 		return (-1);
1384 	}
1385 
1386 	if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) {
1387 		(void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1388 		    sizeof (uniqid));
1389 	}
1390 	arg->uniqid = uniqid;
1391 	(void) strlcpy(arg->locale, locale, sizeof (arg->locale));
1392 	if (!get_doorname(zone_name, doorpath)) {
1393 		zerror(gettext("alternate root path is too long"));
1394 		free(rvalp);
1395 		return (-1);
1396 	}
1397 
1398 	/*
1399 	 * Loop trying to start zoneadmd; if something goes seriously
1400 	 * wrong we break out and fail.
1401 	 */
1402 	for (;;) {
1403 		if (start_zoneadmd(zone_name) != Z_OK)
1404 			break;
1405 
1406 		if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1407 			zperror(gettext("failed to open zone door"), B_FALSE);
1408 			break;
1409 		}
1410 
1411 		darg.data_ptr = (char *)arg;
1412 		darg.data_size = sizeof (*arg);
1413 		darg.desc_ptr = NULL;
1414 		darg.desc_num = 0;
1415 		darg.rbuf = (char *)rvalp;
1416 		darg.rsize = rlen;
1417 		if (door_call(doorfd, &darg) != 0) {
1418 			(void) close(doorfd);
1419 			/*
1420 			 * We'll get EBADF if the door has been revoked.
1421 			 */
1422 			if (errno != EBADF) {
1423 				zperror(gettext("door_call failed"), B_FALSE);
1424 				break;
1425 			}
1426 			continue;	/* take another lap */
1427 		}
1428 		(void) close(doorfd);
1429 
1430 		if (darg.data_size == 0) {
1431 			/* Door server is going away; kick it again. */
1432 			continue;
1433 		}
1434 
1435 		errbuf = rvalp->errbuf;
1436 		while (*errbuf != '\0') {
1437 			/*
1438 			 * Remove any newlines since zerror()
1439 			 * will append one automatically.
1440 			 */
1441 			cp = strchr(errbuf, '\n');
1442 			if (cp != NULL)
1443 				*cp = '\0';
1444 			zerror("%s", errbuf);
1445 			if (cp == NULL)
1446 				break;
1447 			errbuf = cp + 1;
1448 		}
1449 		result = rvalp->rval == 0 ? 0 : -1;
1450 		free(rvalp);
1451 		return (result);
1452 	}
1453 
1454 	free(rvalp);
1455 	return (-1);
1456 }
1457 
1458 static int
1459 invoke_brand_handler(int cmd_num, char *argv[])
1460 {
1461 	zone_dochandle_t handle;
1462 	int err;
1463 
1464 	if ((handle = zonecfg_init_handle()) == NULL) {
1465 		zperror(cmd_to_str(cmd_num), B_TRUE);
1466 		return (Z_ERR);
1467 	}
1468 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1469 		errno = err;
1470 		zperror(cmd_to_str(cmd_num), B_TRUE);
1471 		zonecfg_fini_handle(handle);
1472 		return (Z_ERR);
1473 	}
1474 	if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1475 		zonecfg_fini_handle(handle);
1476 		return (Z_ERR);
1477 	}
1478 	zonecfg_fini_handle(handle);
1479 	return (Z_OK);
1480 }
1481 
1482 static int
1483 ready_func(int argc, char *argv[])
1484 {
1485 	zone_cmd_arg_t zarg;
1486 	int arg;
1487 
1488 	if (zonecfg_in_alt_root()) {
1489 		zerror(gettext("cannot ready zone in alternate root"));
1490 		return (Z_ERR);
1491 	}
1492 
1493 	optind = 0;
1494 	if ((arg = getopt(argc, argv, "?")) != EOF) {
1495 		switch (arg) {
1496 		case '?':
1497 			sub_usage(SHELP_READY, CMD_READY);
1498 			return (optopt == '?' ? Z_OK : Z_USAGE);
1499 		default:
1500 			sub_usage(SHELP_READY, CMD_READY);
1501 			return (Z_USAGE);
1502 		}
1503 	}
1504 	if (argc > optind) {
1505 		sub_usage(SHELP_READY, CMD_READY);
1506 		return (Z_USAGE);
1507 	}
1508 	if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE)
1509 	    != Z_OK)
1510 		return (Z_ERR);
1511 	if (verify_details(CMD_READY, argv) != Z_OK)
1512 		return (Z_ERR);
1513 
1514 	zarg.cmd = Z_READY;
1515 	if (call_zoneadmd(target_zone, &zarg) != 0) {
1516 		zerror(gettext("call to %s failed"), "zoneadmd");
1517 		return (Z_ERR);
1518 	}
1519 	return (Z_OK);
1520 }
1521 
1522 static int
1523 boot_func(int argc, char *argv[])
1524 {
1525 	zone_cmd_arg_t zarg;
1526 	boolean_t force = B_FALSE;
1527 	int arg;
1528 
1529 	if (zonecfg_in_alt_root()) {
1530 		zerror(gettext("cannot boot zone in alternate root"));
1531 		return (Z_ERR);
1532 	}
1533 
1534 	zarg.bootbuf[0] = '\0';
1535 
1536 	/*
1537 	 * The following getopt processes arguments to zone boot; that
1538 	 * is to say, the [here] portion of the argument string:
1539 	 *
1540 	 *	zoneadm -z myzone boot [here] -- -v -m verbose
1541 	 *
1542 	 * Where [here] can either be nothing, -? (in which case we bail
1543 	 * and print usage), -f (a private option to indicate that the
1544 	 * boot operation should be 'forced'), or -s.  Support for -s is
1545 	 * vestigal and obsolete, but is retained because it was a
1546 	 * documented interface and there are known consumers including
1547 	 * admin/install; the proper way to specify boot arguments like -s
1548 	 * is:
1549 	 *
1550 	 *	zoneadm -z myzone boot -- -s -v -m verbose.
1551 	 */
1552 	optind = 0;
1553 	while ((arg = getopt(argc, argv, "?fs")) != EOF) {
1554 		switch (arg) {
1555 		case '?':
1556 			sub_usage(SHELP_BOOT, CMD_BOOT);
1557 			return (optopt == '?' ? Z_OK : Z_USAGE);
1558 		case 's':
1559 			(void) strlcpy(zarg.bootbuf, "-s",
1560 			    sizeof (zarg.bootbuf));
1561 			break;
1562 		case 'f':
1563 			force = B_TRUE;
1564 			break;
1565 		default:
1566 			sub_usage(SHELP_BOOT, CMD_BOOT);
1567 			return (Z_USAGE);
1568 		}
1569 	}
1570 
1571 	for (; optind < argc; optind++) {
1572 		if (strlcat(zarg.bootbuf, argv[optind],
1573 		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1574 			zerror(gettext("Boot argument list too long"));
1575 			return (Z_ERR);
1576 		}
1577 		if (optind < argc - 1)
1578 			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1579 			    sizeof (zarg.bootbuf)) {
1580 				zerror(gettext("Boot argument list too long"));
1581 				return (Z_ERR);
1582 			}
1583 	}
1584 	if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force)
1585 	    != Z_OK)
1586 		return (Z_ERR);
1587 	if (verify_details(CMD_BOOT, argv) != Z_OK)
1588 		return (Z_ERR);
1589 	zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT;
1590 	if (call_zoneadmd(target_zone, &zarg) != 0) {
1591 		zerror(gettext("call to %s failed"), "zoneadmd");
1592 		return (Z_ERR);
1593 	}
1594 
1595 	return (Z_OK);
1596 }
1597 
1598 static void
1599 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
1600 {
1601 	ssize_t result;
1602 	uuid_t uuid;
1603 	FILE *fp;
1604 	ushort_t flags;
1605 
1606 	(void) memset(zeptr, 0, sizeof (*zeptr));
1607 
1608 	zeptr->zid = zid;
1609 
1610 	/*
1611 	 * Since we're looking up our own (non-global) zone name,
1612 	 * we can be assured that it will succeed.
1613 	 */
1614 	result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
1615 	assert(result >= 0);
1616 	if (zonecfg_is_scratch(zeptr->zname) &&
1617 	    (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
1618 		(void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
1619 		    sizeof (zeptr->zname), NULL, 0);
1620 		zonecfg_close_scratch(fp);
1621 	}
1622 
1623 	if (is_system_labeled()) {
1624 		(void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
1625 		    sizeof (zeptr->zroot));
1626 		(void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME,
1627 			    sizeof (zeptr->zbrand));
1628 	} else {
1629 		(void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
1630 		(void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand,
1631 		    sizeof (zeptr->zbrand));
1632 	}
1633 
1634 	zeptr->zstate_str = "running";
1635 	if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
1636 	    !uuid_is_null(uuid))
1637 		uuid_unparse(uuid, zeptr->zuuid);
1638 
1639 	if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
1640 		zperror2(zeptr->zname, gettext("could not get zone flags"));
1641 		exit(Z_ERR);
1642 	}
1643 	if (flags & ZF_NET_EXCL)
1644 		zeptr->ziptype = ZS_EXCLUSIVE;
1645 	else
1646 		zeptr->ziptype = ZS_SHARED;
1647 }
1648 
1649 static int
1650 list_func(int argc, char *argv[])
1651 {
1652 	zone_entry_t *zentp, zent;
1653 	int arg, retv;
1654 	boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE;
1655 	zone_state_t min_state = ZONE_STATE_RUNNING;
1656 	zoneid_t zone_id = getzoneid();
1657 
1658 	if (target_zone == NULL) {
1659 		/* all zones: default view to running but allow override */
1660 		optind = 0;
1661 		while ((arg = getopt(argc, argv, "?cipv")) != EOF) {
1662 			switch (arg) {
1663 			case '?':
1664 				sub_usage(SHELP_LIST, CMD_LIST);
1665 				return (optopt == '?' ? Z_OK : Z_USAGE);
1666 				/*
1667 				 * The 'i' and 'c' options are not mutually
1668 				 * exclusive so if 'c' is given, then min_state
1669 				 * is set to 0 (ZONE_STATE_CONFIGURED) which is
1670 				 * the lowest possible state.  If 'i' is given,
1671 				 * then min_state is set to be the lowest state
1672 				 * so far.
1673 				 */
1674 			case 'c':
1675 				min_state = ZONE_STATE_CONFIGURED;
1676 				break;
1677 			case 'i':
1678 				min_state = min(ZONE_STATE_INSTALLED,
1679 				    min_state);
1680 
1681 				break;
1682 			case 'p':
1683 				parsable = B_TRUE;
1684 				break;
1685 			case 'v':
1686 				verbose = B_TRUE;
1687 				break;
1688 			default:
1689 				sub_usage(SHELP_LIST, CMD_LIST);
1690 				return (Z_USAGE);
1691 			}
1692 		}
1693 		if (parsable && verbose) {
1694 			zerror(gettext("%s -p and -v are mutually exclusive."),
1695 			    cmd_to_str(CMD_LIST));
1696 			return (Z_ERR);
1697 		}
1698 		if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
1699 			retv = zone_print_list(min_state, verbose, parsable);
1700 		} else {
1701 			fake_up_local_zone(zone_id, &zent);
1702 			retv = Z_OK;
1703 			zone_print(&zent, verbose, parsable);
1704 		}
1705 		return (retv);
1706 	}
1707 
1708 	/*
1709 	 * Specific target zone: disallow -i/-c suboptions.
1710 	 */
1711 	optind = 0;
1712 	while ((arg = getopt(argc, argv, "?pv")) != EOF) {
1713 		switch (arg) {
1714 		case '?':
1715 			sub_usage(SHELP_LIST, CMD_LIST);
1716 			return (optopt == '?' ? Z_OK : Z_USAGE);
1717 		case 'p':
1718 			parsable = B_TRUE;
1719 			break;
1720 		case 'v':
1721 			verbose = B_TRUE;
1722 			break;
1723 		default:
1724 			sub_usage(SHELP_LIST, CMD_LIST);
1725 			return (Z_USAGE);
1726 		}
1727 	}
1728 	if (parsable && verbose) {
1729 		zerror(gettext("%s -p and -v are mutually exclusive."),
1730 		    cmd_to_str(CMD_LIST));
1731 		return (Z_ERR);
1732 	}
1733 	if (argc > optind) {
1734 		sub_usage(SHELP_LIST, CMD_LIST);
1735 		return (Z_USAGE);
1736 	}
1737 	if (zone_id != GLOBAL_ZONEID) {
1738 		fake_up_local_zone(zone_id, &zent);
1739 		/*
1740 		 * main() will issue a Z_NO_ZONE error if it cannot get an
1741 		 * id for target_zone, which in a non-global zone should
1742 		 * happen for any zone name except `zonename`.  Thus we
1743 		 * assert() that here but don't otherwise check.
1744 		 */
1745 		assert(strcmp(zent.zname, target_zone) == 0);
1746 		zone_print(&zent, verbose, parsable);
1747 		output = B_TRUE;
1748 	} else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
1749 		zone_print(zentp, verbose, parsable);
1750 		output = B_TRUE;
1751 	} else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
1752 	    &zent) == Z_OK) {
1753 		zone_print(&zent, verbose, parsable);
1754 		output = B_TRUE;
1755 	}
1756 
1757 	/*
1758 	 * Invoke brand-specific handler. Note that we do this
1759 	 * only if we're in the global zone, and target_zone is specified
1760 	 * and it is not the global zone.
1761 	 */
1762 	if (zone_id == GLOBAL_ZONEID && target_zone != NULL &&
1763 	    strcmp(target_zone, GLOBAL_ZONENAME) != 0)
1764 		if (invoke_brand_handler(CMD_LIST, argv) != Z_OK)
1765 			return (Z_ERR);
1766 
1767 	return (output ? Z_OK : Z_ERR);
1768 }
1769 
1770 static void
1771 sigterm(int sig)
1772 {
1773 	/*
1774 	 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop,
1775 	 * then propagate the signal to our process group.
1776 	 */
1777 	assert(sig == SIGINT || sig == SIGTERM);
1778 	(void) sigset(SIGINT, SIG_IGN);
1779 	(void) sigset(SIGTERM, SIG_IGN);
1780 	(void) kill(0, sig);
1781 	child_killed = B_TRUE;
1782 }
1783 
1784 static int
1785 do_subproc(char *cmdbuf)
1786 {
1787 	char inbuf[1024];	/* arbitrary large amount */
1788 	FILE *file;
1789 
1790 	do_subproc_cnt++;
1791 	child_killed = B_FALSE;
1792 	/*
1793 	 * We use popen(3c) to launch child processes for [un]install;
1794 	 * this library call does not return a PID, so we have to kill
1795 	 * the whole process group.  To avoid killing our parent, we
1796 	 * become a process group leader here.  But doing so can wreak
1797 	 * havoc with reading from stdin when launched by a non-job-control
1798 	 * shell, so we close stdin and reopen it as /dev/null first.
1799 	 */
1800 	(void) close(STDIN_FILENO);
1801 	(void) openat(STDIN_FILENO, "/dev/null", O_RDONLY);
1802 	if (!zoneadm_is_nested)
1803 		(void) setpgid(0, 0);
1804 	(void) sigset(SIGINT, sigterm);
1805 	(void) sigset(SIGTERM, sigterm);
1806 	file = popen(cmdbuf, "r");
1807 	for (;;) {
1808 		if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL)
1809 			break;
1810 		(void) fputs(inbuf, stdout);
1811 	}
1812 	(void) sigset(SIGINT, SIG_DFL);
1813 	(void) sigset(SIGTERM, SIG_DFL);
1814 	return (pclose(file));
1815 }
1816 
1817 static int
1818 do_subproc_interactive(char *cmdbuf)
1819 {
1820 	void (*saveint)(int);
1821 	void (*saveterm)(int);
1822 	void (*savequit)(int);
1823 	void (*savehup)(int);
1824 	int pid, child, status;
1825 
1826 	/*
1827 	 * do_subproc() links stdin to /dev/null, which would break any
1828 	 * interactive subprocess we try to launch here.  Similarly, we
1829 	 * can't have been launched as a subprocess ourselves.
1830 	 */
1831 	assert(do_subproc_cnt == 0 && !zoneadm_is_nested);
1832 
1833 	if ((child = vfork()) == 0) {
1834 		(void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL);
1835 	}
1836 
1837 	if (child == -1)
1838 		return (-1);
1839 
1840 	saveint = sigset(SIGINT, SIG_IGN);
1841 	saveterm = sigset(SIGTERM, SIG_IGN);
1842 	savequit = sigset(SIGQUIT, SIG_IGN);
1843 	savehup = sigset(SIGHUP, SIG_IGN);
1844 
1845 	while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
1846 		;
1847 
1848 	(void) sigset(SIGINT, saveint);
1849 	(void) sigset(SIGTERM, saveterm);
1850 	(void) sigset(SIGQUIT, savequit);
1851 	(void) sigset(SIGHUP, savehup);
1852 
1853 	return (pid == -1 ? -1 : status);
1854 }
1855 
1856 static int
1857 subproc_status(const char *cmd, int status, boolean_t verbose_failure)
1858 {
1859 	if (WIFEXITED(status)) {
1860 		int exit_code = WEXITSTATUS(status);
1861 
1862 		if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK))
1863 			zerror(gettext("'%s' failed with exit code %d."), cmd,
1864 			    exit_code);
1865 
1866 		return (exit_code);
1867 	} else if (WIFSIGNALED(status)) {
1868 		int signal = WTERMSIG(status);
1869 		char sigstr[SIG2STR_MAX];
1870 
1871 		if (sig2str(signal, sigstr) == 0) {
1872 			zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
1873 			    sigstr);
1874 		} else {
1875 			zerror(gettext("'%s' terminated by an unknown signal."),
1876 			    cmd);
1877 		}
1878 	} else {
1879 		zerror(gettext("'%s' failed for unknown reasons."), cmd);
1880 	}
1881 
1882 	/*
1883 	 * Assume a subprocess that died due to a signal or an unknown error
1884 	 * should be considered an exit code of ZONE_SUBPROC_FATAL, as the
1885 	 * user will likely need to do some manual cleanup.
1886 	 */
1887 	return (ZONE_SUBPROC_FATAL);
1888 }
1889 
1890 /*
1891  * Various sanity checks; make sure:
1892  * 1. We're in the global zone.
1893  * 2. The calling user has sufficient privilege.
1894  * 3. The target zone is neither the global zone nor anything starting with
1895  *    "SUNW".
1896  * 4a. If we're looking for a 'not running' (i.e., configured or installed)
1897  *     zone, the name service knows about it.
1898  * 4b. For some operations which expect a zone not to be running, that it is
1899  *     not already running (or ready).
1900  */
1901 static int
1902 sanity_check(char *zone, int cmd_num, boolean_t running,
1903     boolean_t unsafe_when_running, boolean_t force)
1904 {
1905 	zone_entry_t *zent;
1906 	priv_set_t *privset;
1907 	zone_state_t state, min_state;
1908 	char kernzone[ZONENAME_MAX];
1909 	FILE *fp;
1910 
1911 	if (getzoneid() != GLOBAL_ZONEID) {
1912 		switch (cmd_num) {
1913 		case CMD_HALT:
1914 			zerror(gettext("use %s to %s this zone."), "halt(1M)",
1915 			    cmd_to_str(cmd_num));
1916 			break;
1917 		case CMD_REBOOT:
1918 			zerror(gettext("use %s to %s this zone."),
1919 			    "reboot(1M)", cmd_to_str(cmd_num));
1920 			break;
1921 		default:
1922 			zerror(gettext("must be in the global zone to %s a "
1923 			    "zone."), cmd_to_str(cmd_num));
1924 			break;
1925 		}
1926 		return (Z_ERR);
1927 	}
1928 
1929 	if ((privset = priv_allocset()) == NULL) {
1930 		zerror(gettext("%s failed"), "priv_allocset");
1931 		return (Z_ERR);
1932 	}
1933 
1934 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1935 		zerror(gettext("%s failed"), "getppriv");
1936 		priv_freeset(privset);
1937 		return (Z_ERR);
1938 	}
1939 
1940 	if (priv_isfullset(privset) == B_FALSE) {
1941 		zerror(gettext("only a privileged user may %s a zone."),
1942 		    cmd_to_str(cmd_num));
1943 		priv_freeset(privset);
1944 		return (Z_ERR);
1945 	}
1946 	priv_freeset(privset);
1947 
1948 	if (zone == NULL) {
1949 		zerror(gettext("no zone specified"));
1950 		return (Z_ERR);
1951 	}
1952 
1953 	if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
1954 		zerror(gettext("%s operation is invalid for the global zone."),
1955 		    cmd_to_str(cmd_num));
1956 		return (Z_ERR);
1957 	}
1958 
1959 	if (strncmp(zone, "SUNW", 4) == 0) {
1960 		zerror(gettext("%s operation is invalid for zones starting "
1961 		    "with SUNW."), cmd_to_str(cmd_num));
1962 		return (Z_ERR);
1963 	}
1964 
1965 	if (!is_native_zone && cmd_num == CMD_MOUNT) {
1966 		zerror(gettext("%s operation is invalid for branded zones."),
1967 		    cmd_to_str(cmd_num));
1968 			return (Z_ERR);
1969 	}
1970 
1971 	if (!zonecfg_in_alt_root()) {
1972 		zent = lookup_running_zone(zone);
1973 	} else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
1974 		zent = NULL;
1975 	} else {
1976 		if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
1977 		    kernzone, sizeof (kernzone)) == 0)
1978 			zent = lookup_running_zone(kernzone);
1979 		else
1980 			zent = NULL;
1981 		zonecfg_close_scratch(fp);
1982 	}
1983 
1984 	/*
1985 	 * Look up from the kernel for 'running' zones.
1986 	 */
1987 	if (running && !force) {
1988 		if (zent == NULL) {
1989 			zerror(gettext("not running"));
1990 			return (Z_ERR);
1991 		}
1992 	} else {
1993 		int err;
1994 
1995 		if (unsafe_when_running && zent != NULL) {
1996 			/* check whether the zone is ready or running */
1997 			if ((err = zone_get_state(zent->zname,
1998 			    &zent->zstate_num)) != Z_OK) {
1999 				errno = err;
2000 				zperror2(zent->zname,
2001 				    gettext("could not get state"));
2002 				/* can't tell, so hedge */
2003 				zent->zstate_str = "ready/running";
2004 			} else {
2005 				zent->zstate_str =
2006 				    zone_state_str(zent->zstate_num);
2007 			}
2008 			zerror(gettext("%s operation is invalid for %s zones."),
2009 			    cmd_to_str(cmd_num), zent->zstate_str);
2010 			return (Z_ERR);
2011 		}
2012 		if ((err = zone_get_state(zone, &state)) != Z_OK) {
2013 			errno = err;
2014 			zperror2(zone, gettext("could not get state"));
2015 			return (Z_ERR);
2016 		}
2017 		switch (cmd_num) {
2018 		case CMD_UNINSTALL:
2019 			if (state == ZONE_STATE_CONFIGURED) {
2020 				zerror(gettext("is already in state '%s'."),
2021 				    zone_state_str(ZONE_STATE_CONFIGURED));
2022 				return (Z_ERR);
2023 			}
2024 			break;
2025 		case CMD_ATTACH:
2026 		case CMD_CLONE:
2027 		case CMD_INSTALL:
2028 			if (state == ZONE_STATE_INSTALLED) {
2029 				zerror(gettext("is already %s."),
2030 				    zone_state_str(ZONE_STATE_INSTALLED));
2031 				return (Z_ERR);
2032 			} else if (state == ZONE_STATE_INCOMPLETE) {
2033 				zerror(gettext("zone is %s; %s required."),
2034 				    zone_state_str(ZONE_STATE_INCOMPLETE),
2035 				    cmd_to_str(CMD_UNINSTALL));
2036 				return (Z_ERR);
2037 			}
2038 			break;
2039 		case CMD_DETACH:
2040 		case CMD_MOVE:
2041 		case CMD_READY:
2042 		case CMD_BOOT:
2043 		case CMD_MOUNT:
2044 		case CMD_MARK:
2045 			if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
2046 			    force)
2047 				min_state = ZONE_STATE_INCOMPLETE;
2048 			else
2049 				min_state = ZONE_STATE_INSTALLED;
2050 
2051 			if (force && cmd_num == CMD_BOOT && is_native_zone) {
2052 				zerror(gettext("Only branded zones may be "
2053 				    "force-booted."));
2054 				return (Z_ERR);
2055 			}
2056 
2057 			if (state < min_state) {
2058 				zerror(gettext("must be %s before %s."),
2059 				    zone_state_str(min_state),
2060 				    cmd_to_str(cmd_num));
2061 				return (Z_ERR);
2062 			}
2063 			break;
2064 		case CMD_VERIFY:
2065 			if (state == ZONE_STATE_INCOMPLETE) {
2066 				zerror(gettext("zone is %s; %s required."),
2067 				    zone_state_str(ZONE_STATE_INCOMPLETE),
2068 				    cmd_to_str(CMD_UNINSTALL));
2069 				return (Z_ERR);
2070 			}
2071 			break;
2072 		case CMD_UNMOUNT:
2073 			if (state != ZONE_STATE_MOUNTED) {
2074 				zerror(gettext("must be %s before %s."),
2075 				    zone_state_str(ZONE_STATE_MOUNTED),
2076 				    cmd_to_str(cmd_num));
2077 				return (Z_ERR);
2078 			}
2079 			break;
2080 		}
2081 	}
2082 	return (Z_OK);
2083 }
2084 
2085 static int
2086 halt_func(int argc, char *argv[])
2087 {
2088 	zone_cmd_arg_t zarg;
2089 	int arg;
2090 
2091 	if (zonecfg_in_alt_root()) {
2092 		zerror(gettext("cannot halt zone in alternate root"));
2093 		return (Z_ERR);
2094 	}
2095 
2096 	optind = 0;
2097 	if ((arg = getopt(argc, argv, "?")) != EOF) {
2098 		switch (arg) {
2099 		case '?':
2100 			sub_usage(SHELP_HALT, CMD_HALT);
2101 			return (optopt == '?' ? Z_OK : Z_USAGE);
2102 		default:
2103 			sub_usage(SHELP_HALT, CMD_HALT);
2104 			return (Z_USAGE);
2105 		}
2106 	}
2107 	if (argc > optind) {
2108 		sub_usage(SHELP_HALT, CMD_HALT);
2109 		return (Z_USAGE);
2110 	}
2111 	/*
2112 	 * zoneadmd should be the one to decide whether or not to proceed,
2113 	 * so even though it seems that the fourth parameter below should
2114 	 * perhaps be B_TRUE, it really shouldn't be.
2115 	 */
2116 	if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
2117 	    != Z_OK)
2118 		return (Z_ERR);
2119 
2120 	/*
2121 	 * Invoke brand-specific handler.
2122 	 */
2123 	if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
2124 		return (Z_ERR);
2125 
2126 	zarg.cmd = Z_HALT;
2127 	return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2128 }
2129 
2130 static int
2131 reboot_func(int argc, char *argv[])
2132 {
2133 	zone_cmd_arg_t zarg;
2134 	int arg;
2135 
2136 	if (zonecfg_in_alt_root()) {
2137 		zerror(gettext("cannot reboot zone in alternate root"));
2138 		return (Z_ERR);
2139 	}
2140 
2141 	optind = 0;
2142 	if ((arg = getopt(argc, argv, "?")) != EOF) {
2143 		switch (arg) {
2144 		case '?':
2145 			sub_usage(SHELP_REBOOT, CMD_REBOOT);
2146 			return (optopt == '?' ? Z_OK : Z_USAGE);
2147 		default:
2148 			sub_usage(SHELP_REBOOT, CMD_REBOOT);
2149 			return (Z_USAGE);
2150 		}
2151 	}
2152 
2153 	zarg.bootbuf[0] = '\0';
2154 	for (; optind < argc; optind++) {
2155 		if (strlcat(zarg.bootbuf, argv[optind],
2156 		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
2157 			zerror(gettext("Boot argument list too long"));
2158 			return (Z_ERR);
2159 		}
2160 		if (optind < argc - 1)
2161 			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
2162 			    sizeof (zarg.bootbuf)) {
2163 				zerror(gettext("Boot argument list too long"));
2164 				return (Z_ERR);
2165 			}
2166 	}
2167 
2168 
2169 	/*
2170 	 * zoneadmd should be the one to decide whether or not to proceed,
2171 	 * so even though it seems that the fourth parameter below should
2172 	 * perhaps be B_TRUE, it really shouldn't be.
2173 	 */
2174 	if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE)
2175 	    != Z_OK)
2176 		return (Z_ERR);
2177 	if (verify_details(CMD_REBOOT, argv) != Z_OK)
2178 		return (Z_ERR);
2179 
2180 	zarg.cmd = Z_REBOOT;
2181 	return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2182 }
2183 
2184 static int
2185 verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[])
2186 {
2187 	char cmdbuf[MAXPATHLEN];
2188 	int err;
2189 	char zonepath[MAXPATHLEN];
2190 	brand_handle_t bh = NULL;
2191 	int status, i;
2192 
2193 	/*
2194 	 * Fetch the verify command from the brand configuration.
2195 	 * "exec" the command so that the returned status is that of
2196 	 * the command and not the shell.
2197 	 */
2198 	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2199 	    Z_OK) {
2200 		errno = err;
2201 		zperror(cmd_to_str(cmd_num), B_TRUE);
2202 		return (Z_ERR);
2203 	}
2204 	if ((bh = brand_open(target_brand)) == NULL) {
2205 		zerror(gettext("missing or invalid brand"));
2206 		return (Z_ERR);
2207 	}
2208 
2209 	/*
2210 	 * If the brand has its own verification routine, execute it now.
2211 	 * The verification routine validates the intended zoneadm
2212 	 * operation for the specific brand. The zoneadm subcommand and
2213 	 * all its arguments are passed to the routine.
2214 	 */
2215 	(void) strcpy(cmdbuf, EXEC_PREFIX);
2216 	err = brand_get_verify_adm(bh, target_zone, zonepath,
2217 	    cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN, 0, NULL);
2218 	brand_close(bh);
2219 	if (err != 0)
2220 		return (Z_BRAND_ERROR);
2221 	if (strlen(cmdbuf) <= EXEC_LEN)
2222 		return (Z_OK);
2223 
2224 	if (strlcat(cmdbuf, cmd_to_str(cmd_num),
2225 	    sizeof (cmdbuf)) >= sizeof (cmdbuf))
2226 		return (Z_ERR);
2227 
2228 	/* Build the argv string */
2229 	i = 0;
2230 	while (argv[i] != NULL) {
2231 		if ((strlcat(cmdbuf, " ",
2232 		    sizeof (cmdbuf)) >= sizeof (cmdbuf)) ||
2233 		    (strlcat(cmdbuf, argv[i++],
2234 		    sizeof (cmdbuf)) >= sizeof (cmdbuf)))
2235 			return (Z_ERR);
2236 	}
2237 
2238 	status = do_subproc_interactive(cmdbuf);
2239 	err = subproc_status(gettext("brand-specific verification"),
2240 	    status, B_FALSE);
2241 
2242 	return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR);
2243 }
2244 
2245 static int
2246 verify_rctls(zone_dochandle_t handle)
2247 {
2248 	struct zone_rctltab rctltab;
2249 	size_t rbs = rctlblk_size();
2250 	rctlblk_t *rctlblk;
2251 	int error = Z_INVAL;
2252 
2253 	if ((rctlblk = malloc(rbs)) == NULL) {
2254 		zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
2255 		    strerror(errno));
2256 		return (Z_NOMEM);
2257 	}
2258 
2259 	if (zonecfg_setrctlent(handle) != Z_OK) {
2260 		zerror(gettext("zonecfg_setrctlent failed"));
2261 		free(rctlblk);
2262 		return (error);
2263 	}
2264 
2265 	rctltab.zone_rctl_valptr = NULL;
2266 	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2267 		struct zone_rctlvaltab *rctlval;
2268 		const char *name = rctltab.zone_rctl_name;
2269 
2270 		if (!zonecfg_is_rctl(name)) {
2271 			zerror(gettext("WARNING: Ignoring unrecognized rctl "
2272 			    "'%s'."),  name);
2273 			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2274 			rctltab.zone_rctl_valptr = NULL;
2275 			continue;
2276 		}
2277 
2278 		for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
2279 		    rctlval = rctlval->zone_rctlval_next) {
2280 			if (zonecfg_construct_rctlblk(rctlval, rctlblk)
2281 			    != Z_OK) {
2282 				zerror(gettext("invalid rctl value: "
2283 				    "(priv=%s,limit=%s,action%s)"),
2284 				    rctlval->zone_rctlval_priv,
2285 				    rctlval->zone_rctlval_limit,
2286 				    rctlval->zone_rctlval_action);
2287 				goto out;
2288 			}
2289 			if (!zonecfg_valid_rctl(name, rctlblk)) {
2290 				zerror(gettext("(priv=%s,limit=%s,action=%s) "
2291 				    "is not a valid value for rctl '%s'"),
2292 				    rctlval->zone_rctlval_priv,
2293 				    rctlval->zone_rctlval_limit,
2294 				    rctlval->zone_rctlval_action,
2295 				    name);
2296 				goto out;
2297 			}
2298 		}
2299 		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2300 	}
2301 	rctltab.zone_rctl_valptr = NULL;
2302 	error = Z_OK;
2303 out:
2304 	zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2305 	(void) zonecfg_endrctlent(handle);
2306 	free(rctlblk);
2307 	return (error);
2308 }
2309 
2310 static int
2311 verify_pool(zone_dochandle_t handle)
2312 {
2313 	char poolname[MAXPATHLEN];
2314 	pool_conf_t *poolconf;
2315 	pool_t *pool;
2316 	int status;
2317 	int error;
2318 
2319 	/*
2320 	 * This ends up being very similar to the check done in zoneadmd.
2321 	 */
2322 	error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
2323 	if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
2324 		/*
2325 		 * No pool specified.
2326 		 */
2327 		return (0);
2328 	}
2329 	if (error != Z_OK) {
2330 		zperror(gettext("Unable to retrieve pool name from "
2331 		    "configuration"), B_TRUE);
2332 		return (error);
2333 	}
2334 	/*
2335 	 * Don't do anything if pools aren't enabled.
2336 	 */
2337 	if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
2338 		zerror(gettext("WARNING: pools facility not active; "
2339 		    "zone will not be bound to pool '%s'."), poolname);
2340 		return (Z_OK);
2341 	}
2342 	/*
2343 	 * Try to provide a sane error message if the requested pool doesn't
2344 	 * exist.  It isn't clear that pools-related failures should
2345 	 * necessarily translate to a failure to verify the zone configuration,
2346 	 * hence they are not considered errors.
2347 	 */
2348 	if ((poolconf = pool_conf_alloc()) == NULL) {
2349 		zerror(gettext("WARNING: pool_conf_alloc failed; "
2350 		    "using default pool"));
2351 		return (Z_OK);
2352 	}
2353 	if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
2354 	    PO_SUCCESS) {
2355 		zerror(gettext("WARNING: pool_conf_open failed; "
2356 		    "using default pool"));
2357 		pool_conf_free(poolconf);
2358 		return (Z_OK);
2359 	}
2360 	pool = pool_get_pool(poolconf, poolname);
2361 	(void) pool_conf_close(poolconf);
2362 	pool_conf_free(poolconf);
2363 	if (pool == NULL) {
2364 		zerror(gettext("WARNING: pool '%s' not found. "
2365 		    "using default pool"), poolname);
2366 	}
2367 
2368 	return (Z_OK);
2369 }
2370 
2371 static int
2372 verify_ipd(zone_dochandle_t handle)
2373 {
2374 	int return_code = Z_OK;
2375 	struct zone_fstab fstab;
2376 	struct stat st;
2377 	char specdir[MAXPATHLEN];
2378 
2379 	if (zonecfg_setipdent(handle) != Z_OK) {
2380 		/*
2381 		 * TRANSLATION_NOTE
2382 		 * inherit-pkg-dirs is a literal that should not be translated.
2383 		 */
2384 		(void) fprintf(stderr, gettext("could not verify "
2385 		    "inherit-pkg-dirs: unable to enumerate mounts\n"));
2386 		return (Z_ERR);
2387 	}
2388 	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
2389 		/*
2390 		 * Verify fs_dir exists.
2391 		 */
2392 		(void) snprintf(specdir, sizeof (specdir), "%s%s",
2393 		    zonecfg_get_root(), fstab.zone_fs_dir);
2394 		if (stat(specdir, &st) != 0) {
2395 			/*
2396 			 * TRANSLATION_NOTE
2397 			 * inherit-pkg-dir is a literal that should not be
2398 			 * translated.
2399 			 */
2400 			(void) fprintf(stderr, gettext("could not verify "
2401 			    "inherit-pkg-dir %s: %s\n"),
2402 			    fstab.zone_fs_dir, strerror(errno));
2403 			return_code = Z_ERR;
2404 		}
2405 		if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2406 			/*
2407 			 * TRANSLATION_NOTE
2408 			 * inherit-pkg-dir and NFS are literals that should
2409 			 * not be translated.
2410 			 */
2411 			(void) fprintf(stderr, gettext("cannot verify "
2412 			    "inherit-pkg-dir %s: NFS mounted file system.\n"
2413 			    "\tA local file system must be used.\n"),
2414 			    fstab.zone_fs_dir);
2415 			return_code = Z_ERR;
2416 		}
2417 	}
2418 	(void) zonecfg_endipdent(handle);
2419 
2420 	return (return_code);
2421 }
2422 
2423 /*
2424  * Verify that the special device/file system exists and is valid.
2425  */
2426 static int
2427 verify_fs_special(struct zone_fstab *fstab)
2428 {
2429 	struct stat st;
2430 
2431 	/*
2432 	 * This validation is really intended for standard zone administration.
2433 	 * If we are in a mini-root or some other upgrade situation where
2434 	 * we are using the scratch zone, just by-pass this.
2435 	 */
2436 	if (zonecfg_in_alt_root())
2437 		return (Z_OK);
2438 
2439 	if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
2440 		return (verify_fs_zfs(fstab));
2441 
2442 	if (stat(fstab->zone_fs_special, &st) != 0) {
2443 		(void) fprintf(stderr, gettext("could not verify fs "
2444 		    "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
2445 		    fstab->zone_fs_special, strerror(errno));
2446 		return (Z_ERR);
2447 	}
2448 
2449 	if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2450 		/*
2451 		 * TRANSLATION_NOTE
2452 		 * fs and NFS are literals that should
2453 		 * not be translated.
2454 		 */
2455 		(void) fprintf(stderr, gettext("cannot verify "
2456 		    "fs %s: NFS mounted file system.\n"
2457 		    "\tA local file system must be used.\n"),
2458 		    fstab->zone_fs_special);
2459 		return (Z_ERR);
2460 	}
2461 
2462 	return (Z_OK);
2463 }
2464 
2465 static int
2466 verify_filesystems(zone_dochandle_t handle)
2467 {
2468 	int return_code = Z_OK;
2469 	struct zone_fstab fstab;
2470 	char cmdbuf[MAXPATHLEN];
2471 	struct stat st;
2472 
2473 	/*
2474 	 * No need to verify inherit-pkg-dir fs types, as their type is
2475 	 * implicitly lofs, which is known.  Therefore, the types are only
2476 	 * verified for regular file systems below.
2477 	 *
2478 	 * Since the actual mount point is not known until the dependent mounts
2479 	 * are performed, we don't attempt any path validation here: that will
2480 	 * happen later when zoneadmd actually does the mounts.
2481 	 */
2482 	if (zonecfg_setfsent(handle) != Z_OK) {
2483 		(void) fprintf(stderr, gettext("could not verify file systems: "
2484 		    "unable to enumerate mounts\n"));
2485 		return (Z_ERR);
2486 	}
2487 	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2488 		if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2489 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2490 			    "type %s is not allowed.\n"), fstab.zone_fs_dir,
2491 			    fstab.zone_fs_type);
2492 			return_code = Z_ERR;
2493 			goto next_fs;
2494 		}
2495 		/*
2496 		 * Verify /usr/lib/fs/<fstype>/mount exists.
2497 		 */
2498 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
2499 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2500 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2501 			    "type %s is too long.\n"), fstab.zone_fs_dir,
2502 			    fstab.zone_fs_type);
2503 			return_code = Z_ERR;
2504 			goto next_fs;
2505 		}
2506 		if (stat(cmdbuf, &st) != 0) {
2507 			(void) fprintf(stderr, gettext("could not verify fs "
2508 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2509 			    cmdbuf, strerror(errno));
2510 			return_code = Z_ERR;
2511 			goto next_fs;
2512 		}
2513 		if (!S_ISREG(st.st_mode)) {
2514 			(void) fprintf(stderr, gettext("could not verify fs "
2515 			    "%s: %s is not a regular file\n"),
2516 			    fstab.zone_fs_dir, cmdbuf);
2517 			return_code = Z_ERR;
2518 			goto next_fs;
2519 		}
2520 		/*
2521 		 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is
2522 		 * set.
2523 		 */
2524 		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
2525 		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2526 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2527 			    "type %s is too long.\n"), fstab.zone_fs_dir,
2528 			    fstab.zone_fs_type);
2529 			return_code = Z_ERR;
2530 			goto next_fs;
2531 		}
2532 		if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) {
2533 			(void) fprintf(stderr, gettext("could not verify fs "
2534 			    "%s: must specify 'raw' device for %s "
2535 			    "file systems\n"),
2536 			    fstab.zone_fs_dir, fstab.zone_fs_type);
2537 			return_code = Z_ERR;
2538 			goto next_fs;
2539 		}
2540 		if (fstab.zone_fs_raw[0] != '\0' &&
2541 		    (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2542 			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2543 			    "'raw' device specified but "
2544 			    "no fsck executable exists for %s\n"),
2545 			    fstab.zone_fs_dir, fstab.zone_fs_type);
2546 			return_code = Z_ERR;
2547 			goto next_fs;
2548 		}
2549 
2550 		/* Verify fs_special. */
2551 		if ((return_code = verify_fs_special(&fstab)) != Z_OK)
2552 			goto next_fs;
2553 
2554 		/* Verify fs_raw. */
2555 		if (fstab.zone_fs_raw[0] != '\0' &&
2556 		    stat(fstab.zone_fs_raw, &st) != 0) {
2557 			/*
2558 			 * TRANSLATION_NOTE
2559 			 * fs is a literal that should not be translated.
2560 			 */
2561 			(void) fprintf(stderr, gettext("could not verify fs "
2562 			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2563 			    fstab.zone_fs_raw, strerror(errno));
2564 			return_code = Z_ERR;
2565 			goto next_fs;
2566 		}
2567 next_fs:
2568 		zonecfg_free_fs_option_list(fstab.zone_fs_options);
2569 	}
2570 	(void) zonecfg_endfsent(handle);
2571 
2572 	return (return_code);
2573 }
2574 
2575 static int
2576 verify_limitpriv(zone_dochandle_t handle)
2577 {
2578 	char *privname = NULL;
2579 	int err;
2580 	priv_set_t *privs;
2581 
2582 	if ((privs = priv_allocset()) == NULL) {
2583 		zperror(gettext("failed to allocate privilege set"), B_FALSE);
2584 		return (Z_NOMEM);
2585 	}
2586 	err = zonecfg_get_privset(handle, privs, &privname);
2587 	switch (err) {
2588 	case Z_OK:
2589 		break;
2590 	case Z_PRIV_PROHIBITED:
2591 		(void) fprintf(stderr, gettext("privilege \"%s\" is not "
2592 		    "permitted within the zone's privilege set\n"), privname);
2593 		break;
2594 	case Z_PRIV_REQUIRED:
2595 		(void) fprintf(stderr, gettext("required privilege \"%s\" is "
2596 		    "missing from the zone's privilege set\n"), privname);
2597 		break;
2598 	case Z_PRIV_UNKNOWN:
2599 		(void) fprintf(stderr, gettext("unknown privilege \"%s\" "
2600 		    "specified in the zone's privilege set\n"), privname);
2601 		break;
2602 	default:
2603 		zperror(
2604 		    gettext("failed to determine the zone's privilege set"),
2605 		    B_TRUE);
2606 		break;
2607 	}
2608 	free(privname);
2609 	priv_freeset(privs);
2610 	return (err);
2611 }
2612 
2613 static void
2614 free_local_netifs(int if_cnt, struct net_if **if_list)
2615 {
2616 	int		i;
2617 
2618 	for (i = 0; i < if_cnt; i++) {
2619 		free(if_list[i]->name);
2620 		free(if_list[i]);
2621 	}
2622 	free(if_list);
2623 }
2624 
2625 /*
2626  * Get a list of the network interfaces, along with their address families,
2627  * that are plumbed in the global zone.  See if_tcp(7p) for a description
2628  * of the ioctls used here.
2629  */
2630 static int
2631 get_local_netifs(int *if_cnt, struct net_if ***if_list)
2632 {
2633 	int		s;
2634 	int		i;
2635 	int		res = Z_OK;
2636 	int		space_needed;
2637 	int		cnt = 0;
2638 	struct		lifnum if_num;
2639 	struct		lifconf if_conf;
2640 	struct		lifreq *if_reqp;
2641 	char		*if_buf;
2642 	struct net_if	**local_ifs = NULL;
2643 
2644 	*if_cnt = 0;
2645 	*if_list = NULL;
2646 
2647 	if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
2648 		return (Z_ERR);
2649 
2650 	/*
2651 	 * Come back here in the unlikely event that the number of interfaces
2652 	 * increases between the time we get the count and the time we do the
2653 	 * SIOCGLIFCONF ioctl.
2654 	 */
2655 retry:
2656 	/* Get the number of interfaces. */
2657 	if_num.lifn_family = AF_UNSPEC;
2658 	if_num.lifn_flags = LIFC_NOXMIT;
2659 	if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
2660 		(void) close(s);
2661 		return (Z_ERR);
2662 	}
2663 
2664 	/* Get the interface configuration list. */
2665 	space_needed = if_num.lifn_count * sizeof (struct lifreq);
2666 	if ((if_buf = malloc(space_needed)) == NULL) {
2667 		(void) close(s);
2668 		return (Z_ERR);
2669 	}
2670 	if_conf.lifc_family = AF_UNSPEC;
2671 	if_conf.lifc_flags = LIFC_NOXMIT;
2672 	if_conf.lifc_len = space_needed;
2673 	if_conf.lifc_buf = if_buf;
2674 	if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
2675 		free(if_buf);
2676 		/*
2677 		 * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
2678 		 * too small.  In this case go back and get the new if cnt.
2679 		 */
2680 		if (errno == EINVAL)
2681 			goto retry;
2682 
2683 		(void) close(s);
2684 		return (Z_ERR);
2685 	}
2686 	(void) close(s);
2687 
2688 	/* Get the name and address family for each interface. */
2689 	if_reqp = if_conf.lifc_req;
2690 	for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
2691 		struct net_if	**p;
2692 		struct lifreq	req;
2693 
2694 		if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
2695 			if_reqp++;
2696 			continue;
2697 		}
2698 
2699 		if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
2700 		    SOCK_DGRAM, 0)) == -1) {
2701 			res = Z_ERR;
2702 			break;
2703 		}
2704 
2705 		(void) strncpy(req.lifr_name, if_reqp->lifr_name,
2706 		    sizeof (req.lifr_name));
2707 		if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
2708 			(void) close(s);
2709 			if_reqp++;
2710 			continue;
2711 		}
2712 
2713 		if ((p = (struct net_if **)realloc(local_ifs,
2714 		    sizeof (struct net_if *) * (cnt + 1))) == NULL) {
2715 			res = Z_ERR;
2716 			break;
2717 		}
2718 		local_ifs = p;
2719 
2720 		if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
2721 			res = Z_ERR;
2722 			break;
2723 		}
2724 
2725 		if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
2726 		    == NULL) {
2727 			free(local_ifs[cnt]);
2728 			res = Z_ERR;
2729 			break;
2730 		}
2731 		local_ifs[cnt]->af = req.lifr_addr.ss_family;
2732 		cnt++;
2733 
2734 		(void) close(s);
2735 		if_reqp++;
2736 	}
2737 
2738 	free(if_buf);
2739 
2740 	if (res != Z_OK) {
2741 		free_local_netifs(cnt, local_ifs);
2742 	} else {
2743 		*if_cnt = cnt;
2744 		*if_list = local_ifs;
2745 	}
2746 
2747 	return (res);
2748 }
2749 
2750 static char *
2751 af2str(int af)
2752 {
2753 	switch (af) {
2754 	case AF_INET:
2755 		return ("IPv4");
2756 	case AF_INET6:
2757 		return ("IPv6");
2758 	default:
2759 		return ("Unknown");
2760 	}
2761 }
2762 
2763 /*
2764  * Cross check the network interface name and address family with the
2765  * interfaces that are set up in the global zone so that we can print the
2766  * appropriate error message.
2767  */
2768 static void
2769 print_net_err(char *phys, char *addr, int af, char *msg)
2770 {
2771 	int		i;
2772 	int		local_if_cnt = 0;
2773 	struct net_if	**local_ifs = NULL;
2774 	boolean_t	found_if = B_FALSE;
2775 	boolean_t	found_af = B_FALSE;
2776 
2777 	if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
2778 		(void) fprintf(stderr,
2779 		    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2780 		    "net", "address", addr, "physical", phys, msg);
2781 		return;
2782 	}
2783 
2784 	for (i = 0; i < local_if_cnt; i++) {
2785 		if (strcmp(phys, local_ifs[i]->name) == 0) {
2786 			found_if = B_TRUE;
2787 			if (af == local_ifs[i]->af) {
2788 				found_af = B_TRUE;
2789 				break;
2790 			}
2791 		}
2792 	}
2793 
2794 	free_local_netifs(local_if_cnt, local_ifs);
2795 
2796 	if (!found_if) {
2797 		(void) fprintf(stderr,
2798 		    gettext("could not verify %s %s=%s\n\t"
2799 		    "network interface %s is not plumbed in the global zone\n"),
2800 		    "net", "physical", phys, phys);
2801 		return;
2802 	}
2803 
2804 	/*
2805 	 * Print this error if we were unable to find the address family
2806 	 * for this interface.  If the af variable is not initialized to
2807 	 * to something meaningful by the caller (not AF_UNSPEC) then we
2808 	 * also skip this message since it wouldn't be informative.
2809 	 */
2810 	if (!found_af && af != AF_UNSPEC) {
2811 		(void) fprintf(stderr,
2812 		    gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
2813 		    "family is not configured on this network interface in "
2814 		    "the\n\tglobal zone\n"),
2815 		    "net", "address", addr, "physical", phys, af2str(af));
2816 		return;
2817 	}
2818 
2819 	(void) fprintf(stderr,
2820 	    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2821 	    "net", "address", addr, "physical", phys, msg);
2822 }
2823 
2824 static int
2825 verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[])
2826 {
2827 	struct zone_nwiftab nwiftab;
2828 	int return_code = Z_OK;
2829 	int err;
2830 	boolean_t in_alt_root;
2831 	zone_iptype_t iptype;
2832 	int fd;
2833 
2834 	in_alt_root = zonecfg_in_alt_root();
2835 	if (in_alt_root)
2836 		goto no_net;
2837 
2838 	if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
2839 		errno = err;
2840 		zperror(cmd_to_str(cmd_num), B_TRUE);
2841 		zonecfg_fini_handle(handle);
2842 		return (Z_ERR);
2843 	}
2844 	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2845 		errno = err;
2846 		zperror(cmd_to_str(cmd_num), B_TRUE);
2847 		zonecfg_fini_handle(handle);
2848 		return (Z_ERR);
2849 	}
2850 	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2851 		struct lifreq lifr;
2852 		sa_family_t af = AF_UNSPEC;
2853 		char dl_owner_zname[ZONENAME_MAX];
2854 		zoneid_t dl_owner_zid;
2855 		zoneid_t target_zid;
2856 		int res;
2857 
2858 		/* skip any loopback interfaces */
2859 		if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
2860 			continue;
2861 		switch (iptype) {
2862 		case ZS_SHARED:
2863 			if ((res = zonecfg_valid_net_address(
2864 			    nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
2865 				print_net_err(nwiftab.zone_nwif_physical,
2866 				    nwiftab.zone_nwif_address, af,
2867 				    zonecfg_strerror(res));
2868 			    return_code = Z_ERR;
2869 			    continue;
2870 			}
2871 			af = lifr.lifr_addr.ss_family;
2872 			if (!zonecfg_ifname_exists(af,
2873 			    nwiftab.zone_nwif_physical)) {
2874 				/*
2875 				 * The interface failed to come up. We continue
2876 				 * on anyway for the sake of consistency: a
2877 				 * zone is not shut down if the interface fails
2878 				 * any time after boot, nor does the global zone
2879 				 * fail to boot if an interface fails.
2880 				 */
2881 				(void) fprintf(stderr,
2882 				    gettext("WARNING: skipping network "
2883 					"interface '%s' which may not be "
2884 					"present/plumbed in the global "
2885 					"zone.\n"),
2886 				    nwiftab.zone_nwif_physical);
2887 			}
2888 			break;
2889 		case ZS_EXCLUSIVE:
2890 			/* Warning if it exists for either IPv4 or IPv6 */
2891 
2892 			if (zonecfg_ifname_exists(AF_INET,
2893 			    nwiftab.zone_nwif_physical) ||
2894 			    zonecfg_ifname_exists(AF_INET6,
2895 			    nwiftab.zone_nwif_physical)) {
2896 				(void) fprintf(stderr,
2897 				    gettext("WARNING: skipping network "
2898 				    "interface '%s' which is used in the "
2899 				    "global zone.\n"),
2900 				    nwiftab.zone_nwif_physical);
2901 				break;
2902 			}
2903 			/*
2904 			 * Verify that the physical interface can
2905 			 * be opened
2906 			 */
2907 			fd = ifname_open(nwiftab.zone_nwif_physical);
2908 			if (fd == -1) {
2909 				(void) fprintf(stderr,
2910 				    gettext("WARNING: skipping network "
2911 				    "interface '%s' which cannot be opened.\n"),
2912 				    nwiftab.zone_nwif_physical);
2913 				break;
2914 			} else {
2915 				(void) close(fd);
2916 			}
2917 			/*
2918 			 * Verify whether the physical interface is already
2919 			 * used by a zone.
2920 			 */
2921 			dl_owner_zid = ALL_ZONES;
2922 			if (zone_check_datalink(&dl_owner_zid,
2923 			    nwiftab.zone_nwif_physical) != 0)
2924 				break;
2925 
2926 			/*
2927 			 * If the zone being verified is
2928 			 * running and owns the interface
2929 			 */
2930 			target_zid = getzoneidbyname(target_zone);
2931 			if (target_zid == dl_owner_zid)
2932 				break;
2933 
2934 			/* Zone id match failed, use name to check */
2935 			if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
2936 			    ZONENAME_MAX) < 0) {
2937 				/* No name, show ID instead */
2938 				(void) snprintf(dl_owner_zname, ZONENAME_MAX,
2939 				    "<%d>", dl_owner_zid);
2940 			} else if (strcmp(dl_owner_zname, target_zone) == 0)
2941 				break;
2942 
2943 			/*
2944 			 * Note here we only report a warning that
2945 			 * the interface is already in use by another
2946 			 * running zone, and the verify process just
2947 			 * goes on, if the interface is still in use
2948 			 * when this zone really boots up, zoneadmd
2949 			 * will find it. If the name of the zone which
2950 			 * owns this interface cannot be determined,
2951 			 * then it is not possible to determine if there
2952 			 * is a conflict so just report it as a warning.
2953 			 */
2954 			(void) fprintf(stderr,
2955 			    gettext("WARNING: skipping network interface "
2956 			    "'%s' which is used by the non-global zone "
2957 			    "'%s'.\n"), nwiftab.zone_nwif_physical,
2958 			    dl_owner_zname);
2959 			break;
2960 		}
2961 	}
2962 	(void) zonecfg_endnwifent(handle);
2963 no_net:
2964 
2965 	/* verify that lofs has not been excluded from the kernel */
2966 	if (!(cmd_num == CMD_DETACH || cmd_num == CMD_ATTACH ||
2967 	    cmd_num == CMD_MOVE || cmd_num == CMD_CLONE) &&
2968 	    modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) {
2969 		if (errno == ENXIO)
2970 			(void) fprintf(stderr, gettext("could not verify "
2971 			    "lofs(7FS): possibly excluded in /etc/system\n"));
2972 		else
2973 			(void) fprintf(stderr, gettext("could not verify "
2974 			    "lofs(7FS): %s\n"), strerror(errno));
2975 		return_code = Z_ERR;
2976 	}
2977 
2978 	if (verify_filesystems(handle) != Z_OK)
2979 		return_code = Z_ERR;
2980 	if (verify_ipd(handle) != Z_OK)
2981 		return_code = Z_ERR;
2982 	if (!in_alt_root && verify_rctls(handle) != Z_OK)
2983 		return_code = Z_ERR;
2984 	if (!in_alt_root && verify_pool(handle) != Z_OK)
2985 		return_code = Z_ERR;
2986 	if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2987 		return_code = Z_ERR;
2988 	if (!in_alt_root && verify_datasets(handle) != Z_OK)
2989 		return_code = Z_ERR;
2990 
2991 	/*
2992 	 * As the "mount" command is used for patching/upgrading of zones
2993 	 * or other maintenance processes, the zone's privilege set is not
2994 	 * checked in this case.  Instead, the default, safe set of
2995 	 * privileges will be used when this zone is created in the
2996 	 * kernel.
2997 	 */
2998 	if (!in_alt_root && cmd_num != CMD_MOUNT &&
2999 	    verify_limitpriv(handle) != Z_OK)
3000 		return_code = Z_ERR;
3001 
3002 	return (return_code);
3003 }
3004 
3005 static int
3006 verify_details(int cmd_num, char *argv[])
3007 {
3008 	zone_dochandle_t handle;
3009 	char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
3010 	int return_code = Z_OK;
3011 	int err;
3012 
3013 	if ((handle = zonecfg_init_handle()) == NULL) {
3014 		zperror(cmd_to_str(cmd_num), B_TRUE);
3015 		return (Z_ERR);
3016 	}
3017 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
3018 		errno = err;
3019 		zperror(cmd_to_str(cmd_num), B_TRUE);
3020 		zonecfg_fini_handle(handle);
3021 		return (Z_ERR);
3022 	}
3023 	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
3024 	    Z_OK) {
3025 		errno = err;
3026 		zperror(cmd_to_str(cmd_num), B_TRUE);
3027 		zonecfg_fini_handle(handle);
3028 		return (Z_ERR);
3029 	}
3030 	/*
3031 	 * zonecfg_get_zonepath() gets its data from the XML repository.
3032 	 * Verify this against the index file, which is checked first by
3033 	 * zone_get_zonepath().  If they don't match, bail out.
3034 	 */
3035 	if ((err = zone_get_zonepath(target_zone, checkpath,
3036 	    sizeof (checkpath))) != Z_OK) {
3037 		errno = err;
3038 		zperror2(target_zone, gettext("could not get zone path"));
3039 		return (Z_ERR);
3040 	}
3041 	if (strcmp(zonepath, checkpath) != 0) {
3042 		/*
3043 		 * TRANSLATION_NOTE
3044 		 * XML and zonepath are literals that should not be translated.
3045 		 */
3046 		(void) fprintf(stderr, gettext("The XML repository has "
3047 		    "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
3048 		    "These must match, so fix the incorrect entry.\n"),
3049 		    zonepath, checkpath);
3050 		return (Z_ERR);
3051 	}
3052 	if (validate_zonepath(zonepath, cmd_num) != Z_OK) {
3053 		(void) fprintf(stderr, gettext("could not verify zonepath %s "
3054 		    "because of the above errors.\n"), zonepath);
3055 		return_code = Z_ERR;
3056 	}
3057 
3058 	if (verify_handle(cmd_num, handle, argv) != Z_OK)
3059 		return_code = Z_ERR;
3060 
3061 	zonecfg_fini_handle(handle);
3062 	if (return_code == Z_ERR)
3063 		(void) fprintf(stderr,
3064 		    gettext("%s: zone %s failed to verify\n"),
3065 		    execname, target_zone);
3066 	return (return_code);
3067 }
3068 
3069 static int
3070 verify_func(int argc, char *argv[])
3071 {
3072 	int arg;
3073 
3074 	optind = 0;
3075 	if ((arg = getopt(argc, argv, "?")) != EOF) {
3076 		switch (arg) {
3077 		case '?':
3078 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
3079 			return (optopt == '?' ? Z_OK : Z_USAGE);
3080 		default:
3081 			sub_usage(SHELP_VERIFY, CMD_VERIFY);
3082 			return (Z_USAGE);
3083 		}
3084 	}
3085 	if (argc > optind) {
3086 		sub_usage(SHELP_VERIFY, CMD_VERIFY);
3087 		return (Z_USAGE);
3088 	}
3089 	if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE, B_FALSE)
3090 	    != Z_OK)
3091 		return (Z_ERR);
3092 	return (verify_details(CMD_VERIFY, argv));
3093 }
3094 
3095 static int
3096 addopt(char *buf, int opt, char *optarg, size_t bufsize)
3097 {
3098 	char optstring[4];
3099 
3100 	if (opt > 0)
3101 		(void) sprintf(optstring, " -%c", opt);
3102 	else
3103 		(void) strcpy(optstring, " ");
3104 
3105 	if ((strlcat(buf, optstring, bufsize) > bufsize))
3106 		return (Z_ERR);
3107 	if ((optarg != NULL) && (strlcat(buf, optarg, bufsize) > bufsize))
3108 		return (Z_ERR);
3109 	return (Z_OK);
3110 }
3111 
3112 static int
3113 install_func(int argc, char *argv[])
3114 {
3115 	char cmdbuf[MAXPATHLEN];
3116 	int lockfd;
3117 	int arg, err, subproc_err;
3118 	char zonepath[MAXPATHLEN];
3119 	brand_handle_t bh = NULL;
3120 	int status;
3121 	boolean_t nodataset = B_FALSE;
3122 	char opts[128];
3123 
3124 	if (target_zone == NULL) {
3125 		sub_usage(SHELP_INSTALL, CMD_INSTALL);
3126 		return (Z_USAGE);
3127 	}
3128 
3129 	if (zonecfg_in_alt_root()) {
3130 		zerror(gettext("cannot install zone in alternate root"));
3131 		return (Z_ERR);
3132 	}
3133 
3134 	if ((err = zone_get_zonepath(target_zone, zonepath,
3135 	    sizeof (zonepath))) != Z_OK) {
3136 		errno = err;
3137 		zperror2(target_zone, gettext("could not get zone path"));
3138 		return (Z_ERR);
3139 	}
3140 
3141 	/* Fetch the install command from the brand configuration.  */
3142 	if ((bh = brand_open(target_brand)) == NULL) {
3143 		zerror(gettext("missing or invalid brand"));
3144 		return (Z_ERR);
3145 	}
3146 
3147 	(void) strcpy(cmdbuf, EXEC_PREFIX);
3148 	if (brand_get_install(bh, target_zone, zonepath, cmdbuf + EXEC_LEN,
3149 	    sizeof (cmdbuf) - EXEC_LEN, 0, NULL) != 0) {
3150 		zerror("invalid brand configuration: missing install resource");
3151 		brand_close(bh);
3152 		return (Z_ERR);
3153 	}
3154 
3155 	(void) strcpy(opts, "?x:");
3156 	if (!is_native_zone) {
3157 		/*
3158 		 * Fetch the list of recognized command-line options from
3159 		 * the brand configuration file.
3160 		 */
3161 		if (brand_get_installopts(bh, opts + strlen(opts),
3162 		    sizeof (opts) - strlen(opts)) != 0) {
3163 			zerror("invalid brand configuration: missing "
3164 			    "install options resource");
3165 			brand_close(bh);
3166 			return (Z_ERR);
3167 		}
3168 	}
3169 	brand_close(bh);
3170 
3171 	optind = 0;
3172 	while ((arg = getopt(argc, argv, opts)) != EOF) {
3173 		switch (arg) {
3174 		case '?':
3175 			sub_usage(SHELP_INSTALL, CMD_INSTALL);
3176 			return (optopt == '?' ? Z_OK : Z_USAGE);
3177 		case 'x':
3178 			if (strcmp(optarg, "nodataset") != 0) {
3179 				sub_usage(SHELP_INSTALL, CMD_INSTALL);
3180 				return (Z_USAGE);
3181 			}
3182 			nodataset = B_TRUE;
3183 			break;
3184 		default:
3185 			if (is_native_zone) {
3186 				sub_usage(SHELP_INSTALL, CMD_INSTALL);
3187 				return (Z_USAGE);
3188 			}
3189 
3190 			/*
3191 			 * This option isn't for zoneadm, so append it to
3192 			 * the command line passed to the brand-specific
3193 			 * install routine.
3194 			 */
3195 			if (addopt(cmdbuf, optopt, optarg,
3196 			    sizeof (cmdbuf)) != Z_OK) {
3197 				zerror("Install command line too long");
3198 				return (Z_ERR);
3199 			}
3200 			break;
3201 		}
3202 	}
3203 
3204 	if (!is_native_zone) {
3205 		for (; optind < argc; optind++) {
3206 			if (addopt(cmdbuf, 0, argv[optind],
3207 			    sizeof (cmdbuf)) != Z_OK) {
3208 				zerror("Install command line too long");
3209 				return (Z_ERR);
3210 			}
3211 		}
3212 	}
3213 
3214 	if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE, B_FALSE)
3215 	    != Z_OK)
3216 		return (Z_ERR);
3217 	if (verify_details(CMD_INSTALL, argv) != Z_OK)
3218 		return (Z_ERR);
3219 
3220 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3221 		zerror(gettext("another %s may have an operation in progress."),
3222 		    "zoneadm");
3223 		return (Z_ERR);
3224 	}
3225 	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3226 	if (err != Z_OK) {
3227 		errno = err;
3228 		zperror2(target_zone, gettext("could not set state"));
3229 		goto done;
3230 	}
3231 
3232 	if (!nodataset)
3233 		create_zfs_zonepath(zonepath);
3234 
3235 	/*
3236 	 * According to the Application Packaging Developer's Guide, a
3237 	 * "checkinstall" script when included in a package is executed as
3238 	 * the user "install", if such a user exists, or by the user
3239 	 * "nobody".  In order to support this dubious behavior, the path
3240 	 * to the zone being constructed is opened up during the life of
3241 	 * the command laying down the zone's root file system.  Once this
3242 	 * has completed, regardless of whether it was successful, the
3243 	 * path to the zone is again restricted.
3244 	 */
3245 	if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) {
3246 		zperror(zonepath, B_FALSE);
3247 		err = Z_ERR;
3248 		goto done;
3249 	}
3250 
3251 	if (is_native_zone)
3252 		status = do_subproc(cmdbuf);
3253 	else
3254 		status = do_subproc_interactive(cmdbuf);
3255 
3256 	if (chmod(zonepath, S_IRWXU) != 0) {
3257 		zperror(zonepath, B_FALSE);
3258 		err = Z_ERR;
3259 		goto done;
3260 	}
3261 	if ((subproc_err =
3262 	    subproc_status(gettext("brand-specific installation"), status,
3263 	    B_FALSE)) != ZONE_SUBPROC_OK) {
3264 		err = Z_ERR;
3265 		goto done;
3266 	}
3267 
3268 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3269 		errno = err;
3270 		zperror2(target_zone, gettext("could not set state"));
3271 		goto done;
3272 	}
3273 
3274 done:
3275 	/*
3276 	 * If the install script exited with ZONE_SUBPROC_USAGE or
3277 	 * ZONE_SUBPROC_NOTCOMPLETE, try to clean up the zone and leave the
3278 	 * zone in the CONFIGURED state so that another install can be
3279 	 * attempted without requiring an uninstall first.
3280 	 */
3281 	if ((subproc_err == ZONE_SUBPROC_USAGE) ||
3282 	    (subproc_err == ZONE_SUBPROC_NOTCOMPLETE)) {
3283 		if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
3284 			errno = err;
3285 			zperror2(target_zone,
3286 			    gettext("cleaning up zonepath failed"));
3287 		} else if ((err = zone_set_state(target_zone,
3288 		    ZONE_STATE_CONFIGURED)) != Z_OK) {
3289 			errno = err;
3290 			zperror2(target_zone, gettext("could not set state"));
3291 		}
3292 	}
3293 
3294 	release_lock_file(lockfd);
3295 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3296 }
3297 
3298 /*
3299  * Check that the inherited pkg dirs are the same for the clone and its source.
3300  * The easiest way to do that is check that the list of ipds is the same
3301  * by matching each one against the other.  This algorithm should be fine since
3302  * the list of ipds should not be that long.
3303  */
3304 static int
3305 valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone,
3306 	zone_dochandle_t t_handle, char *target_zone)
3307 {
3308 	int err;
3309 	int res = Z_OK;
3310 	int s_cnt = 0;
3311 	int t_cnt = 0;
3312 	struct zone_fstab s_fstab;
3313 	struct zone_fstab t_fstab;
3314 
3315 	/*
3316 	 * First check the source of the clone against the target.
3317 	 */
3318 	if ((err = zonecfg_setipdent(s_handle)) != Z_OK) {
3319 		errno = err;
3320 		zperror2(source_zone, gettext("could not enumerate "
3321 		    "inherit-pkg-dirs"));
3322 		return (Z_ERR);
3323 	}
3324 
3325 	while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) {
3326 		boolean_t match = B_FALSE;
3327 
3328 		s_cnt++;
3329 
3330 		if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
3331 			errno = err;
3332 			zperror2(target_zone, gettext("could not enumerate "
3333 			    "inherit-pkg-dirs"));
3334 			(void) zonecfg_endipdent(s_handle);
3335 			return (Z_ERR);
3336 		}
3337 
3338 		while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) {
3339 			if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir)
3340 			    == 0) {
3341 				match = B_TRUE;
3342 				break;
3343 			}
3344 		}
3345 		(void) zonecfg_endipdent(t_handle);
3346 
3347 		if (!match) {
3348 			(void) fprintf(stderr, gettext("inherit-pkg-dir "
3349 			    "'%s' is not configured in zone %s.\n"),
3350 			    s_fstab.zone_fs_dir, target_zone);
3351 			res = Z_ERR;
3352 		}
3353 	}
3354 
3355 	(void) zonecfg_endipdent(s_handle);
3356 
3357 	/* skip the next check if we already have errors */
3358 	if (res == Z_ERR)
3359 		return (res);
3360 
3361 	/*
3362 	 * Now check the number of ipds in the target so we can verify
3363 	 * that the source is not a subset of the target.
3364 	 */
3365 	if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
3366 		errno = err;
3367 		zperror2(target_zone, gettext("could not enumerate "
3368 		    "inherit-pkg-dirs"));
3369 		return (Z_ERR);
3370 	}
3371 
3372 	while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK)
3373 		t_cnt++;
3374 
3375 	(void) zonecfg_endipdent(t_handle);
3376 
3377 	if (t_cnt != s_cnt) {
3378 		(void) fprintf(stderr, gettext("Zone %s is configured "
3379 		    "with inherit-pkg-dirs that are not configured in zone "
3380 		    "%s.\n"), target_zone, source_zone);
3381 		res = Z_ERR;
3382 	}
3383 
3384 	return (res);
3385 }
3386 
3387 static void
3388 warn_dev_match(zone_dochandle_t s_handle, char *source_zone,
3389 	zone_dochandle_t t_handle, char *target_zone)
3390 {
3391 	int err;
3392 	struct zone_devtab s_devtab;
3393 	struct zone_devtab t_devtab;
3394 
3395 	if ((err = zonecfg_setdevent(t_handle)) != Z_OK) {
3396 		errno = err;
3397 		zperror2(target_zone, gettext("could not enumerate devices"));
3398 		return;
3399 	}
3400 
3401 	while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) {
3402 		if ((err = zonecfg_setdevent(s_handle)) != Z_OK) {
3403 			errno = err;
3404 			zperror2(source_zone,
3405 			    gettext("could not enumerate devices"));
3406 			(void) zonecfg_enddevent(t_handle);
3407 			return;
3408 		}
3409 
3410 		while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) {
3411 			/*
3412 			 * Use fnmatch to catch the case where wildcards
3413 			 * were used in one zone and the other has an
3414 			 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs.
3415 			 * /dev/\*dsk/c0t0d0s6).
3416 			 */
3417 			if (fnmatch(t_devtab.zone_dev_match,
3418 			    s_devtab.zone_dev_match, FNM_PATHNAME) == 0 ||
3419 			    fnmatch(s_devtab.zone_dev_match,
3420 			    t_devtab.zone_dev_match, FNM_PATHNAME) == 0) {
3421 				(void) fprintf(stderr,
3422 				    gettext("WARNING: device '%s' "
3423 				    "is configured in both zones.\n"),
3424 				    t_devtab.zone_dev_match);
3425 				break;
3426 			}
3427 		}
3428 		(void) zonecfg_enddevent(s_handle);
3429 	}
3430 
3431 	(void) zonecfg_enddevent(t_handle);
3432 }
3433 
3434 /*
3435  * Check if the specified mount option (opt) is contained within the
3436  * options string.
3437  */
3438 static boolean_t
3439 opt_match(char *opt, char *options)
3440 {
3441 	char *p;
3442 	char *lastp;
3443 
3444 	if ((p = strtok_r(options, ",", &lastp)) != NULL) {
3445 		if (strcmp(p, opt) == 0)
3446 			return (B_TRUE);
3447 		while ((p = strtok_r(NULL, ",", &lastp)) != NULL) {
3448 			if (strcmp(p, opt) == 0)
3449 				return (B_TRUE);
3450 		}
3451 	}
3452 
3453 	return (B_FALSE);
3454 }
3455 
3456 #define	RW_LOFS	"WARNING: read-write lofs file system on '%s' is configured " \
3457 	"in both zones.\n"
3458 
3459 static void
3460 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
3461 {
3462 	/*
3463 	 * It is ok to have shared lofs mounted fs but we want to warn if
3464 	 * either is rw since this will effect the other zone.
3465 	 */
3466 	if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) {
3467 		zone_fsopt_t *optp;
3468 
3469 		/* The default is rw so no options means rw */
3470 		if (t_fstab->zone_fs_options == NULL ||
3471 		    s_fstab->zone_fs_options == NULL) {
3472 			(void) fprintf(stderr, gettext(RW_LOFS),
3473 			    t_fstab->zone_fs_special);
3474 			return;
3475 		}
3476 
3477 		for (optp = s_fstab->zone_fs_options; optp != NULL;
3478 		    optp = optp->zone_fsopt_next) {
3479 			if (opt_match("rw", optp->zone_fsopt_opt)) {
3480 				(void) fprintf(stderr, gettext(RW_LOFS),
3481 				    s_fstab->zone_fs_special);
3482 				return;
3483 			}
3484 		}
3485 
3486 		for (optp = t_fstab->zone_fs_options; optp != NULL;
3487 		    optp = optp->zone_fsopt_next) {
3488 			if (opt_match("rw", optp->zone_fsopt_opt)) {
3489 				(void) fprintf(stderr, gettext(RW_LOFS),
3490 				    t_fstab->zone_fs_special);
3491 				return;
3492 			}
3493 		}
3494 
3495 		return;
3496 	}
3497 
3498 	/*
3499 	 * TRANSLATION_NOTE
3500 	 * The first variable is the file system type and the second is
3501 	 * the file system special device.  For example,
3502 	 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
3503 	 */
3504 	(void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
3505 	    "is configured in both zones.\n"), t_fstab->zone_fs_type,
3506 	    t_fstab->zone_fs_special);
3507 }
3508 
3509 static void
3510 warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
3511 	zone_dochandle_t t_handle, char *target_zone)
3512 {
3513 	int err;
3514 	struct zone_fstab s_fstab;
3515 	struct zone_fstab t_fstab;
3516 
3517 	if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
3518 		errno = err;
3519 		zperror2(target_zone,
3520 		    gettext("could not enumerate file systems"));
3521 		return;
3522 	}
3523 
3524 	while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
3525 		if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
3526 			errno = err;
3527 			zperror2(source_zone,
3528 			    gettext("could not enumerate file systems"));
3529 			(void) zonecfg_endfsent(t_handle);
3530 			return;
3531 		}
3532 
3533 		while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
3534 			if (strcmp(t_fstab.zone_fs_special,
3535 			    s_fstab.zone_fs_special) == 0) {
3536 				print_fs_warnings(&s_fstab, &t_fstab);
3537 				break;
3538 			}
3539 		}
3540 		(void) zonecfg_endfsent(s_handle);
3541 	}
3542 
3543 	(void) zonecfg_endfsent(t_handle);
3544 }
3545 
3546 /*
3547  * We don't catch the case where you used the same IP address but
3548  * it is not an exact string match.  For example, 192.9.0.128 vs. 192.09.0.128.
3549  * However, we're not going to worry about that but we will check for
3550  * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24)
3551  * and handle that case as a match.
3552  */
3553 static void
3554 warn_ip_match(zone_dochandle_t s_handle, char *source_zone,
3555 	zone_dochandle_t t_handle, char *target_zone)
3556 {
3557 	int err;
3558 	struct zone_nwiftab s_nwiftab;
3559 	struct zone_nwiftab t_nwiftab;
3560 
3561 	if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) {
3562 		errno = err;
3563 		zperror2(target_zone,
3564 		    gettext("could not enumerate network interfaces"));
3565 		return;
3566 	}
3567 
3568 	while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) {
3569 		char *p;
3570 
3571 		/* remove an (optional) netmask from the address */
3572 		if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL)
3573 			*p = '\0';
3574 
3575 		if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) {
3576 			errno = err;
3577 			zperror2(source_zone,
3578 			    gettext("could not enumerate network interfaces"));
3579 			(void) zonecfg_endnwifent(t_handle);
3580 			return;
3581 		}
3582 
3583 		while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) {
3584 			/* remove an (optional) netmask from the address */
3585 			if ((p = strchr(s_nwiftab.zone_nwif_address, '/'))
3586 			    != NULL)
3587 				*p = '\0';
3588 
3589 			/* For exclusive-IP zones, address is not specified. */
3590 			if (strlen(s_nwiftab.zone_nwif_address) == 0)
3591 				continue;
3592 
3593 			if (strcmp(t_nwiftab.zone_nwif_address,
3594 			    s_nwiftab.zone_nwif_address) == 0) {
3595 				(void) fprintf(stderr,
3596 				    gettext("WARNING: network address '%s' "
3597 				    "is configured in both zones.\n"),
3598 				    t_nwiftab.zone_nwif_address);
3599 				break;
3600 			}
3601 		}
3602 		(void) zonecfg_endnwifent(s_handle);
3603 	}
3604 
3605 	(void) zonecfg_endnwifent(t_handle);
3606 }
3607 
3608 static void
3609 warn_dataset_match(zone_dochandle_t s_handle, char *source,
3610 	zone_dochandle_t t_handle, char *target)
3611 {
3612 	int err;
3613 	struct zone_dstab s_dstab;
3614 	struct zone_dstab t_dstab;
3615 
3616 	if ((err = zonecfg_setdsent(t_handle)) != Z_OK) {
3617 		errno = err;
3618 		zperror2(target, gettext("could not enumerate datasets"));
3619 		return;
3620 	}
3621 
3622 	while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) {
3623 		if ((err = zonecfg_setdsent(s_handle)) != Z_OK) {
3624 			errno = err;
3625 			zperror2(source,
3626 			    gettext("could not enumerate datasets"));
3627 			(void) zonecfg_enddsent(t_handle);
3628 			return;
3629 		}
3630 
3631 		while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) {
3632 			if (strcmp(t_dstab.zone_dataset_name,
3633 			    s_dstab.zone_dataset_name) == 0) {
3634 				target_zone = source;
3635 				zerror(gettext("WARNING: dataset '%s' "
3636 				    "is configured in both zones.\n"),
3637 				    t_dstab.zone_dataset_name);
3638 				break;
3639 			}
3640 		}
3641 		(void) zonecfg_enddsent(s_handle);
3642 	}
3643 
3644 	(void) zonecfg_enddsent(t_handle);
3645 }
3646 
3647 /*
3648  * Check that the clone and its source have the same brand type.
3649  */
3650 static int
3651 valid_brand_clone(char *source_zone, char *target_zone)
3652 {
3653 	brand_handle_t bh;
3654 	char source_brand[MAXNAMELEN];
3655 
3656 	if ((zone_get_brand(source_zone, source_brand,
3657 	    sizeof (source_brand))) != Z_OK) {
3658 		(void) fprintf(stderr, "%s: zone '%s': %s\n",
3659 		    execname, source_zone, gettext("missing or invalid brand"));
3660 		return (Z_ERR);
3661 	}
3662 
3663 	if (strcmp(source_brand, target_brand) != NULL) {
3664 		(void) fprintf(stderr,
3665 		    gettext("%s: Zones '%s' and '%s' have different brand "
3666 		    "types.\n"), execname, source_zone, target_zone);
3667 		return (Z_ERR);
3668 	}
3669 
3670 	if ((bh = brand_open(target_brand)) == NULL) {
3671 		zerror(gettext("missing or invalid brand"));
3672 		return (Z_ERR);
3673 	}
3674 	brand_close(bh);
3675 	return (Z_OK);
3676 }
3677 
3678 static int
3679 validate_clone(char *source_zone, char *target_zone)
3680 {
3681 	int err = Z_OK;
3682 	zone_dochandle_t s_handle;
3683 	zone_dochandle_t t_handle;
3684 
3685 	if ((t_handle = zonecfg_init_handle()) == NULL) {
3686 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3687 		return (Z_ERR);
3688 	}
3689 	if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) {
3690 		errno = err;
3691 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3692 		zonecfg_fini_handle(t_handle);
3693 		return (Z_ERR);
3694 	}
3695 
3696 	if ((s_handle = zonecfg_init_handle()) == NULL) {
3697 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3698 		zonecfg_fini_handle(t_handle);
3699 		return (Z_ERR);
3700 	}
3701 	if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) {
3702 		errno = err;
3703 		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3704 		goto done;
3705 	}
3706 
3707 	/* verify new zone has same brand type */
3708 	err = valid_brand_clone(source_zone, target_zone);
3709 	if (err != Z_OK)
3710 		goto done;
3711 
3712 	/* verify new zone has same inherit-pkg-dirs */
3713 	err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone);
3714 
3715 	/* warn about imported fs's which are the same */
3716 	warn_fs_match(s_handle, source_zone, t_handle, target_zone);
3717 
3718 	/* warn about imported IP addresses which are the same */
3719 	warn_ip_match(s_handle, source_zone, t_handle, target_zone);
3720 
3721 	/* warn about imported devices which are the same */
3722 	warn_dev_match(s_handle, source_zone, t_handle, target_zone);
3723 
3724 	/* warn about imported datasets which are the same */
3725 	warn_dataset_match(s_handle, source_zone, t_handle, target_zone);
3726 
3727 done:
3728 	zonecfg_fini_handle(t_handle);
3729 	zonecfg_fini_handle(s_handle);
3730 
3731 	return ((err == Z_OK) ? Z_OK : Z_ERR);
3732 }
3733 
3734 static int
3735 copy_zone(char *src, char *dst)
3736 {
3737 	boolean_t out_null = B_FALSE;
3738 	int status;
3739 	char *outfile;
3740 	char cmdbuf[MAXPATHLEN * 2 + 128];
3741 
3742 	if ((outfile = tempnam("/var/log", "zone")) == NULL) {
3743 		outfile = "/dev/null";
3744 		out_null = B_TRUE;
3745 	}
3746 
3747 	/*
3748 	 * Use find to get the list of files to copy.  We need to skip
3749 	 * files of type "socket" since cpio can't handle those but that
3750 	 * should be ok since the app will recreate the socket when it runs.
3751 	 * We also need to filter out anything under the .zfs subdir.  Since
3752 	 * find is running depth-first, we need the extra egrep to filter .zfs.
3753 	 */
3754 	(void) snprintf(cmdbuf, sizeof (cmdbuf),
3755 	    "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
3756 	    "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
3757 	    "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
3758 	    src, dst, outfile);
3759 
3760 	status = do_subproc(cmdbuf);
3761 
3762 	if (subproc_status("copy", status, B_TRUE) != ZONE_SUBPROC_OK) {
3763 		if (!out_null)
3764 			(void) fprintf(stderr, gettext("\nThe copy failed.\n"
3765 			    "More information can be found in %s\n"), outfile);
3766 		return (Z_ERR);
3767 	}
3768 
3769 	if (!out_null)
3770 		(void) unlink(outfile);
3771 
3772 	return (Z_OK);
3773 }
3774 
3775 static int
3776 zone_postclone(char *zonepath)
3777 {
3778 	char cmdbuf[MAXPATHLEN];
3779 	int status;
3780 	brand_handle_t bh;
3781 	int err = Z_OK;
3782 
3783 	/*
3784 	 * Fetch the post-clone command, if any, from the brand
3785 	 * configuration.
3786 	 */
3787 	if ((bh = brand_open(target_brand)) == NULL) {
3788 		zerror(gettext("missing or invalid brand"));
3789 		return (Z_ERR);
3790 	}
3791 	(void) strcpy(cmdbuf, EXEC_PREFIX);
3792 	err = brand_get_postclone(bh, target_zone, zonepath, cmdbuf + EXEC_LEN,
3793 	    sizeof (cmdbuf) - EXEC_LEN, 0, NULL);
3794 	brand_close(bh);
3795 
3796 	if (err == 0 && strlen(cmdbuf) > EXEC_LEN) {
3797 		status = do_subproc(cmdbuf);
3798 		if ((err = subproc_status("postclone", status, B_FALSE))
3799 		    != ZONE_SUBPROC_OK) {
3800 			zerror(gettext("post-clone configuration failed."));
3801 			err = Z_ERR;
3802 		}
3803 	}
3804 
3805 	return (err);
3806 }
3807 
3808 /* ARGSUSED */
3809 static int
3810 zfm_print(const char *p, void *r) {
3811 	zerror("  %s\n", p);
3812 	return (0);
3813 }
3814 
3815 int
3816 clone_copy(char *source_zonepath, char *zonepath)
3817 {
3818 	int err;
3819 
3820 	/* Don't clone the zone if anything is still mounted there */
3821 	if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
3822 		zerror(gettext("These file systems are mounted on "
3823 		    "subdirectories of %s.\n"), source_zonepath);
3824 		(void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
3825 		return (Z_ERR);
3826 	}
3827 
3828 	/*
3829 	 * Attempt to create a ZFS fs for the zonepath.  As usual, we don't
3830 	 * care if this works or not since we always have the default behavior
3831 	 * of a simple directory for the zonepath.
3832 	 */
3833 	create_zfs_zonepath(zonepath);
3834 
3835 	(void) printf(gettext("Copying %s..."), source_zonepath);
3836 	(void) fflush(stdout);
3837 
3838 	err = copy_zone(source_zonepath, zonepath);
3839 
3840 	(void) printf("\n");
3841 
3842 	return (err);
3843 }
3844 
3845 static int
3846 clone_func(int argc, char *argv[])
3847 {
3848 	char *source_zone = NULL;
3849 	int lockfd;
3850 	int err, arg;
3851 	char zonepath[MAXPATHLEN];
3852 	char source_zonepath[MAXPATHLEN];
3853 	zone_state_t state;
3854 	zone_entry_t *zent;
3855 	char *method = NULL;
3856 	char *snapshot = NULL;
3857 
3858 	if (zonecfg_in_alt_root()) {
3859 		zerror(gettext("cannot clone zone in alternate root"));
3860 		return (Z_ERR);
3861 	}
3862 
3863 	optind = 0;
3864 	if ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
3865 		switch (arg) {
3866 		case '?':
3867 			sub_usage(SHELP_CLONE, CMD_CLONE);
3868 			return (optopt == '?' ? Z_OK : Z_USAGE);
3869 		case 'm':
3870 			method = optarg;
3871 			break;
3872 		case 's':
3873 			snapshot = optarg;
3874 			break;
3875 		default:
3876 			sub_usage(SHELP_CLONE, CMD_CLONE);
3877 			return (Z_USAGE);
3878 		}
3879 	}
3880 	if (argc != (optind + 1) ||
3881 	    (method != NULL && strcmp(method, "copy") != 0)) {
3882 		sub_usage(SHELP_CLONE, CMD_CLONE);
3883 		return (Z_USAGE);
3884 	}
3885 	source_zone = argv[optind];
3886 	if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE, B_FALSE)
3887 	    != Z_OK)
3888 		return (Z_ERR);
3889 	if (verify_details(CMD_CLONE, argv) != Z_OK)
3890 		return (Z_ERR);
3891 
3892 	/*
3893 	 * We also need to do some extra validation on the source zone.
3894 	 */
3895 	if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3896 		zerror(gettext("%s operation is invalid for the global zone."),
3897 		    cmd_to_str(CMD_CLONE));
3898 		return (Z_ERR);
3899 	}
3900 
3901 	if (strncmp(source_zone, "SUNW", 4) == 0) {
3902 		zerror(gettext("%s operation is invalid for zones starting "
3903 		    "with SUNW."), cmd_to_str(CMD_CLONE));
3904 		return (Z_ERR);
3905 	}
3906 
3907 	zent = lookup_running_zone(source_zone);
3908 	if (zent != NULL) {
3909 		/* check whether the zone is ready or running */
3910 		if ((err = zone_get_state(zent->zname, &zent->zstate_num))
3911 		    != Z_OK) {
3912 			errno = err;
3913 			zperror2(zent->zname, gettext("could not get state"));
3914 			/* can't tell, so hedge */
3915 			zent->zstate_str = "ready/running";
3916 		} else {
3917 			zent->zstate_str = zone_state_str(zent->zstate_num);
3918 		}
3919 		zerror(gettext("%s operation is invalid for %s zones."),
3920 		    cmd_to_str(CMD_CLONE), zent->zstate_str);
3921 		return (Z_ERR);
3922 	}
3923 
3924 	if ((err = zone_get_state(source_zone, &state)) != Z_OK) {
3925 		errno = err;
3926 		zperror2(source_zone, gettext("could not get state"));
3927 		return (Z_ERR);
3928 	}
3929 	if (state != ZONE_STATE_INSTALLED) {
3930 		(void) fprintf(stderr,
3931 		    gettext("%s: zone %s is %s; %s is required.\n"),
3932 		    execname, source_zone, zone_state_str(state),
3933 		    zone_state_str(ZONE_STATE_INSTALLED));
3934 		return (Z_ERR);
3935 	}
3936 
3937 	/*
3938 	 * The source zone checks out ok, continue with the clone.
3939 	 */
3940 
3941 	if (validate_clone(source_zone, target_zone) != Z_OK)
3942 		return (Z_ERR);
3943 
3944 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3945 		zerror(gettext("another %s may have an operation in progress."),
3946 		    "zoneadm");
3947 		return (Z_ERR);
3948 	}
3949 
3950 	if ((err = zone_get_zonepath(source_zone, source_zonepath,
3951 	    sizeof (source_zonepath))) != Z_OK) {
3952 		errno = err;
3953 		zperror2(source_zone, gettext("could not get zone path"));
3954 		goto done;
3955 	}
3956 
3957 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3958 	    != Z_OK) {
3959 		errno = err;
3960 		zperror2(target_zone, gettext("could not get zone path"));
3961 		goto done;
3962 	}
3963 
3964 	if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3965 	    != Z_OK) {
3966 		errno = err;
3967 		zperror2(target_zone, gettext("could not set state"));
3968 		goto done;
3969 	}
3970 
3971 	if (snapshot != NULL) {
3972 		err = clone_snapshot_zfs(snapshot, zonepath);
3973 	} else {
3974 		/*
3975 		 * We always copy the clone unless the source is ZFS and a
3976 		 * ZFS clone worked.  We fallback to copying if the ZFS clone
3977 		 * fails for some reason.
3978 		 */
3979 		err = Z_ERR;
3980 		if (method == NULL && is_zonepath_zfs(source_zonepath))
3981 			err = clone_zfs(source_zone, source_zonepath, zonepath);
3982 
3983 		if (err != Z_OK)
3984 			err = clone_copy(source_zonepath, zonepath);
3985 	}
3986 
3987 	/*
3988 	 * Trusted Extensions requires that cloned zones use the same sysid
3989 	 * configuration, so it is not appropriate to perform any
3990 	 * post-clone reconfiguration.
3991 	 */
3992 	if ((err == Z_OK) && !is_system_labeled())
3993 		err = zone_postclone(zonepath);
3994 
3995 done:
3996 	/*
3997 	 * If everything went well, we mark the zone as installed.
3998 	 */
3999 	if (err == Z_OK) {
4000 		err = zone_set_state(target_zone, ZONE_STATE_INSTALLED);
4001 		if (err != Z_OK) {
4002 			errno = err;
4003 			zperror2(target_zone, gettext("could not set state"));
4004 		}
4005 	}
4006 	release_lock_file(lockfd);
4007 	return ((err == Z_OK) ? Z_OK : Z_ERR);
4008 }
4009 
4010 /*
4011  * Used when removing a zonepath after uninstalling or cleaning up after
4012  * the move subcommand.  This handles a zonepath that has non-standard
4013  * contents so that we will only cleanup the stuff we know about and leave
4014  * any user data alone.
4015  *
4016  * If the "all" parameter is true then we should remove the whole zonepath
4017  * even if it has non-standard files/directories in it.  This can be used when
4018  * we need to cleanup after moving the zonepath across file systems.
4019  *
4020  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
4021  * and not the shell.
4022  */
4023 static int
4024 cleanup_zonepath(char *zonepath, boolean_t all)
4025 {
4026 	int		status;
4027 	int		i;
4028 	boolean_t	non_std = B_FALSE;
4029 	struct dirent	*dp;
4030 	DIR		*dirp;
4031 	char		*std_entries[] = {"dev", "lu", "root", NULL};
4032 			/* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
4033 	char		cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
4034 
4035 	/*
4036 	 * We shouldn't need these checks but lets be paranoid since we
4037 	 * could blow away the whole system here if we got the wrong zonepath.
4038 	 */
4039 	if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
4040 		(void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
4041 		return (Z_INVAL);
4042 	}
4043 
4044 	/*
4045 	 * If the dirpath is already gone (maybe it was manually removed) then
4046 	 * we just return Z_OK so that the cleanup is successful.
4047 	 */
4048 	if ((dirp = opendir(zonepath)) == NULL)
4049 		return (Z_OK);
4050 
4051 	/*
4052 	 * Look through the zonepath directory to see if there are any
4053 	 * non-standard files/dirs.  Also skip .zfs since that might be
4054 	 * there but we'll handle ZFS file systems as a special case.
4055 	 */
4056 	while ((dp = readdir(dirp)) != NULL) {
4057 		if (strcmp(dp->d_name, ".") == 0 ||
4058 		    strcmp(dp->d_name, "..") == 0 ||
4059 		    strcmp(dp->d_name, ".zfs") == 0)
4060 			continue;
4061 
4062 		for (i = 0; std_entries[i] != NULL; i++)
4063 			if (strcmp(dp->d_name, std_entries[i]) == 0)
4064 				break;
4065 
4066 		if (std_entries[i] == NULL)
4067 			non_std = B_TRUE;
4068 	}
4069 	(void) closedir(dirp);
4070 
4071 	if (!all && non_std) {
4072 		/*
4073 		 * There are extra, non-standard directories/files in the
4074 		 * zonepath so we don't want to remove the zonepath.  We
4075 		 * just want to remove the standard directories and leave
4076 		 * the user data alone.
4077 		 */
4078 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
4079 
4080 		for (i = 0; std_entries[i] != NULL; i++) {
4081 			char tmpbuf[MAXPATHLEN];
4082 
4083 			if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
4084 			    zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
4085 			    strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
4086 			    sizeof (cmdbuf)) {
4087 				(void) fprintf(stderr,
4088 				    gettext("path is too long\n"));
4089 				return (Z_INVAL);
4090 			}
4091 		}
4092 
4093 		status = do_subproc(cmdbuf);
4094 
4095 		(void) fprintf(stderr, gettext("WARNING: Unable to completely "
4096 		    "remove %s\nbecause it contains additional user data.  "
4097 		    "Only the standard directory\nentries have been "
4098 		    "removed.\n"),
4099 		    zonepath);
4100 
4101 		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4102 		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4103 	}
4104 
4105 	/*
4106 	 * There is nothing unexpected in the zonepath, try to get rid of the
4107 	 * whole zonepath directory.
4108 	 *
4109 	 * If the zonepath is its own zfs file system, try to destroy the
4110 	 * file system.  If that fails for some reason (e.g. it has clones)
4111 	 * then we'll just remove the contents of the zonepath.
4112 	 */
4113 	if (is_zonepath_zfs(zonepath)) {
4114 		if (destroy_zfs(zonepath) == Z_OK)
4115 			return (Z_OK);
4116 		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
4117 		    " %s/*", zonepath);
4118 		status = do_subproc(cmdbuf);
4119 		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4120 		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4121 	}
4122 
4123 	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
4124 	    zonepath);
4125 	status = do_subproc(cmdbuf);
4126 
4127 	return ((subproc_status(RMCOMMAND, status, B_TRUE) == ZONE_SUBPROC_OK)
4128 	    ? Z_OK : Z_ERR);
4129 }
4130 
4131 static int
4132 move_func(int argc, char *argv[])
4133 {
4134 	char *new_zonepath = NULL;
4135 	int lockfd;
4136 	int err, arg;
4137 	char zonepath[MAXPATHLEN];
4138 	zone_dochandle_t handle;
4139 	boolean_t fast;
4140 	boolean_t is_zfs = B_FALSE;
4141 	struct dirent *dp;
4142 	DIR *dirp;
4143 	boolean_t empty = B_TRUE;
4144 	boolean_t revert;
4145 	struct stat zonepath_buf;
4146 	struct stat new_zonepath_buf;
4147 
4148 	if (zonecfg_in_alt_root()) {
4149 		zerror(gettext("cannot move zone in alternate root"));
4150 		return (Z_ERR);
4151 	}
4152 
4153 	optind = 0;
4154 	if ((arg = getopt(argc, argv, "?")) != EOF) {
4155 		switch (arg) {
4156 		case '?':
4157 			sub_usage(SHELP_MOVE, CMD_MOVE);
4158 			return (optopt == '?' ? Z_OK : Z_USAGE);
4159 		default:
4160 			sub_usage(SHELP_MOVE, CMD_MOVE);
4161 			return (Z_USAGE);
4162 		}
4163 	}
4164 	if (argc != (optind + 1)) {
4165 		sub_usage(SHELP_MOVE, CMD_MOVE);
4166 		return (Z_USAGE);
4167 	}
4168 	new_zonepath = argv[optind];
4169 	if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE, B_FALSE)
4170 	    != Z_OK)
4171 		return (Z_ERR);
4172 	if (verify_details(CMD_MOVE, argv) != Z_OK)
4173 		return (Z_ERR);
4174 
4175 	/*
4176 	 * Check out the new zonepath.  This has the side effect of creating
4177 	 * a directory for the new zonepath.  We depend on this later when we
4178 	 * stat to see if we are doing a cross file system move or not.
4179 	 */
4180 	if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
4181 		return (Z_ERR);
4182 
4183 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4184 	    != Z_OK) {
4185 		errno = err;
4186 		zperror2(target_zone, gettext("could not get zone path"));
4187 		return (Z_ERR);
4188 	}
4189 
4190 	if (stat(zonepath, &zonepath_buf) == -1) {
4191 		zperror(gettext("could not stat zone path"), B_FALSE);
4192 		return (Z_ERR);
4193 	}
4194 
4195 	if (stat(new_zonepath, &new_zonepath_buf) == -1) {
4196 		zperror(gettext("could not stat new zone path"), B_FALSE);
4197 		return (Z_ERR);
4198 	}
4199 
4200 	/*
4201 	 * Check if the destination directory is empty.
4202 	 */
4203 	if ((dirp = opendir(new_zonepath)) == NULL) {
4204 		zperror(gettext("could not open new zone path"), B_FALSE);
4205 		return (Z_ERR);
4206 	}
4207 	while ((dp = readdir(dirp)) != (struct dirent *)0) {
4208 		if (strcmp(dp->d_name, ".") == 0 ||
4209 		    strcmp(dp->d_name, "..") == 0)
4210 			continue;
4211 		empty = B_FALSE;
4212 		break;
4213 	}
4214 	(void) closedir(dirp);
4215 
4216 	/* Error if there is anything in the destination directory. */
4217 	if (!empty) {
4218 		(void) fprintf(stderr, gettext("could not move zone to %s: "
4219 		    "directory not empty\n"), new_zonepath);
4220 		return (Z_ERR);
4221 	}
4222 
4223 	/* Don't move the zone if anything is still mounted there */
4224 	if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
4225 		zerror(gettext("These file systems are mounted on "
4226 		    "subdirectories of %s.\n"), zonepath);
4227 		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
4228 		return (Z_ERR);
4229 	}
4230 
4231 	/*
4232 	 * Check if we are moving in the same file system and can do a fast
4233 	 * move or if we are crossing file systems and have to copy the data.
4234 	 */
4235 	fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
4236 
4237 	if ((handle = zonecfg_init_handle()) == NULL) {
4238 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4239 		return (Z_ERR);
4240 	}
4241 
4242 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4243 		errno = err;
4244 		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4245 		zonecfg_fini_handle(handle);
4246 		return (Z_ERR);
4247 	}
4248 
4249 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4250 		zerror(gettext("another %s may have an operation in progress."),
4251 		    "zoneadm");
4252 		zonecfg_fini_handle(handle);
4253 		return (Z_ERR);
4254 	}
4255 
4256 	/*
4257 	 * We're making some file system changes now so we have to clean up
4258 	 * the file system before we are done.  This will either clean up the
4259 	 * new zonepath if the zonecfg update failed or it will clean up the
4260 	 * old zonepath if everything is ok.
4261 	 */
4262 	revert = B_TRUE;
4263 
4264 	if (is_zonepath_zfs(zonepath) &&
4265 	    move_zfs(zonepath, new_zonepath) != Z_ERR) {
4266 		is_zfs = B_TRUE;
4267 
4268 	} else if (fast) {
4269 		/* same file system, use rename for a quick move */
4270 
4271 		/*
4272 		 * Remove the new_zonepath directory that got created above
4273 		 * during the validation.  It gets in the way of the rename.
4274 		 */
4275 		if (rmdir(new_zonepath) != 0) {
4276 			zperror(gettext("could not rmdir new zone path"),
4277 			    B_FALSE);
4278 			zonecfg_fini_handle(handle);
4279 			release_lock_file(lockfd);
4280 			return (Z_ERR);
4281 		}
4282 
4283 		if (rename(zonepath, new_zonepath) != 0) {
4284 			/*
4285 			 * If this fails we don't need to do all of the
4286 			 * cleanup that happens for the rest of the code
4287 			 * so just return from this error.
4288 			 */
4289 			zperror(gettext("could not move zone"), B_FALSE);
4290 			zonecfg_fini_handle(handle);
4291 			release_lock_file(lockfd);
4292 			return (Z_ERR);
4293 		}
4294 
4295 	} else {
4296 		/*
4297 		 * Attempt to create a ZFS fs for the new zonepath.  As usual,
4298 		 * we don't care if this works or not since we always have the
4299 		 * default behavior of a simple directory for the zonepath.
4300 		 */
4301 		create_zfs_zonepath(new_zonepath);
4302 
4303 		(void) printf(gettext(
4304 		    "Moving across file systems; copying zonepath %s..."),
4305 		    zonepath);
4306 		(void) fflush(stdout);
4307 
4308 		err = copy_zone(zonepath, new_zonepath);
4309 
4310 		(void) printf("\n");
4311 		if (err != Z_OK)
4312 			goto done;
4313 	}
4314 
4315 	if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
4316 		errno = err;
4317 		zperror(gettext("could not set new zonepath"), B_TRUE);
4318 		goto done;
4319 	}
4320 
4321 	if ((err = zonecfg_save(handle)) != Z_OK) {
4322 		errno = err;
4323 		zperror(gettext("zonecfg save failed"), B_TRUE);
4324 		goto done;
4325 	}
4326 
4327 	revert = B_FALSE;
4328 
4329 done:
4330 	zonecfg_fini_handle(handle);
4331 	release_lock_file(lockfd);
4332 
4333 	/*
4334 	 * Clean up the file system based on how things went.  We either
4335 	 * clean up the new zonepath if the operation failed for some reason
4336 	 * or we clean up the old zonepath if everything is ok.
4337 	 */
4338 	if (revert) {
4339 		/* The zonecfg update failed, cleanup the new zonepath. */
4340 		if (is_zfs) {
4341 			if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
4342 				(void) fprintf(stderr, gettext("could not "
4343 				    "restore zonepath, the zfs mountpoint is "
4344 				    "set as:\n%s\n"), new_zonepath);
4345 				/*
4346 				 * err is already != Z_OK since we're reverting
4347 				 */
4348 			}
4349 
4350 		} else if (fast) {
4351 			if (rename(new_zonepath, zonepath) != 0) {
4352 				zperror(gettext("could not restore zonepath"),
4353 				    B_FALSE);
4354 				/*
4355 				 * err is already != Z_OK since we're reverting
4356 				 */
4357 			}
4358 		} else {
4359 			(void) printf(gettext("Cleaning up zonepath %s..."),
4360 			    new_zonepath);
4361 			(void) fflush(stdout);
4362 			err = cleanup_zonepath(new_zonepath, B_TRUE);
4363 			(void) printf("\n");
4364 
4365 			if (err != Z_OK) {
4366 				errno = err;
4367 				zperror(gettext("could not remove new "
4368 				    "zonepath"), B_TRUE);
4369 			} else {
4370 				/*
4371 				 * Because we're reverting we know the mainline
4372 				 * code failed but we just reused the err
4373 				 * variable so we reset it back to Z_ERR.
4374 				 */
4375 				err = Z_ERR;
4376 			}
4377 		}
4378 
4379 	} else {
4380 		/* The move was successful, cleanup the old zonepath. */
4381 		if (!is_zfs && !fast) {
4382 			(void) printf(
4383 			    gettext("Cleaning up zonepath %s..."), zonepath);
4384 			(void) fflush(stdout);
4385 			err = cleanup_zonepath(zonepath, B_TRUE);
4386 			(void) printf("\n");
4387 
4388 			if (err != Z_OK) {
4389 				errno = err;
4390 				zperror(gettext("could not remove zonepath"),
4391 				    B_TRUE);
4392 			}
4393 		}
4394 	}
4395 
4396 	return ((err == Z_OK) ? Z_OK : Z_ERR);
4397 }
4398 
4399 static int
4400 detach_func(int argc, char *argv[])
4401 {
4402 	int lockfd;
4403 	int err, arg;
4404 	char zonepath[MAXPATHLEN];
4405 	zone_dochandle_t handle;
4406 	boolean_t execute = B_TRUE;
4407 
4408 	if (zonecfg_in_alt_root()) {
4409 		zerror(gettext("cannot detach zone in alternate root"));
4410 		return (Z_ERR);
4411 	}
4412 
4413 	optind = 0;
4414 	if ((arg = getopt(argc, argv, "?n")) != EOF) {
4415 		switch (arg) {
4416 		case '?':
4417 			sub_usage(SHELP_DETACH, CMD_DETACH);
4418 			return (optopt == '?' ? Z_OK : Z_USAGE);
4419 		case 'n':
4420 			execute = B_FALSE;
4421 			break;
4422 		default:
4423 			sub_usage(SHELP_DETACH, CMD_DETACH);
4424 			return (Z_USAGE);
4425 		}
4426 	}
4427 
4428 	if (execute) {
4429 		if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE,
4430 		    B_FALSE) != Z_OK)
4431 			return (Z_ERR);
4432 		if (verify_details(CMD_DETACH, argv) != Z_OK)
4433 			return (Z_ERR);
4434 	} else {
4435 		/*
4436 		 * We want a dry-run to work for a non-privileged user so we
4437 		 * only do minimal validation.
4438 		 */
4439 		if (getzoneid() != GLOBAL_ZONEID) {
4440 			zerror(gettext("must be in the global zone to %s a "
4441 			    "zone."), cmd_to_str(CMD_DETACH));
4442 			return (Z_ERR);
4443 		}
4444 
4445 		if (target_zone == NULL) {
4446 			zerror(gettext("no zone specified"));
4447 			return (Z_ERR);
4448 		}
4449 
4450 		if (strcmp(target_zone, GLOBAL_ZONENAME) == 0) {
4451 			zerror(gettext("%s operation is invalid for the "
4452 			    "global zone."), cmd_to_str(CMD_DETACH));
4453 			return (Z_ERR);
4454 		}
4455 	}
4456 
4457 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4458 	    != Z_OK) {
4459 		errno = err;
4460 		zperror2(target_zone, gettext("could not get zone path"));
4461 		return (Z_ERR);
4462 	}
4463 
4464 	/* Don't detach the zone if anything is still mounted there */
4465 	if (execute && zonecfg_find_mounts(zonepath, NULL, NULL)) {
4466 		zerror(gettext("These file systems are mounted on "
4467 		    "subdirectories of %s.\n"), zonepath);
4468 		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
4469 		return (Z_ERR);
4470 	}
4471 
4472 	if ((handle = zonecfg_init_handle()) == NULL) {
4473 		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4474 		return (Z_ERR);
4475 	}
4476 
4477 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4478 		errno = err;
4479 		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4480 		zonecfg_fini_handle(handle);
4481 		return (Z_ERR);
4482 	}
4483 
4484 	if (execute && grab_lock_file(target_zone, &lockfd) != Z_OK) {
4485 		zerror(gettext("another %s may have an operation in progress."),
4486 		    "zoneadm");
4487 		zonecfg_fini_handle(handle);
4488 		return (Z_ERR);
4489 	}
4490 
4491 	if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) {
4492 		errno = err;
4493 		zperror(gettext("getting the detach information failed"),
4494 		    B_TRUE);
4495 		goto done;
4496 	}
4497 
4498 	if ((err = zonecfg_detach_save(handle, (execute ? 0 : ZONE_DRY_RUN)))
4499 	    != Z_OK) {
4500 		errno = err;
4501 		zperror(gettext("saving the detach manifest failed"), B_TRUE);
4502 		goto done;
4503 	}
4504 
4505 	/*
4506 	 * Set the zone state back to configured unless we are running with the
4507 	 * no-execute option.
4508 	 */
4509 	if (execute && (err = zone_set_state(target_zone,
4510 	    ZONE_STATE_CONFIGURED)) != Z_OK) {
4511 		errno = err;
4512 		zperror(gettext("could not reset state"), B_TRUE);
4513 	}
4514 
4515 done:
4516 	zonecfg_fini_handle(handle);
4517 	if (execute)
4518 		release_lock_file(lockfd);
4519 
4520 	return ((err == Z_OK) ? Z_OK : Z_ERR);
4521 }
4522 
4523 /*
4524  * During attach we go through and fix up the /dev entries for the zone
4525  * we are attaching.  In order to regenerate /dev with the correct devices,
4526  * the old /dev will be removed, the zone readied (which generates a new
4527  * /dev) then halted, then we use the info from the manifest to update
4528  * the modes, owners, etc. on the new /dev.
4529  */
4530 static int
4531 dev_fix(zone_dochandle_t handle)
4532 {
4533 	int			res;
4534 	int			err;
4535 	int			status;
4536 	struct zone_devpermtab	devtab;
4537 	zone_cmd_arg_t		zarg;
4538 	char			devpath[MAXPATHLEN];
4539 				/* 6: "exec " and " " */
4540 	char			cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6];
4541 
4542 	if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath)))
4543 	    != Z_OK)
4544 		return (res);
4545 
4546 	if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath))
4547 		return (Z_TOO_BIG);
4548 
4549 	/*
4550 	 * "exec" the command so that the returned status is that of
4551 	 * RMCOMMAND and not the shell.
4552 	 */
4553 	(void) snprintf(cmdbuf, sizeof (cmdbuf), EXEC_PREFIX RMCOMMAND " %s",
4554 	    devpath);
4555 	status = do_subproc(cmdbuf);
4556 	if ((err = subproc_status(RMCOMMAND, status, B_TRUE)) !=
4557 	    ZONE_SUBPROC_OK) {
4558 		(void) fprintf(stderr,
4559 		    gettext("could not remove existing /dev\n"));
4560 		return (Z_ERR);
4561 	}
4562 
4563 	/* In order to ready the zone, it must be in the installed state */
4564 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4565 		errno = err;
4566 		zperror(gettext("could not reset state"), B_TRUE);
4567 		return (Z_ERR);
4568 	}
4569 
4570 	/* We have to ready the zone to regen the dev tree */
4571 	zarg.cmd = Z_READY;
4572 	if (call_zoneadmd(target_zone, &zarg) != 0) {
4573 		zerror(gettext("call to %s failed"), "zoneadmd");
4574 		/* attempt to restore zone to configured state */
4575 		(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4576 		return (Z_ERR);
4577 	}
4578 
4579 	zarg.cmd = Z_HALT;
4580 	if (call_zoneadmd(target_zone, &zarg) != 0) {
4581 		zerror(gettext("call to %s failed"), "zoneadmd");
4582 		/* attempt to restore zone to configured state */
4583 		(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4584 		return (Z_ERR);
4585 	}
4586 
4587 	/* attempt to restore zone to configured state */
4588 	(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4589 
4590 	if (zonecfg_setdevperment(handle) != Z_OK) {
4591 		(void) fprintf(stderr,
4592 		    gettext("unable to enumerate device entries\n"));
4593 		return (Z_ERR);
4594 	}
4595 
4596 	while (zonecfg_getdevperment(handle, &devtab) == Z_OK) {
4597 		int err;
4598 
4599 		if ((err = zonecfg_devperms_apply(handle,
4600 		    devtab.zone_devperm_name, devtab.zone_devperm_uid,
4601 		    devtab.zone_devperm_gid, devtab.zone_devperm_mode,
4602 		    devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL)
4603 			(void) fprintf(stderr, gettext("error updating device "
4604 			    "%s: %s\n"), devtab.zone_devperm_name,
4605 			    zonecfg_strerror(err));
4606 
4607 		free(devtab.zone_devperm_acl);
4608 	}
4609 
4610 	(void) zonecfg_enddevperment(handle);
4611 
4612 	return (Z_OK);
4613 }
4614 
4615 /*
4616  * Validate attaching a zone but don't actually do the work.  The zone
4617  * does not have to exist, so there is some complexity getting a new zone
4618  * configuration set up so that we can perform the validation.  This is
4619  * handled within zonecfg_attach_manifest() which returns two handles; one
4620  * for the the full configuration to validate (rem_handle) and the other
4621  * (local_handle) containing only the zone configuration derived from the
4622  * manifest.
4623  */
4624 static int
4625 dryrun_attach(char *manifest_path, char *argv[])
4626 {
4627 	int fd;
4628 	int err;
4629 	int res;
4630 	zone_dochandle_t local_handle;
4631 	zone_dochandle_t rem_handle = NULL;
4632 
4633 	if (strcmp(manifest_path, "-") == 0) {
4634 		fd = 0;
4635 	} else if ((fd = open(manifest_path, O_RDONLY)) < 0) {
4636 		zperror(gettext("could not open manifest path"), B_FALSE);
4637 		return (Z_ERR);
4638 	}
4639 
4640 	if ((local_handle = zonecfg_init_handle()) == NULL) {
4641 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4642 		res = Z_ERR;
4643 		goto done;
4644 	}
4645 
4646 	if ((rem_handle = zonecfg_init_handle()) == NULL) {
4647 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4648 		res = Z_ERR;
4649 		goto done;
4650 	}
4651 
4652 	if ((err = zonecfg_attach_manifest(fd, local_handle, rem_handle))
4653 	    != Z_OK) {
4654 		if (err == Z_INVALID_DOCUMENT)
4655 			zerror(gettext("Cannot attach to an earlier release "
4656 			    "of the operating system"));
4657 		else
4658 			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4659 		res = Z_ERR;
4660 		goto done;
4661 	}
4662 
4663 	/*
4664 	 * Retrieve remote handle brand type and determine whether it is
4665 	 * native or not.
4666 	 */
4667 	if (zonecfg_get_brand(rem_handle, target_brand, sizeof (target_brand))
4668 	    != Z_OK) {
4669 		zerror(gettext("missing or invalid brand"));
4670 		exit(Z_ERR);
4671 	}
4672 	is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
4673 
4674 	res = verify_handle(CMD_ATTACH, local_handle, argv);
4675 
4676 	/* Get the detach information for the locally defined zone. */
4677 	if ((err = zonecfg_get_detach_info(local_handle, B_FALSE)) != Z_OK) {
4678 		errno = err;
4679 		zperror(gettext("getting the attach information failed"),
4680 		    B_TRUE);
4681 		res = Z_ERR;
4682 	} else {
4683 		/* sw_cmp prints error msgs as necessary */
4684 		if (sw_cmp(local_handle, rem_handle, SW_CMP_NONE) != Z_OK)
4685 			res = Z_ERR;
4686 	}
4687 
4688 done:
4689 	if (strcmp(manifest_path, "-") != 0)
4690 		(void) close(fd);
4691 
4692 	zonecfg_fini_handle(local_handle);
4693 	zonecfg_fini_handle(rem_handle);
4694 
4695 	return ((res == Z_OK) ? Z_OK : Z_ERR);
4696 }
4697 
4698 static int
4699 attach_func(int argc, char *argv[])
4700 {
4701 	int lockfd;
4702 	int err, arg;
4703 	boolean_t force = B_FALSE;
4704 	zone_dochandle_t handle;
4705 	zone_dochandle_t athandle = NULL;
4706 	char zonepath[MAXPATHLEN];
4707 	char brand[MAXNAMELEN], atbrand[MAXNAMELEN];
4708 	boolean_t execute = B_TRUE;
4709 	char *manifest_path;
4710 
4711 	if (zonecfg_in_alt_root()) {
4712 		zerror(gettext("cannot attach zone in alternate root"));
4713 		return (Z_ERR);
4714 	}
4715 
4716 	optind = 0;
4717 	if ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
4718 		switch (arg) {
4719 		case '?':
4720 			sub_usage(SHELP_ATTACH, CMD_ATTACH);
4721 			return (optopt == '?' ? Z_OK : Z_USAGE);
4722 		case 'F':
4723 			force = B_TRUE;
4724 			break;
4725 		case 'n':
4726 			execute = B_FALSE;
4727 			manifest_path = optarg;
4728 			break;
4729 		default:
4730 			sub_usage(SHELP_ATTACH, CMD_ATTACH);
4731 			return (Z_USAGE);
4732 		}
4733 	}
4734 
4735 	/*
4736 	 * If the no-execute option was specified, we need to branch down
4737 	 * a completely different path since there is no zone required to be
4738 	 * configured for this option.
4739 	 */
4740 	if (!execute)
4741 		return (dryrun_attach(manifest_path, argv));
4742 
4743 	if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE, B_FALSE)
4744 	    != Z_OK)
4745 		return (Z_ERR);
4746 	if (verify_details(CMD_ATTACH, argv) != Z_OK)
4747 		return (Z_ERR);
4748 
4749 	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4750 	    != Z_OK) {
4751 		errno = err;
4752 		zperror2(target_zone, gettext("could not get zone path"));
4753 		return (Z_ERR);
4754 	}
4755 
4756 	if ((handle = zonecfg_init_handle()) == NULL) {
4757 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4758 		return (Z_ERR);
4759 	}
4760 
4761 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4762 		errno = err;
4763 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4764 		zonecfg_fini_handle(handle);
4765 		return (Z_ERR);
4766 	}
4767 
4768 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4769 		zerror(gettext("another %s may have an operation in progress."),
4770 		    "zoneadm");
4771 		zonecfg_fini_handle(handle);
4772 		return (Z_ERR);
4773 	}
4774 
4775 	if (force)
4776 		goto forced;
4777 
4778 	if ((athandle = zonecfg_init_handle()) == NULL) {
4779 		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4780 		goto done;
4781 	}
4782 
4783 	if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE,
4784 	    athandle)) != Z_OK) {
4785 		if (err == Z_NO_ZONE)
4786 			zerror(gettext("Not a detached zone"));
4787 		else if (err == Z_INVALID_DOCUMENT)
4788 			zerror(gettext("Cannot attach to an earlier release "
4789 			    "of the operating system"));
4790 		else
4791 			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4792 		goto done;
4793 	}
4794 
4795 	/* Get the detach information for the locally defined zone. */
4796 	if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
4797 		errno = err;
4798 		zperror(gettext("getting the attach information failed"),
4799 		    B_TRUE);
4800 		goto done;
4801 	}
4802 
4803 	/*
4804 	 * Ensure that the detached and locally defined zones are both of
4805 	 * the same brand.
4806 	 */
4807 	if ((zonecfg_get_brand(handle, brand, sizeof (brand)) != 0) ||
4808 	    (zonecfg_get_brand(athandle, atbrand, sizeof (atbrand)) != 0)) {
4809 		err = Z_ERR;
4810 		zerror(gettext("missing or invalid brand"));
4811 		goto done;
4812 	}
4813 
4814 	if (strcmp(atbrand, brand) != NULL) {
4815 		err = Z_ERR;
4816 		zerror(gettext("Trying to attach a '%s' zone to a '%s' "
4817 		    "configuration."), atbrand, brand);
4818 		goto done;
4819 	}
4820 
4821 	/* sw_cmp prints error msgs as necessary */
4822 	if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
4823 		goto done;
4824 
4825 	if ((err = dev_fix(athandle)) != Z_OK)
4826 		goto done;
4827 
4828 forced:
4829 
4830 	zonecfg_rm_detached(handle, force);
4831 
4832 	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4833 		errno = err;
4834 		zperror(gettext("could not reset state"), B_TRUE);
4835 	}
4836 
4837 done:
4838 	zonecfg_fini_handle(handle);
4839 	release_lock_file(lockfd);
4840 	if (athandle != NULL)
4841 		zonecfg_fini_handle(athandle);
4842 
4843 	return ((err == Z_OK) ? Z_OK : Z_ERR);
4844 }
4845 
4846 /*
4847  * On input, TRUE => yes, FALSE => no.
4848  * On return, TRUE => 1, FALSE => 0, could not ask => -1.
4849  */
4850 
4851 static int
4852 ask_yesno(boolean_t default_answer, const char *question)
4853 {
4854 	char line[64];	/* should be large enough to answer yes or no */
4855 
4856 	if (!isatty(STDIN_FILENO))
4857 		return (-1);
4858 	for (;;) {
4859 		(void) printf("%s (%s)? ", question,
4860 		    default_answer ? "[y]/n" : "y/[n]");
4861 		if (fgets(line, sizeof (line), stdin) == NULL ||
4862 		    line[0] == '\n')
4863 			return (default_answer ? 1 : 0);
4864 		if (tolower(line[0]) == 'y')
4865 			return (1);
4866 		if (tolower(line[0]) == 'n')
4867 			return (0);
4868 	}
4869 }
4870 
4871 static int
4872 uninstall_func(int argc, char *argv[])
4873 {
4874 	char line[ZONENAME_MAX + 128];	/* Enough for "Are you sure ..." */
4875 	char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
4876 	boolean_t force = B_FALSE;
4877 	int lockfd, answer;
4878 	int err, arg;
4879 
4880 	if (zonecfg_in_alt_root()) {
4881 		zerror(gettext("cannot uninstall zone in alternate root"));
4882 		return (Z_ERR);
4883 	}
4884 
4885 	optind = 0;
4886 	while ((arg = getopt(argc, argv, "?F")) != EOF) {
4887 		switch (arg) {
4888 		case '?':
4889 			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4890 			return (optopt == '?' ? Z_OK : Z_USAGE);
4891 		case 'F':
4892 			force = B_TRUE;
4893 			break;
4894 		default:
4895 			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4896 			return (Z_USAGE);
4897 		}
4898 	}
4899 	if (argc > optind) {
4900 		sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4901 		return (Z_USAGE);
4902 	}
4903 
4904 	if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE, B_FALSE)
4905 	    != Z_OK)
4906 		return (Z_ERR);
4907 
4908 	/*
4909 	 * Invoke brand-specific handler.
4910 	 */
4911 	if (invoke_brand_handler(CMD_UNINSTALL, argv) != Z_OK)
4912 		return (Z_ERR);
4913 
4914 	if (!force) {
4915 		(void) snprintf(line, sizeof (line),
4916 		    gettext("Are you sure you want to %s zone %s"),
4917 		    cmd_to_str(CMD_UNINSTALL), target_zone);
4918 		if ((answer = ask_yesno(B_FALSE, line)) == 0) {
4919 			return (Z_OK);
4920 		} else if (answer == -1) {
4921 			zerror(gettext("Input not from terminal and -F "
4922 			    "not specified: %s not done."),
4923 			    cmd_to_str(CMD_UNINSTALL));
4924 			return (Z_ERR);
4925 		}
4926 	}
4927 
4928 	if ((err = zone_get_zonepath(target_zone, zonepath,
4929 	    sizeof (zonepath))) != Z_OK) {
4930 		errno = err;
4931 		zperror2(target_zone, gettext("could not get zone path"));
4932 		return (Z_ERR);
4933 	}
4934 	if ((err = zone_get_rootpath(target_zone, rootpath,
4935 	    sizeof (rootpath))) != Z_OK) {
4936 		errno = err;
4937 		zperror2(target_zone, gettext("could not get root path"));
4938 		return (Z_ERR);
4939 	}
4940 
4941 	/*
4942 	 * If there seems to be a zoneadmd running for this zone, call it
4943 	 * to tell it that an uninstall is happening; if all goes well it
4944 	 * will then shut itself down.
4945 	 */
4946 	if (ping_zoneadmd(target_zone) == Z_OK) {
4947 		zone_cmd_arg_t zarg;
4948 		zarg.cmd = Z_NOTE_UNINSTALLING;
4949 		/* we don't care too much if this fails... just plow on */
4950 		(void) call_zoneadmd(target_zone, &zarg);
4951 	}
4952 
4953 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4954 		zerror(gettext("another %s may have an operation in progress."),
4955 		    "zoneadm");
4956 		return (Z_ERR);
4957 	}
4958 
4959 	/* Don't uninstall the zone if anything is mounted there */
4960 	err = zonecfg_find_mounts(rootpath, NULL, NULL);
4961 	if (err) {
4962 		zerror(gettext("These file systems are mounted on "
4963 		    "subdirectories of %s.\n"), rootpath);
4964 		(void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
4965 		return (Z_ERR);
4966 	}
4967 
4968 	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
4969 	if (err != Z_OK) {
4970 		errno = err;
4971 		zperror2(target_zone, gettext("could not set state"));
4972 		goto bad;
4973 	}
4974 
4975 	if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
4976 		errno = err;
4977 		zperror2(target_zone, gettext("cleaning up zonepath failed"));
4978 		goto bad;
4979 	}
4980 
4981 	err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4982 	if (err != Z_OK) {
4983 		errno = err;
4984 		zperror2(target_zone, gettext("could not reset state"));
4985 	}
4986 bad:
4987 	release_lock_file(lockfd);
4988 	return (err);
4989 }
4990 
4991 /* ARGSUSED */
4992 static int
4993 mount_func(int argc, char *argv[])
4994 {
4995 	zone_cmd_arg_t zarg;
4996 	boolean_t force = B_FALSE;
4997 	int arg;
4998 
4999 	/*
5000 	 * The only supported subargument to the "mount" subcommand is
5001 	 * "-f", which forces us to mount a zone in the INCOMPLETE state.
5002 	 */
5003 	optind = 0;
5004 	if ((arg = getopt(argc, argv, "f")) != EOF) {
5005 		switch (arg) {
5006 		case 'f':
5007 			force = B_TRUE;
5008 			break;
5009 		default:
5010 			return (Z_USAGE);
5011 		}
5012 	}
5013 	if (argc > optind)
5014 		return (Z_USAGE);
5015 
5016 	if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
5017 	    != Z_OK)
5018 		return (Z_ERR);
5019 	if (verify_details(CMD_MOUNT, argv) != Z_OK)
5020 		return (Z_ERR);
5021 
5022 	zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
5023 	if (call_zoneadmd(target_zone, &zarg) != 0) {
5024 		zerror(gettext("call to %s failed"), "zoneadmd");
5025 		return (Z_ERR);
5026 	}
5027 	return (Z_OK);
5028 }
5029 
5030 /* ARGSUSED */
5031 static int
5032 unmount_func(int argc, char *argv[])
5033 {
5034 	zone_cmd_arg_t zarg;
5035 
5036 	if (argc > 0)
5037 		return (Z_USAGE);
5038 	if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5039 	    != Z_OK)
5040 		return (Z_ERR);
5041 
5042 	zarg.cmd = Z_UNMOUNT;
5043 	if (call_zoneadmd(target_zone, &zarg) != 0) {
5044 		zerror(gettext("call to %s failed"), "zoneadmd");
5045 		return (Z_ERR);
5046 	}
5047 	return (Z_OK);
5048 }
5049 
5050 static int
5051 mark_func(int argc, char *argv[])
5052 {
5053 	int err, lockfd;
5054 
5055 	if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
5056 		return (Z_USAGE);
5057 	if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
5058 	    != Z_OK)
5059 		return (Z_ERR);
5060 
5061 	/*
5062 	 * Invoke brand-specific handler.
5063 	 */
5064 	if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5065 		return (Z_ERR);
5066 
5067 	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
5068 		zerror(gettext("another %s may have an operation in progress."),
5069 		    "zoneadm");
5070 		return (Z_ERR);
5071 	}
5072 
5073 	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
5074 	if (err != Z_OK) {
5075 		errno = err;
5076 		zperror2(target_zone, gettext("could not set state"));
5077 	}
5078 	release_lock_file(lockfd);
5079 
5080 	return (err);
5081 }
5082 
5083 /*
5084  * Check what scheduling class we're running under and print a warning if
5085  * we're not using FSS.
5086  */
5087 static int
5088 check_sched_fss(zone_dochandle_t handle)
5089 {
5090 	char class_name[PC_CLNMSZ];
5091 
5092 	if (zonecfg_get_dflt_sched_class(handle, class_name,
5093 	    sizeof (class_name)) != Z_OK) {
5094 		zerror(gettext("WARNING: unable to determine the zone's "
5095 		    "scheduling class"));
5096 	} else if (strcmp("FSS", class_name) != 0) {
5097 		zerror(gettext("WARNING: The zone.cpu-shares rctl is set but\n"
5098 		    "FSS is not the default scheduling class for this zone.  "
5099 		    "FSS will be\nused for processes in the zone but to get "
5100 		    "the full benefit of FSS,\nit should be the default "
5101 		    "scheduling class.  See dispadmin(1M) for\nmore details."));
5102 		return (Z_SYSTEM);
5103 	}
5104 
5105 	return (Z_OK);
5106 }
5107 
5108 static int
5109 check_cpu_shares_sched(zone_dochandle_t handle)
5110 {
5111 	int err;
5112 	int res = Z_OK;
5113 	struct zone_rctltab rctl;
5114 
5115 	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
5116 		errno = err;
5117 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5118 		return (err);
5119 	}
5120 
5121 	while (zonecfg_getrctlent(handle, &rctl) == Z_OK) {
5122 		if (strcmp(rctl.zone_rctl_name, "zone.cpu-shares") == 0) {
5123 			if (check_sched_fss(handle) != Z_OK)
5124 				res = Z_SYSTEM;
5125 			break;
5126 		}
5127 	}
5128 
5129 	(void) zonecfg_endrctlent(handle);
5130 
5131 	return (res);
5132 }
5133 
5134 /*
5135  * Check if there is a mix of processes running in different pools within the
5136  * zone.  This is currently only going to be called for the global zone from
5137  * apply_func but that could be generalized in the future.
5138  */
5139 static boolean_t
5140 mixed_pools(zoneid_t zoneid)
5141 {
5142 	DIR *dirp;
5143 	dirent_t *dent;
5144 	boolean_t mixed = B_FALSE;
5145 	boolean_t poolid_set = B_FALSE;
5146 	poolid_t last_poolid = 0;
5147 
5148 	if ((dirp = opendir("/proc")) == NULL) {
5149 		zerror(gettext("could not open /proc"));
5150 		return (B_FALSE);
5151 	}
5152 
5153 	while ((dent = readdir(dirp)) != NULL) {
5154 		int procfd;
5155 		psinfo_t ps;
5156 		char procpath[MAXPATHLEN];
5157 
5158 		if (dent->d_name[0] == '.')
5159 			continue;
5160 
5161 		(void) snprintf(procpath, sizeof (procpath), "/proc/%s/psinfo",
5162 		    dent->d_name);
5163 
5164 		if ((procfd = open(procpath, O_RDONLY)) == -1)
5165 			continue;
5166 
5167 		if (read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) {
5168 			/* skip processes in other zones and system processes */
5169 			if (zoneid != ps.pr_zoneid || ps.pr_flag & SSYS) {
5170 				(void) close(procfd);
5171 				continue;
5172 			}
5173 
5174 			if (poolid_set) {
5175 				if (ps.pr_poolid != last_poolid)
5176 					mixed = B_TRUE;
5177 			} else {
5178 				last_poolid = ps.pr_poolid;
5179 				poolid_set = B_TRUE;
5180 			}
5181 		}
5182 
5183 		(void) close(procfd);
5184 
5185 		if (mixed)
5186 			break;
5187 	}
5188 
5189 	(void) closedir(dirp);
5190 
5191 	return (mixed);
5192 }
5193 
5194 /*
5195  * Check if a persistent or temporary pool is configured for the zone.
5196  * This is currently only going to be called for the global zone from
5197  * apply_func but that could be generalized in the future.
5198  */
5199 static boolean_t
5200 pool_configured(zone_dochandle_t handle)
5201 {
5202 	int err1, err2;
5203 	struct zone_psettab pset_tab;
5204 	char poolname[MAXPATHLEN];
5205 
5206 	err1 = zonecfg_lookup_pset(handle, &pset_tab);
5207 	err2 = zonecfg_get_pool(handle, poolname, sizeof (poolname));
5208 
5209 	if (err1 == Z_NO_ENTRY &&
5210 	    (err2 == Z_NO_ENTRY || (err2 == Z_OK && strlen(poolname) == 0)))
5211 		return (B_FALSE);
5212 
5213 	return (B_TRUE);
5214 }
5215 
5216 /*
5217  * This is an undocumented interface which is currently only used to apply
5218  * the global zone resource management settings when the system boots.
5219  * This function does not yet properly handle updating a running system so
5220  * any projects running in the zone would be trashed if this function
5221  * were to run after the zone had booted.  It also does not reset any
5222  * rctl settings that were removed from zonecfg.  There is still work to be
5223  * done before we can properly support dynamically updating the resource
5224  * management settings for a running zone (global or non-global).  Thus, this
5225  * functionality is undocumented for now.
5226  */
5227 /* ARGSUSED */
5228 static int
5229 apply_func(int argc, char *argv[])
5230 {
5231 	int err;
5232 	int res = Z_OK;
5233 	priv_set_t *privset;
5234 	zoneid_t zoneid;
5235 	zone_dochandle_t handle;
5236 	struct zone_mcaptab mcap;
5237 	char pool_err[128];
5238 
5239 	zoneid = getzoneid();
5240 
5241 	if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
5242 	    target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
5243 		return (usage(B_FALSE));
5244 
5245 	if ((privset = priv_allocset()) == NULL) {
5246 		zerror(gettext("%s failed"), "priv_allocset");
5247 		return (Z_ERR);
5248 	}
5249 
5250 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5251 		zerror(gettext("%s failed"), "getppriv");
5252 		priv_freeset(privset);
5253 		return (Z_ERR);
5254 	}
5255 
5256 	if (priv_isfullset(privset) == B_FALSE) {
5257 		(void) usage(B_FALSE);
5258 		priv_freeset(privset);
5259 		return (Z_ERR);
5260 	}
5261 	priv_freeset(privset);
5262 
5263 	if ((handle = zonecfg_init_handle()) == NULL) {
5264 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5265 		return (Z_ERR);
5266 	}
5267 
5268 	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
5269 		errno = err;
5270 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5271 		zonecfg_fini_handle(handle);
5272 		return (Z_ERR);
5273 	}
5274 
5275 	/* specific error msgs are printed within apply_rctls */
5276 	if ((err = zonecfg_apply_rctls(target_zone, handle)) != Z_OK) {
5277 		errno = err;
5278 		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5279 		res = Z_ERR;
5280 	}
5281 
5282 	if ((err = check_cpu_shares_sched(handle)) != Z_OK)
5283 		res = Z_ERR;
5284 
5285 	if (pool_configured(handle)) {
5286 		if (mixed_pools(zoneid)) {
5287 			zerror(gettext("Zone is using multiple resource "
5288 			    "pools.  The pool\nconfiguration cannot be "
5289 			    "applied without rebooting."));
5290 			res = Z_ERR;
5291 		} else {
5292 
5293 			/*
5294 			 * The next two blocks of code attempt to set up
5295 			 * temporary pools as well as persistent pools.  In
5296 			 * both cases we call the functions unconditionally.
5297 			 * Within each funtion the code will check if the zone
5298 			 * is actually configured for a temporary pool or
5299 			 * persistent pool and just return if there is nothing
5300 			 * to do.
5301 			 */
5302 			if ((err = zonecfg_bind_tmp_pool(handle, zoneid,
5303 			    pool_err, sizeof (pool_err))) != Z_OK) {
5304 				if (err == Z_POOL || err == Z_POOL_CREATE ||
5305 				    err == Z_POOL_BIND)
5306 					zerror("%s: %s", zonecfg_strerror(err),
5307 					    pool_err);
5308 				else
5309 					zerror(gettext("could not bind zone to "
5310 					    "temporary pool: %s"),
5311 					    zonecfg_strerror(err));
5312 				res = Z_ERR;
5313 			}
5314 
5315 			if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
5316 			    sizeof (pool_err))) != Z_OK) {
5317 				if (err == Z_POOL || err == Z_POOL_BIND)
5318 					zerror("%s: %s", zonecfg_strerror(err),
5319 					    pool_err);
5320 				else
5321 					zerror("%s", zonecfg_strerror(err));
5322 			}
5323 		}
5324 	}
5325 
5326 	/*
5327 	 * If a memory cap is configured, set the cap in the kernel using
5328 	 * zone_setattr() and make sure the rcapd SMF service is enabled.
5329 	 */
5330 	if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
5331 		uint64_t num;
5332 		char smf_err[128];
5333 
5334 		num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
5335 		if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
5336 			zerror(gettext("could not set zone memory cap"));
5337 			res = Z_ERR;
5338 		}
5339 
5340 		if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
5341 			zerror(gettext("enabling system/rcap service failed: "
5342 			    "%s"), smf_err);
5343 			res = Z_ERR;
5344 		}
5345 	}
5346 
5347 	zonecfg_fini_handle(handle);
5348 
5349 	return (res);
5350 }
5351 
5352 static int
5353 help_func(int argc, char *argv[])
5354 {
5355 	int arg, cmd_num;
5356 
5357 	if (argc == 0) {
5358 		(void) usage(B_TRUE);
5359 		return (Z_OK);
5360 	}
5361 	optind = 0;
5362 	if ((arg = getopt(argc, argv, "?")) != EOF) {
5363 		switch (arg) {
5364 		case '?':
5365 			sub_usage(SHELP_HELP, CMD_HELP);
5366 			return (optopt == '?' ? Z_OK : Z_USAGE);
5367 		default:
5368 			sub_usage(SHELP_HELP, CMD_HELP);
5369 			return (Z_USAGE);
5370 		}
5371 	}
5372 	while (optind < argc) {
5373 		/* Private commands have NULL short_usage; omit them */
5374 		if ((cmd_num = cmd_match(argv[optind])) < 0 ||
5375 		    cmdtab[cmd_num].short_usage == NULL) {
5376 			sub_usage(SHELP_HELP, CMD_HELP);
5377 			return (Z_USAGE);
5378 		}
5379 		sub_usage(cmdtab[cmd_num].short_usage, cmd_num);
5380 		optind++;
5381 	}
5382 	return (Z_OK);
5383 }
5384 
5385 /*
5386  * Returns: CMD_MIN thru CMD_MAX on success, -1 on error
5387  */
5388 
5389 static int
5390 cmd_match(char *cmd)
5391 {
5392 	int i;
5393 
5394 	for (i = CMD_MIN; i <= CMD_MAX; i++) {
5395 		/* return only if there is an exact match */
5396 		if (strcmp(cmd, cmdtab[i].cmd_name) == 0)
5397 			return (cmdtab[i].cmd_num);
5398 	}
5399 	return (-1);
5400 }
5401 
5402 static int
5403 parse_and_run(int argc, char *argv[])
5404 {
5405 	int i = cmd_match(argv[0]);
5406 
5407 	if (i < 0)
5408 		return (usage(B_FALSE));
5409 	return (cmdtab[i].handler(argc - 1, &(argv[1])));
5410 }
5411 
5412 static char *
5413 get_execbasename(char *execfullname)
5414 {
5415 	char *last_slash, *execbasename;
5416 
5417 	/* guard against '/' at end of command invocation */
5418 	for (;;) {
5419 		last_slash = strrchr(execfullname, '/');
5420 		if (last_slash == NULL) {
5421 			execbasename = execfullname;
5422 			break;
5423 		} else {
5424 			execbasename = last_slash + 1;
5425 			if (*execbasename == '\0') {
5426 				*last_slash = '\0';
5427 				continue;
5428 			}
5429 			break;
5430 		}
5431 	}
5432 	return (execbasename);
5433 }
5434 
5435 int
5436 main(int argc, char **argv)
5437 {
5438 	int arg;
5439 	zoneid_t zid;
5440 	struct stat st;
5441 	char *zone_lock_env;
5442 	int err;
5443 
5444 	if ((locale = setlocale(LC_ALL, "")) == NULL)
5445 		locale = "C";
5446 	(void) textdomain(TEXT_DOMAIN);
5447 	setbuf(stdout, NULL);
5448 	(void) sigset(SIGHUP, SIG_IGN);
5449 	execname = get_execbasename(argv[0]);
5450 	target_zone = NULL;
5451 	if (chdir("/") != 0) {
5452 		zerror(gettext("could not change directory to /."));
5453 		exit(Z_ERR);
5454 	}
5455 
5456 	if (init_zfs() != Z_OK)
5457 		exit(Z_ERR);
5458 
5459 	while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) {
5460 		switch (arg) {
5461 		case '?':
5462 			return (usage(B_TRUE));
5463 		case 'u':
5464 			target_uuid = optarg;
5465 			break;
5466 		case 'z':
5467 			target_zone = optarg;
5468 			break;
5469 		case 'R':	/* private option for admin/install use */
5470 			if (*optarg != '/') {
5471 				zerror(gettext("root path must be absolute."));
5472 				exit(Z_ERR);
5473 			}
5474 			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
5475 				zerror(
5476 				    gettext("root path must be a directory."));
5477 				exit(Z_ERR);
5478 			}
5479 			zonecfg_set_root(optarg);
5480 			break;
5481 		default:
5482 			return (usage(B_FALSE));
5483 		}
5484 	}
5485 
5486 	if (optind >= argc)
5487 		return (usage(B_FALSE));
5488 
5489 	if (target_uuid != NULL && *target_uuid != '\0') {
5490 		uuid_t uuid;
5491 		static char newtarget[ZONENAME_MAX];
5492 
5493 		if (uuid_parse(target_uuid, uuid) == -1) {
5494 			zerror(gettext("illegal UUID value specified"));
5495 			exit(Z_ERR);
5496 		}
5497 		if (zonecfg_get_name_by_uuid(uuid, newtarget,
5498 		    sizeof (newtarget)) == Z_OK)
5499 			target_zone = newtarget;
5500 	}
5501 
5502 	if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
5503 		errno = Z_NO_ZONE;
5504 		zperror(target_zone, B_TRUE);
5505 		exit(Z_ERR);
5506 	}
5507 
5508 	/*
5509 	 * See if we have inherited the right to manipulate this zone from
5510 	 * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
5511 	 * indicate it.  If not, make that explicit in our environment.
5512 	 */
5513 	zone_lock_env = getenv(LOCK_ENV_VAR);
5514 	if (zone_lock_env == NULL) {
5515 		if (putenv(zoneadm_lock_not_held) != 0) {
5516 			zperror(target_zone, B_TRUE);
5517 			exit(Z_ERR);
5518 		}
5519 	} else {
5520 		zoneadm_is_nested = B_TRUE;
5521 		if (atoi(zone_lock_env) == 1)
5522 			zone_lock_cnt = 1;
5523 	}
5524 
5525 	/*
5526 	 * If we are going to be operating on a single zone, retrieve its
5527 	 * brand type and determine whether it is native or not.
5528 	 */
5529 	if ((target_zone != NULL) &&
5530 	    (strcmp(target_zone, GLOBAL_ZONENAME) != NULL)) {
5531 		if (zone_get_brand(target_zone, target_brand,
5532 		    sizeof (target_brand)) != Z_OK) {
5533 			zerror(gettext("missing or invalid brand"));
5534 			exit(Z_ERR);
5535 		}
5536 		is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
5537 	}
5538 
5539 	err = parse_and_run(argc - optind, &argv[optind]);
5540 
5541 	return (err);
5542 }
5543