zoneadmd.c (ffbafc5382b8d46def826aec8c419ad31dff8ebd) zoneadmd.c (3f2f09c1efd66f6d2995998ea72c5df8c70c9a97)
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

--- 226 unchanged lines hidden (view full) ---

235
236 buflen = snprintf(zlogp->log, zlogp->loglen, "%s\n", buf);
237 copylen = MIN(buflen, zlogp->loglen);
238 zlogp->log += copylen;
239 zlogp->loglen -= copylen;
240 }
241}
242
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

--- 226 unchanged lines hidden (view full) ---

235
236 buflen = snprintf(zlogp->log, zlogp->loglen, "%s\n", buf);
237 copylen = MIN(buflen, zlogp->loglen);
238 zlogp->log += copylen;
239 zlogp->loglen -= copylen;
240 }
241}
242
243/*
244 * Emit a warning for any boot arguments which are unrecognized. Since
245 * Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we
246 * put the arguments into an argv style array, use getopt to process them,
247 * and put the resultant argument string back into outargs.
248 *
249 * During the filtering, we pull out any arguments which are truly "boot"
250 * arguments, leaving only those which are to be passed intact to the
251 * progenitor process. The one we support at the moment is -i, which
252 * indicates to the kernel which program should be launched as 'init'.
253 *
254 * A return of Z_INVAL indicates specifically that the arguments are
255 * not valid; this is a non-fatal error. Except for Z_OK, all other return
256 * values are treated as fatal.
257 */
243static int
258static int
259filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
260 char *init_file, char *badarg)
261{
262 int argc = 0, argc_save;
263 int i;
264 int err;
265 char *arg, *lasts, **argv = NULL, **argv_save;
266 char zonecfg_args[BOOTARGS_MAX];
267 char scratchargs[BOOTARGS_MAX], *sargs;
268 char c;
269
270 bzero(outargs, BOOTARGS_MAX);
271 bzero(badarg, BOOTARGS_MAX);
272
273 (void) strlcpy(init_file, PATH_TO_INIT, MAXPATHLEN);
274
275 /*
276 * If the user didn't specify transient boot arguments, check
277 * to see if there were any specified in the zone configuration,
278 * and use them if applicable.
279 */
280 if (inargs == NULL || inargs[0] == '\0') {
281 zone_dochandle_t handle;
282 if ((handle = zonecfg_init_handle()) == NULL) {
283 zerror(zlogp, B_TRUE,
284 "getting zone configuration handle");
285 return (Z_BAD_HANDLE);
286 }
287 err = zonecfg_get_snapshot_handle(zone_name, handle);
288 if (err != Z_OK) {
289 zerror(zlogp, B_FALSE,
290 "invalid configuration snapshot");
291 zonecfg_fini_handle(handle);
292 return (Z_BAD_HANDLE);
293 }
294
295 bzero(zonecfg_args, sizeof (zonecfg_args));
296 (void) zonecfg_get_bootargs(handle, zonecfg_args,
297 sizeof (zonecfg_args));
298 inargs = zonecfg_args;
299 zonecfg_fini_handle(handle);
300 }
301
302 if (strlen(inargs) >= BOOTARGS_MAX) {
303 zerror(zlogp, B_FALSE, "boot argument string too long");
304 return (Z_INVAL);
305 }
306
307 (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
308 sargs = scratchargs;
309 while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
310 sargs = NULL;
311 argc++;
312 }
313
314 if ((argv = calloc(argc + 1, sizeof (char *))) == NULL) {
315 zerror(zlogp, B_FALSE, "memory allocation failed");
316 return (Z_NOMEM);
317 }
318
319 argv_save = argv;
320 argc_save = argc;
321
322 (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
323 sargs = scratchargs;
324 i = 0;
325 while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
326 sargs = NULL;
327 if ((argv[i] = strdup(arg)) == NULL) {
328 err = Z_NOMEM;
329 zerror(zlogp, B_FALSE, "memory allocation failed");
330 goto done;
331 }
332 i++;
333 }
334
335 /*
336 * We preserve compatibility with the Solaris system boot behavior,
337 * which allows:
338 *
339 * # reboot kernel/unix -s -m verbose
340 *
341 * In this example, kernel/unix tells the booter what file to
342 * boot. We don't want reboot in a zone to be gratuitously different,
343 * so we silently ignore the boot file, if necessary.
344 */
345 if (argv[0] == NULL)
346 goto done;
347
348 assert(argv[0][0] != ' ');
349 assert(argv[0][0] != '\t');
350
351 if (argv[0][0] != '-' && argv[0][0] != '\0') {
352 argv = &argv[1];
353 argc--;
354 }
355
356 optind = 0;
357 opterr = 0;
358 err = Z_OK;
359 while ((c = getopt(argc, argv, "i:m:s")) != -1) {
360 switch (c) {
361 case 'i':
362 /*
363 * -i is handled by the runtime and is not passed
364 * along to userland
365 */
366 (void) strlcpy(init_file, optarg, MAXPATHLEN);
367 break;
368 case 'm':
369 case 's':
370 /* These pass through unmolested */
371 (void) snprintf(outargs, BOOTARGS_MAX,
372 "%s -%c %s ", outargs, c, optarg ? optarg : "");
373 break;
374 case '?':
375 /*
376 * We warn about unknown arguments but pass them
377 * along anyway-- if someone wants to develop their
378 * own init replacement, they can pass it whatever
379 * args they want.
380 */
381 err = Z_INVAL;
382 (void) snprintf(outargs, BOOTARGS_MAX,
383 "%s -%c", outargs, optopt);
384 (void) snprintf(badarg, BOOTARGS_MAX,
385 "%s -%c", badarg, optopt);
386 break;
387 }
388 }
389
390 /*
391 * For Solaris Zones we warn about and discard non-option arguments.
392 * Hence 'boot foo bar baz gub' --> 'boot'. However, to be similar
393 * to the kernel, we concat up all the other remaining boot args.
394 * and warn on them as a group.
395 */
396 if (optind < argc) {
397 err = Z_INVAL;
398 while (optind < argc) {
399 (void) snprintf(badarg, BOOTARGS_MAX, "%s%s%s",
400 badarg, strlen(badarg) > 0 ? " " : "",
401 argv[optind]);
402 optind++;
403 }
404 zerror(zlogp, B_FALSE, "WARNING: Unused or invalid boot "
405 "arguments `%s'.", badarg);
406 }
407
408done:
409 for (i = 0; i < argc_save; i++) {
410 if (argv_save[i] != NULL)
411 free(argv_save[i]);
412 }
413 free(argv_save);
414 return (err);
415}
416
417
418static int
244mkzonedir(zlog_t *zlogp)
245{
246 struct stat st;
247 /*
248 * We must create and lock everyone but root out of ZONES_TMPDIR
249 * since anyone can open any UNIX domain socket, regardless of
250 * its file system permissions. Sigh...
251 */

--- 146 unchanged lines hidden (view full) ---

398 return (0);
399}
400
401static int
402zone_bootup(zlog_t *zlogp, const char *bootargs)
403{
404 zoneid_t zoneid;
405 struct stat st;
419mkzonedir(zlog_t *zlogp)
420{
421 struct stat st;
422 /*
423 * We must create and lock everyone but root out of ZONES_TMPDIR
424 * since anyone can open any UNIX domain socket, regardless of
425 * its file system permissions. Sigh...
426 */

--- 146 unchanged lines hidden (view full) ---

573 return (0);
574}
575
576static int
577zone_bootup(zlog_t *zlogp, const char *bootargs)
578{
579 zoneid_t zoneid;
580 struct stat st;
406 char zroot[MAXPATHLEN], initpath[MAXPATHLEN];
581 char zroot[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
582 char nbootargs[BOOTARGS_MAX];
583 int err;
407
408 if (init_console_slave(zlogp) != 0)
409 return (-1);
410 reset_slave_terminal(zlogp);
411
412 if ((zoneid = getzoneidbyname(zone_name)) == -1) {
413 zerror(zlogp, B_TRUE, "unable to get zoneid");
414 return (-1);
415 }
416
417 if (zone_mount_early(zlogp, zoneid) != 0)
418 return (-1);
419
584
585 if (init_console_slave(zlogp) != 0)
586 return (-1);
587 reset_slave_terminal(zlogp);
588
589 if ((zoneid = getzoneidbyname(zone_name)) == -1) {
590 zerror(zlogp, B_TRUE, "unable to get zoneid");
591 return (-1);
592 }
593
594 if (zone_mount_early(zlogp, zoneid) != 0)
595 return (-1);
596
597 err = filter_bootargs(zlogp, bootargs, nbootargs, init_file,
598 bad_boot_arg);
599 if (err == Z_INVAL)
600 eventstream_write(Z_EVT_ZONE_BADARGS);
601 else if (err != Z_OK)
602 return (-1);
603
604 assert(init_file[0] != '\0');
605
420 /*
606 /*
421 * Try to anticipate possible problems: Make sure init is executable.
607 * Try to anticipate possible problems: Make sure whatever binary
608 * is supposed to be init is executable.
422 */
423 if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) {
424 zerror(zlogp, B_FALSE, "unable to determine zone root");
425 return (-1);
426 }
609 */
610 if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) {
611 zerror(zlogp, B_FALSE, "unable to determine zone root");
612 return (-1);
613 }
427 (void) snprintf(initpath, sizeof (initpath), "%s%s", zroot,
428 PATH_TO_INIT);
614 (void) snprintf(initpath, sizeof (initpath), "%s%s", zroot, init_file);
429
430 if (stat(initpath, &st) == -1) {
431 zerror(zlogp, B_TRUE, "could not stat %s", initpath);
432 return (-1);
433 }
434
435 if ((st.st_mode & S_IXUSR) == 0) {
436 zerror(zlogp, B_FALSE, "%s is not executable", initpath);
437 return (-1);
438 }
439
615
616 if (stat(initpath, &st) == -1) {
617 zerror(zlogp, B_TRUE, "could not stat %s", initpath);
618 return (-1);
619 }
620
621 if ((st.st_mode & S_IXUSR) == 0) {
622 zerror(zlogp, B_FALSE, "%s is not executable", initpath);
623 return (-1);
624 }
625
440 if (zone_boot(zoneid, bootargs) == -1) {
626 if (zone_setattr(zoneid, ZONE_ATTR_INITNAME, init_file, 0) == -1) {
627 zerror(zlogp, B_TRUE, "could not set zone boot file");
628 return (-1);
629 }
630
631 if (zone_setattr(zoneid, ZONE_ATTR_BOOTARGS, nbootargs, 0) == -1) {
632 zerror(zlogp, B_TRUE, "could not set zone boot arguments");
633 return (-1);
634 }
635
636 if (zone_boot(zoneid) == -1) {
441 zerror(zlogp, B_TRUE, "unable to boot zone");
442 return (-1);
443 }
444
445 return (0);
446}
447
448static int

--- 114 unchanged lines hidden (view full) ---

563 zlog.log = zlog.buf;
564 /* defer initialization of zlog.locale until after credential check */
565 zlogp = &zlog;
566
567 if (alen != sizeof (zone_cmd_arg_t)) {
568 /*
569 * This really shouldn't be happening.
570 */
637 zerror(zlogp, B_TRUE, "unable to boot zone");
638 return (-1);
639 }
640
641 return (0);
642}
643
644static int

--- 114 unchanged lines hidden (view full) ---

759 zlog.log = zlog.buf;
760 /* defer initialization of zlog.locale until after credential check */
761 zlogp = &zlog;
762
763 if (alen != sizeof (zone_cmd_arg_t)) {
764 /*
765 * This really shouldn't be happening.
766 */
571 zerror(&logsys, B_FALSE, "invalid argument");
767 zerror(&logsys, B_FALSE, "argument size (%d bytes) "
768 "unexpected (expected %d bytes)", alen,
769 sizeof (zone_cmd_arg_t));
572 goto out;
573 }
574 cmd = zargp->cmd;
575
576 if (door_ucred(&uc) != 0) {
577 zerror(&logsys, B_TRUE, "door_ucred");
578 goto out;
579 }

--- 169 unchanged lines hidden (view full) ---

749 * zone; the second client loses, but his request
750 * doesn't fail, since the zone is now in the desired
751 * state.
752 */
753 zerror(zlogp, B_FALSE, "zone is already ready");
754 rval = 0;
755 break;
756 case Z_BOOT:
770 goto out;
771 }
772 cmd = zargp->cmd;
773
774 if (door_ucred(&uc) != 0) {
775 zerror(&logsys, B_TRUE, "door_ucred");
776 goto out;
777 }

--- 169 unchanged lines hidden (view full) ---

947 * zone; the second client loses, but his request
948 * doesn't fail, since the zone is now in the desired
949 * state.
950 */
951 zerror(zlogp, B_FALSE, "zone is already ready");
952 rval = 0;
953 break;
954 case Z_BOOT:
955 (void) strlcpy(boot_args, zargp->bootbuf,
956 sizeof (boot_args));
757 eventstream_write(Z_EVT_ZONE_BOOTING);
758 rval = zone_bootup(zlogp, zargp->bootbuf);
759 audit_put_record(zlogp, uc, rval, "boot");
760 if (rval != 0) {
761 bringup_failure_recovery = B_TRUE;
762 (void) zone_halt(zlogp, B_FALSE);
763 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
764 }
957 eventstream_write(Z_EVT_ZONE_BOOTING);
958 rval = zone_bootup(zlogp, zargp->bootbuf);
959 audit_put_record(zlogp, uc, rval, "boot");
960 if (rval != 0) {
961 bringup_failure_recovery = B_TRUE;
962 (void) zone_halt(zlogp, B_FALSE);
963 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
964 }
965 boot_args[0] = '\0';
765 break;
766 case Z_HALT:
767 if (kernelcall) /* Invalid; can't happen */
768 abort();
769 if ((rval = zone_halt(zlogp, B_FALSE)) != 0)
770 break;
771 eventstream_write(Z_EVT_ZONE_HALTED);
772 break;

--- 56 unchanged lines hidden (view full) ---

829 rval = 0;
830 break;
831 case Z_HALT:
832 if ((rval = zone_halt(zlogp, B_FALSE)) != 0)
833 break;
834 eventstream_write(Z_EVT_ZONE_HALTED);
835 break;
836 case Z_REBOOT:
966 break;
967 case Z_HALT:
968 if (kernelcall) /* Invalid; can't happen */
969 abort();
970 if ((rval = zone_halt(zlogp, B_FALSE)) != 0)
971 break;
972 eventstream_write(Z_EVT_ZONE_HALTED);
973 break;

--- 56 unchanged lines hidden (view full) ---

1030 rval = 0;
1031 break;
1032 case Z_HALT:
1033 if ((rval = zone_halt(zlogp, B_FALSE)) != 0)
1034 break;
1035 eventstream_write(Z_EVT_ZONE_HALTED);
1036 break;
1037 case Z_REBOOT:
1038 (void) strlcpy(boot_args, zargp->bootbuf,
1039 sizeof (boot_args));
837 eventstream_write(Z_EVT_ZONE_REBOOTING);
838 if ((rval = zone_halt(zlogp, B_FALSE)) != 0) {
839 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1040 eventstream_write(Z_EVT_ZONE_REBOOTING);
1041 if ((rval = zone_halt(zlogp, B_FALSE)) != 0) {
1042 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1043 boot_args[0] = '\0';
840 break;
841 }
842 if ((rval = zone_ready(zlogp, B_FALSE)) != 0) {
843 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1044 break;
1045 }
1046 if ((rval = zone_ready(zlogp, B_FALSE)) != 0) {
1047 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1048 boot_args[0] = '\0';
844 break;
845 }
1049 break;
1050 }
846 rval = zone_bootup(zlogp, "");
1051 rval = zone_bootup(zlogp, zargp->bootbuf);
847 audit_put_record(zlogp, uc, rval, "reboot");
848 if (rval != 0) {
849 (void) zone_halt(zlogp, B_FALSE);
850 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
851 }
1052 audit_put_record(zlogp, uc, rval, "reboot");
1053 if (rval != 0) {
1054 (void) zone_halt(zlogp, B_FALSE);
1055 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1056 }
1057 boot_args[0] = '\0';
852 break;
853 case Z_NOTE_UNINSTALLING:
854 case Z_MOUNT:
855 case Z_UNMOUNT:
856 zerror(zlogp, B_FALSE, "%s operation is invalid "
857 "for zones in state '%s'", z_cmd_name(cmd),
858 zone_state_str(zstate));
859 rval = -1;

--- 79 unchanged lines hidden (view full) ---

939 int doorfd = -1;
940 int err, ret = -1;
941 struct stat st;
942 struct flock flock;
943 zone_state_t zstate;
944
945top:
946 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1058 break;
1059 case Z_NOTE_UNINSTALLING:
1060 case Z_MOUNT:
1061 case Z_UNMOUNT:
1062 zerror(zlogp, B_FALSE, "%s operation is invalid "
1063 "for zones in state '%s'", z_cmd_name(cmd),
1064 zone_state_str(zstate));
1065 rval = -1;

--- 79 unchanged lines hidden (view full) ---

1145 int doorfd = -1;
1146 int err, ret = -1;
1147 struct stat st;
1148 struct flock flock;
1149 zone_state_t zstate;
1150
1151top:
1152 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
947 zerror(zlogp, B_FALSE, "failed to get zone state: %s\n",
1153 zerror(zlogp, B_FALSE, "failed to get zone state: %s",
948 zonecfg_strerror(err));
949 goto out;
950 }
951 if ((doorfd = open(zone_door_path, O_CREAT|O_RDWR,
952 S_IREAD|S_IWRITE)) < 0) {
953 zerror(zlogp, B_TRUE, "failed to open %s", zone_door_path);
954 goto out;
955 }

--- 164 unchanged lines hidden (view full) ---

1120 */
1121 if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
1122 zerror(zlogp, B_FALSE, "cannot manage the %s zone",
1123 GLOBAL_ZONENAME);
1124 return (1);
1125 }
1126
1127 if (zone_get_id(zone_name, &zid) != 0) {
1154 zonecfg_strerror(err));
1155 goto out;
1156 }
1157 if ((doorfd = open(zone_door_path, O_CREAT|O_RDWR,
1158 S_IREAD|S_IWRITE)) < 0) {
1159 zerror(zlogp, B_TRUE, "failed to open %s", zone_door_path);
1160 goto out;
1161 }

--- 164 unchanged lines hidden (view full) ---

1326 */
1327 if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
1328 zerror(zlogp, B_FALSE, "cannot manage the %s zone",
1329 GLOBAL_ZONENAME);
1330 return (1);
1331 }
1332
1333 if (zone_get_id(zone_name, &zid) != 0) {
1128 zerror(zlogp, B_FALSE, "could not manage %s: %s\n", zone_name,
1334 zerror(zlogp, B_FALSE, "could not manage %s: %s", zone_name,
1129 zonecfg_strerror(Z_NO_ZONE));
1130 return (1);
1131 }
1132
1133 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1335 zonecfg_strerror(Z_NO_ZONE));
1336 return (1);
1337 }
1338
1339 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1134 zerror(zlogp, B_FALSE, "failed to get zone state: %s\n",
1340 zerror(zlogp, B_FALSE, "failed to get zone state: %s",
1135 zonecfg_strerror(err));
1136 return (1);
1137 }
1138 if (zstate < ZONE_STATE_INSTALLED) {
1139 zerror(zlogp, B_FALSE,
1140 "cannot manage a zone which is in state '%s'",
1141 zone_state_str(zstate));
1142 return (1);

--- 11 unchanged lines hidden (view full) ---

1154 if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1155 zerror(zlogp, B_TRUE, "%s failed", "getppriv");
1156 priv_freeset(privset);
1157 return (1);
1158 }
1159
1160 if (priv_isfullset(privset) == B_FALSE) {
1161 zerror(zlogp, B_FALSE, "You lack sufficient privilege to "
1341 zonecfg_strerror(err));
1342 return (1);
1343 }
1344 if (zstate < ZONE_STATE_INSTALLED) {
1345 zerror(zlogp, B_FALSE,
1346 "cannot manage a zone which is in state '%s'",
1347 zone_state_str(zstate));
1348 return (1);

--- 11 unchanged lines hidden (view full) ---

1360 if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1361 zerror(zlogp, B_TRUE, "%s failed", "getppriv");
1362 priv_freeset(privset);
1363 return (1);
1364 }
1365
1366 if (priv_isfullset(privset) == B_FALSE) {
1367 zerror(zlogp, B_FALSE, "You lack sufficient privilege to "
1162 "run this command (all privs required)\n");
1368 "run this command (all privs required)");
1163 priv_freeset(privset);
1164 return (1);
1165 }
1166 priv_freeset(privset);
1167
1168 if (mkzonedir(zlogp) != 0)
1169 return (1);
1170

--- 244 unchanged lines hidden ---
1369 priv_freeset(privset);
1370 return (1);
1371 }
1372 priv_freeset(privset);
1373
1374 if (mkzonedir(zlogp) != 0)
1375 return (1);
1376

--- 244 unchanged lines hidden ---