Print this page
Fixes to allow compilation on OmniOS and OI
OS-3342+co
OS-1572
OS-327
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/zoneadmd/zoneadmd.c
+++ new/usr/src/cmd/zoneadmd/zoneadmd.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * zoneadmd manages zones; one zoneadmd process is launched for each
29 29 * non-global zone on the system. This daemon juggles four jobs:
30 30 *
31 31 * - Implement setup and teardown of the zone "virtual platform": mount and
32 32 * unmount filesystems; create and destroy network interfaces; communicate
33 33 * with devfsadmd to lay out devices for the zone; instantiate the zone
34 34 * console device; configure process runtime attributes such as resource
35 35 * controls, pool bindings, fine-grained privileges.
36 36 *
37 37 * - Launch the zone's init(1M) process.
38 38 *
39 39 * - Implement a door server; clients (like zoneadm) connect to the door
40 40 * server and request zone state changes. The kernel is also a client of
41 41 * this door server. A request to halt or reboot the zone which originates
42 42 * *inside* the zone results in a door upcall from the kernel into zoneadmd.
43 43 *
44 44 * One minor problem is that messages emitted by zoneadmd need to be passed
45 45 * back to the zoneadm process making the request. These messages need to
46 46 * be rendered in the client's locale; so, this is passed in as part of the
47 47 * request. The exception is the kernel upcall to zoneadmd, in which case
48 48 * messages are syslog'd.
49 49 *
50 50 * To make all of this work, the Makefile adds -a to xgettext to extract *all*
51 51 * strings, and an exclusion file (zoneadmd.xcl) is used to exclude those
52 52 * strings which do not need to be translated.
53 53 *
54 54 * - Act as a console server for zlogin -C processes; see comments in zcons.c
55 55 * for more information about the zone console architecture.
56 56 *
57 57 * DESIGN NOTES
58 58 *
59 59 * Restart:
60 60 * A chief design constraint of zoneadmd is that it should be restartable in
61 61 * the case that the administrator kills it off, or it suffers a fatal error,
62 62 * without the running zone being impacted; this is akin to being able to
63 63 * reboot the service processor of a server without affecting the OS instance.
64 64 */
65 65
66 66 #include <sys/param.h>
67 67 #include <sys/mman.h>
68 68 #include <sys/types.h>
69 69 #include <sys/stat.h>
70 70 #include <sys/sysmacros.h>
71 71
72 72 #include <bsm/adt.h>
73 73 #include <bsm/adt_event.h>
74 74
75 75 #include <alloca.h>
76 76 #include <assert.h>
77 77 #include <errno.h>
78 78 #include <door.h>
79 79 #include <fcntl.h>
80 80 #include <locale.h>
81 81 #include <signal.h>
82 82 #include <stdarg.h>
83 83 #include <stdio.h>
84 84 #include <stdlib.h>
85 85 #include <string.h>
86 86 #include <strings.h>
87 87 #include <synch.h>
88 88 #include <syslog.h>
89 89 #include <thread.h>
90 90 #include <unistd.h>
91 91 #include <wait.h>
92 92 #include <limits.h>
93 93 #include <zone.h>
94 94 #include <libbrand.h>
95 95 #include <sys/brand.h>
96 96 #include <libcontract.h>
97 97 #include <libcontract_priv.h>
98 98 #include <sys/brand.h>
99 99 #include <sys/contract/process.h>
100 100 #include <sys/ctfs.h>
101 101 #include <libdladm.h>
102 102 #include <sys/dls_mgmt.h>
103 103 #include <libscf.h>
104 104
105 105 #include <libzonecfg.h>
106 106 #include <zonestat_impl.h>
107 107 #include "zoneadmd.h"
108 108
109 109 static char *progname;
110 110 char *zone_name; /* zone which we are managing */
111 111 char pool_name[MAXNAMELEN];
112 112 char default_brand[MAXNAMELEN];
113 113 char brand_name[MAXNAMELEN];
114 114 boolean_t zone_isnative;
115 115 boolean_t zone_iscluster;
116 116 boolean_t zone_islabeled;
117 117 boolean_t shutdown_in_progress;
118 118 static zoneid_t zone_id;
119 119 dladm_handle_t dld_handle = NULL;
120 120
121 121 static char pre_statechg_hook[2 * MAXPATHLEN];
122 122 static char post_statechg_hook[2 * MAXPATHLEN];
123 123 char query_hook[2 * MAXPATHLEN];
124 124
125 125 zlog_t logsys;
126 126
127 127 mutex_t lock = DEFAULTMUTEX; /* to serialize stuff */
128 128 mutex_t msglock = DEFAULTMUTEX; /* for calling setlocale() */
129 129
130 130 static sema_t scratch_sem; /* for scratch zones */
131 131
132 132 static char zone_door_path[MAXPATHLEN];
133 133 static int zone_door = -1;
134 134
135 135 boolean_t in_death_throes = B_FALSE; /* daemon is dying */
136 136 boolean_t bringup_failure_recovery = B_FALSE; /* ignore certain failures */
137 137
138 138 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
139 139 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
140 140 #endif
141 141
142 142 #define DEFAULT_LOCALE "C"
143 143
144 144 static const char *
145 145 z_cmd_name(zone_cmd_t zcmd)
146 146 {
147 147 /* This list needs to match the enum in sys/zone.h */
148 148 static const char *zcmdstr[] = {
149 149 "ready", "boot", "forceboot", "reboot", "halt",
150 150 "note_uninstalling", "mount", "forcemount", "unmount",
151 151 "shutdown"
152 152 };
153 153
154 154 if (zcmd >= sizeof (zcmdstr) / sizeof (*zcmdstr))
155 155 return ("unknown");
156 156 else
157 157 return (zcmdstr[(int)zcmd]);
158 158 }
159 159
160 160 static char *
161 161 get_execbasename(char *execfullname)
162 162 {
163 163 char *last_slash, *execbasename;
164 164
165 165 /* guard against '/' at end of command invocation */
166 166 for (;;) {
167 167 last_slash = strrchr(execfullname, '/');
168 168 if (last_slash == NULL) {
169 169 execbasename = execfullname;
170 170 break;
171 171 } else {
172 172 execbasename = last_slash + 1;
173 173 if (*execbasename == '\0') {
174 174 *last_slash = '\0';
175 175 continue;
176 176 }
177 177 break;
178 178 }
179 179 }
180 180 return (execbasename);
181 181 }
182 182
183 183 static void
184 184 usage(void)
185 185 {
186 186 (void) fprintf(stderr, gettext("Usage: %s -z zonename\n"), progname);
187 187 (void) fprintf(stderr,
188 188 gettext("\tNote: %s should not be run directly.\n"), progname);
189 189 exit(2);
190 190 }
191 191
192 192 /* ARGSUSED */
193 193 static void
194 194 sigchld(int sig)
195 195 {
196 196 }
197 197
198 198 char *
199 199 localize_msg(char *locale, const char *msg)
200 200 {
201 201 char *out;
202 202
203 203 (void) mutex_lock(&msglock);
204 204 (void) setlocale(LC_MESSAGES, locale);
205 205 out = gettext(msg);
206 206 (void) setlocale(LC_MESSAGES, DEFAULT_LOCALE);
207 207 (void) mutex_unlock(&msglock);
208 208 return (out);
209 209 }
210 210
211 211 /* PRINTFLIKE3 */
212 212 void
213 213 zerror(zlog_t *zlogp, boolean_t use_strerror, const char *fmt, ...)
214 214 {
215 215 va_list alist;
216 216 char buf[MAXPATHLEN * 2]; /* enough space for err msg with a path */
217 217 char *bp;
218 218 int saved_errno = errno;
219 219
220 220 if (zlogp == NULL)
221 221 return;
222 222 if (zlogp == &logsys)
223 223 (void) snprintf(buf, sizeof (buf), "[zone '%s'] ",
224 224 zone_name);
225 225 else
226 226 buf[0] = '\0';
227 227 bp = &(buf[strlen(buf)]);
228 228
229 229 /*
230 230 * In theory, the locale pointer should be set to either "C" or a
231 231 * char array, so it should never be NULL
232 232 */
233 233 assert(zlogp->locale != NULL);
234 234 /* Locale is per process, but we are multi-threaded... */
235 235 fmt = localize_msg(zlogp->locale, fmt);
236 236
237 237 va_start(alist, fmt);
238 238 (void) vsnprintf(bp, sizeof (buf) - (bp - buf), fmt, alist);
239 239 va_end(alist);
240 240 bp = &(buf[strlen(buf)]);
241 241 if (use_strerror)
242 242 (void) snprintf(bp, sizeof (buf) - (bp - buf), ": %s",
243 243 strerror(saved_errno));
244 244 if (zlogp == &logsys) {
245 245 (void) syslog(LOG_ERR, "%s", buf);
246 246 } else if (zlogp->logfile != NULL) {
247 247 (void) fprintf(zlogp->logfile, "%s\n", buf);
248 248 } else {
249 249 size_t buflen;
250 250 size_t copylen;
251 251
252 252 buflen = snprintf(zlogp->log, zlogp->loglen, "%s\n", buf);
253 253 copylen = MIN(buflen, zlogp->loglen);
254 254 zlogp->log += copylen;
255 255 zlogp->loglen -= copylen;
256 256 }
257 257 }
258 258
259 259 /*
260 260 * Emit a warning for any boot arguments which are unrecognized. Since
261 261 * Solaris boot arguments are getopt(3c) compatible (see kernel(1m)), we
262 262 * put the arguments into an argv style array, use getopt to process them,
263 263 * and put the resultant argument string back into outargs.
264 264 *
265 265 * During the filtering, we pull out any arguments which are truly "boot"
266 266 * arguments, leaving only those which are to be passed intact to the
267 267 * progenitor process. The one we support at the moment is -i, which
268 268 * indicates to the kernel which program should be launched as 'init'.
269 269 *
270 270 * A return of Z_INVAL indicates specifically that the arguments are
271 271 * not valid; this is a non-fatal error. Except for Z_OK, all other return
272 272 * values are treated as fatal.
273 273 */
274 274 static int
275 275 filter_bootargs(zlog_t *zlogp, const char *inargs, char *outargs,
276 276 char *init_file, char *badarg)
277 277 {
278 278 int argc = 0, argc_save;
279 279 int i;
280 280 int err;
281 281 char *arg, *lasts, **argv = NULL, **argv_save;
282 282 char zonecfg_args[BOOTARGS_MAX];
283 283 char scratchargs[BOOTARGS_MAX], *sargs;
284 284 char c;
285 285
286 286 bzero(outargs, BOOTARGS_MAX);
287 287 bzero(badarg, BOOTARGS_MAX);
288 288
289 289 /*
290 290 * If the user didn't specify transient boot arguments, check
291 291 * to see if there were any specified in the zone configuration,
292 292 * and use them if applicable.
293 293 */
294 294 if (inargs == NULL || inargs[0] == '\0') {
295 295 zone_dochandle_t handle;
296 296 if ((handle = zonecfg_init_handle()) == NULL) {
297 297 zerror(zlogp, B_TRUE,
298 298 "getting zone configuration handle");
299 299 return (Z_BAD_HANDLE);
300 300 }
301 301 err = zonecfg_get_snapshot_handle(zone_name, handle);
302 302 if (err != Z_OK) {
303 303 zerror(zlogp, B_FALSE,
304 304 "invalid configuration snapshot");
305 305 zonecfg_fini_handle(handle);
306 306 return (Z_BAD_HANDLE);
307 307 }
308 308
309 309 bzero(zonecfg_args, sizeof (zonecfg_args));
310 310 (void) zonecfg_get_bootargs(handle, zonecfg_args,
311 311 sizeof (zonecfg_args));
312 312 inargs = zonecfg_args;
313 313 zonecfg_fini_handle(handle);
314 314 }
315 315
316 316 if (strlen(inargs) >= BOOTARGS_MAX) {
317 317 zerror(zlogp, B_FALSE, "boot argument string too long");
318 318 return (Z_INVAL);
319 319 }
320 320
321 321 (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
322 322 sargs = scratchargs;
323 323 while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
324 324 sargs = NULL;
325 325 argc++;
326 326 }
327 327
328 328 if ((argv = calloc(argc + 1, sizeof (char *))) == NULL) {
329 329 zerror(zlogp, B_FALSE, "memory allocation failed");
330 330 return (Z_NOMEM);
331 331 }
332 332
333 333 argv_save = argv;
334 334 argc_save = argc;
335 335
336 336 (void) strlcpy(scratchargs, inargs, sizeof (scratchargs));
337 337 sargs = scratchargs;
338 338 i = 0;
339 339 while ((arg = strtok_r(sargs, " \t", &lasts)) != NULL) {
340 340 sargs = NULL;
341 341 if ((argv[i] = strdup(arg)) == NULL) {
342 342 err = Z_NOMEM;
343 343 zerror(zlogp, B_FALSE, "memory allocation failed");
344 344 goto done;
345 345 }
346 346 i++;
347 347 }
348 348
349 349 /*
350 350 * We preserve compatibility with the Solaris system boot behavior,
351 351 * which allows:
352 352 *
353 353 * # reboot kernel/unix -s -m verbose
354 354 *
355 355 * In this example, kernel/unix tells the booter what file to
356 356 * boot. We don't want reboot in a zone to be gratuitously different,
357 357 * so we silently ignore the boot file, if necessary.
358 358 */
359 359 if (argv[0] == NULL)
360 360 goto done;
361 361
362 362 assert(argv[0][0] != ' ');
363 363 assert(argv[0][0] != '\t');
364 364
365 365 if (argv[0][0] != '-' && argv[0][0] != '\0') {
366 366 argv = &argv[1];
367 367 argc--;
368 368 }
369 369
370 370 optind = 0;
371 371 opterr = 0;
372 372 err = Z_OK;
373 373 while ((c = getopt(argc, argv, "fi:m:s")) != -1) {
374 374 switch (c) {
375 375 case 'i':
376 376 /*
377 377 * -i is handled by the runtime and is not passed
378 378 * along to userland
379 379 */
380 380 (void) strlcpy(init_file, optarg, MAXPATHLEN);
381 381 break;
382 382 case 'f':
383 383 /* This has already been processed by zoneadm */
384 384 break;
385 385 case 'm':
386 386 case 's':
387 387 /* These pass through unmolested */
388 388 (void) snprintf(outargs, BOOTARGS_MAX,
389 389 "%s -%c %s ", outargs, c, optarg ? optarg : "");
390 390 break;
391 391 case '?':
392 392 /*
393 393 * We warn about unknown arguments but pass them
394 394 * along anyway-- if someone wants to develop their
395 395 * own init replacement, they can pass it whatever
396 396 * args they want.
397 397 */
398 398 err = Z_INVAL;
399 399 (void) snprintf(outargs, BOOTARGS_MAX,
400 400 "%s -%c", outargs, optopt);
401 401 (void) snprintf(badarg, BOOTARGS_MAX,
402 402 "%s -%c", badarg, optopt);
403 403 break;
404 404 }
405 405 }
406 406
407 407 /*
408 408 * For Solaris Zones we warn about and discard non-option arguments.
409 409 * Hence 'boot foo bar baz gub' --> 'boot'. However, to be similar
410 410 * to the kernel, we concat up all the other remaining boot args.
411 411 * and warn on them as a group.
412 412 */
413 413 if (optind < argc) {
414 414 err = Z_INVAL;
415 415 while (optind < argc) {
416 416 (void) snprintf(badarg, BOOTARGS_MAX, "%s%s%s",
417 417 badarg, strlen(badarg) > 0 ? " " : "",
418 418 argv[optind]);
419 419 optind++;
420 420 }
421 421 zerror(zlogp, B_FALSE, "WARNING: Unused or invalid boot "
422 422 "arguments `%s'.", badarg);
423 423 }
424 424
425 425 done:
426 426 for (i = 0; i < argc_save; i++) {
427 427 if (argv_save[i] != NULL)
428 428 free(argv_save[i]);
429 429 }
430 430 free(argv_save);
431 431 return (err);
432 432 }
433 433
434 434
435 435 static int
436 436 mkzonedir(zlog_t *zlogp)
437 437 {
438 438 struct stat st;
439 439 /*
440 440 * We must create and lock everyone but root out of ZONES_TMPDIR
441 441 * since anyone can open any UNIX domain socket, regardless of
442 442 * its file system permissions. Sigh...
443 443 */
444 444 if (mkdir(ZONES_TMPDIR, S_IRWXU) < 0 && errno != EEXIST) {
445 445 zerror(zlogp, B_TRUE, "could not mkdir '%s'", ZONES_TMPDIR);
446 446 return (-1);
447 447 }
448 448 /* paranoia */
449 449 if ((stat(ZONES_TMPDIR, &st) < 0) || !S_ISDIR(st.st_mode)) {
450 450 zerror(zlogp, B_TRUE, "'%s' is not a directory", ZONES_TMPDIR);
451 451 return (-1);
452 452 }
453 453 (void) chmod(ZONES_TMPDIR, S_IRWXU);
454 454 return (0);
455 455 }
456 456
457 457 /*
458 458 * Run the brand's pre-state change callback, if it exists.
459 459 */
460 460 static int
461 461 brand_prestatechg(zlog_t *zlogp, int state, int cmd)
462 462 {
463 463 char cmdbuf[2 * MAXPATHLEN];
464 464 const char *altroot;
465 465
466 466 if (pre_statechg_hook[0] == '\0')
467 467 return (0);
468 468
469 469 altroot = zonecfg_get_root();
470 470 if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", pre_statechg_hook,
471 471 state, cmd, altroot) > sizeof (cmdbuf))
472 472 return (-1);
473 473
474 474 if (do_subproc(zlogp, cmdbuf, NULL) != 0)
475 475 return (-1);
476 476
477 477 return (0);
478 478 }
479 479
480 480 /*
481 481 * Run the brand's post-state change callback, if it exists.
482 482 */
483 483 static int
484 484 brand_poststatechg(zlog_t *zlogp, int state, int cmd)
485 485 {
486 486 char cmdbuf[2 * MAXPATHLEN];
487 487 const char *altroot;
488 488
489 489 if (post_statechg_hook[0] == '\0')
490 490 return (0);
491 491
492 492 altroot = zonecfg_get_root();
493 493 if (snprintf(cmdbuf, sizeof (cmdbuf), "%s %d %d %s", post_statechg_hook,
494 494 state, cmd, altroot) > sizeof (cmdbuf))
495 495 return (-1);
496 496
497 497 if (do_subproc(zlogp, cmdbuf, NULL) != 0)
498 498 return (-1);
499 499
500 500 return (0);
501 501 }
502 502
503 503 /*
504 504 * Notify zonestatd of the new zone. If zonestatd is not running, this
505 505 * will do nothing.
506 506 */
507 507 static void
508 508 notify_zonestatd(zoneid_t zoneid)
509 509 {
510 510 int cmd[2];
511 511 int fd;
512 512 door_arg_t params;
513 513
514 514 fd = open(ZS_DOOR_PATH, O_RDONLY);
515 515 if (fd < 0)
516 516 return;
517 517
518 518 cmd[0] = ZSD_CMD_NEW_ZONE;
519 519 cmd[1] = zoneid;
520 520 params.data_ptr = (char *)&cmd;
521 521 params.data_size = sizeof (cmd);
522 522 params.desc_ptr = NULL;
523 523 params.desc_num = 0;
524 524 params.rbuf = NULL;
525 525 params.rsize = NULL;
526 526 (void) door_call(fd, ¶ms);
527 527 (void) close(fd);
528 528 }
529 529
530 530 /*
531 531 * Bring a zone up to the pre-boot "ready" stage. The mount_cmd argument is
532 532 * 'true' if this is being invoked as part of the processing for the "mount"
533 533 * subcommand.
534 534 */
535 535 static int
536 536 zone_ready(zlog_t *zlogp, zone_mnt_t mount_cmd, int zstate)
537 537 {
538 538 int err;
539 539
540 540 if (brand_prestatechg(zlogp, zstate, Z_READY) != 0)
541 541 return (-1);
542 542
543 543 if ((err = zonecfg_create_snapshot(zone_name)) != Z_OK) {
544 544 zerror(zlogp, B_FALSE, "unable to create snapshot: %s",
545 545 zonecfg_strerror(err));
546 546 goto bad;
547 547 }
548 548
549 549 if ((zone_id = vplat_create(zlogp, mount_cmd)) == -1) {
550 550 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
551 551 zerror(zlogp, B_FALSE, "destroying snapshot: %s",
552 552 zonecfg_strerror(err));
553 553 goto bad;
554 554 }
555 555 if (vplat_bringup(zlogp, mount_cmd, zone_id) != 0) {
556 556 bringup_failure_recovery = B_TRUE;
557 557 (void) vplat_teardown(NULL, (mount_cmd != Z_MNT_BOOT), B_FALSE);
558 558 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
559 559 zerror(zlogp, B_FALSE, "destroying snapshot: %s",
560 560 zonecfg_strerror(err));
561 561 goto bad;
562 562 }
563 563
564 564 if (brand_poststatechg(zlogp, zstate, Z_READY) != 0)
565 565 goto bad;
566 566
567 567 return (0);
568 568
569 569 bad:
570 570 /*
571 571 * If something goes wrong, we up the zones's state to the target
572 572 * state, READY, and then invoke the hook as if we're halting.
573 573 */
574 574 (void) brand_poststatechg(zlogp, ZONE_STATE_READY, Z_HALT);
575 575 return (-1);
576 576 }
577 577
578 578 int
579 579 init_template(void)
580 580 {
581 581 int fd;
582 582 int err = 0;
583 583
584 584 fd = open64(CTFS_ROOT "/process/template", O_RDWR);
585 585 if (fd == -1)
586 586 return (-1);
587 587
588 588 /*
589 589 * For now, zoneadmd doesn't do anything with the contract.
590 590 * Deliver no events, don't inherit, and allow it to be orphaned.
591 591 */
592 592 err |= ct_tmpl_set_critical(fd, 0);
593 593 err |= ct_tmpl_set_informative(fd, 0);
594 594 err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR);
595 595 err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT);
596 596 if (err || ct_tmpl_activate(fd)) {
597 597 (void) close(fd);
598 598 return (-1);
599 599 }
600 600
601 601 return (fd);
602 602 }
603 603
604 604 typedef struct fs_callback {
605 605 zlog_t *zlogp;
606 606 zoneid_t zoneid;
607 607 boolean_t mount_cmd;
608 608 } fs_callback_t;
609 609
610 610 static int
611 611 mount_early_fs(void *data, const char *spec, const char *dir,
612 612 const char *fstype, const char *opt)
613 613 {
614 614 zlog_t *zlogp = ((fs_callback_t *)data)->zlogp;
615 615 zoneid_t zoneid = ((fs_callback_t *)data)->zoneid;
616 616 boolean_t mount_cmd = ((fs_callback_t *)data)->mount_cmd;
617 617 char rootpath[MAXPATHLEN];
618 618 pid_t child;
619 619 int child_status;
620 620 int tmpl_fd;
621 621 int rv;
622 622 ctid_t ct;
623 623
624 624 /* determine the zone rootpath */
625 625 if (mount_cmd) {
626 626 char zonepath[MAXPATHLEN];
627 627 char luroot[MAXPATHLEN];
628 628
629 629 if (zone_get_zonepath(zone_name,
630 630 zonepath, sizeof (zonepath)) != Z_OK) {
631 631 zerror(zlogp, B_FALSE, "unable to determine zone path");
632 632 return (-1);
633 633 }
634 634
635 635 (void) snprintf(luroot, sizeof (luroot), "%s/lu", zonepath);
636 636 resolve_lofs(zlogp, luroot, sizeof (luroot));
637 637 (void) strlcpy(rootpath, luroot, sizeof (rootpath));
638 638 } else {
639 639 if (zone_get_rootpath(zone_name,
640 640 rootpath, sizeof (rootpath)) != Z_OK) {
641 641 zerror(zlogp, B_FALSE, "unable to determine zone root");
642 642 return (-1);
643 643 }
644 644 }
645 645
646 646 if ((rv = valid_mount_path(zlogp, rootpath, spec, dir, fstype)) < 0) {
647 647 zerror(zlogp, B_FALSE, "%s%s is not a valid mount point",
648 648 rootpath, dir);
649 649 return (-1);
650 650 } else if (rv > 0) {
651 651 /* The mount point path doesn't exist, create it now. */
652 652 if (make_one_dir(zlogp, rootpath, dir,
653 653 DEFAULT_DIR_MODE, DEFAULT_DIR_USER,
654 654 DEFAULT_DIR_GROUP) != 0) {
655 655 zerror(zlogp, B_FALSE, "failed to create mount point");
656 656 return (-1);
657 657 }
658 658
659 659 /*
660 660 * Now this might seem weird, but we need to invoke
661 661 * valid_mount_path() again. Why? Because it checks
662 662 * to make sure that the mount point path is canonical,
663 663 * which it can only do if the path exists, so now that
664 664 * we've created the path we have to verify it again.
665 665 */
666 666 if ((rv = valid_mount_path(zlogp, rootpath, spec, dir,
667 667 fstype)) < 0) {
668 668 zerror(zlogp, B_FALSE,
669 669 "%s%s is not a valid mount point", rootpath, dir);
670 670 return (-1);
671 671 }
672 672 }
673 673
674 674 if ((tmpl_fd = init_template()) == -1) {
675 675 zerror(zlogp, B_TRUE, "failed to create contract");
676 676 return (-1);
677 677 }
678 678
679 679 if ((child = fork()) == -1) {
680 680 (void) ct_tmpl_clear(tmpl_fd);
681 681 (void) close(tmpl_fd);
682 682 zerror(zlogp, B_TRUE, "failed to fork");
683 683 return (-1);
684 684
685 685 } else if (child == 0) { /* child */
686 686 char opt_buf[MAX_MNTOPT_STR];
687 687 int optlen = 0;
688 688 int mflag = MS_DATA;
689 689
690 690 (void) ct_tmpl_clear(tmpl_fd);
691 691 /*
692 692 * Even though there are no procs running in the zone, we
693 693 * do this for paranoia's sake.
694 694 */
695 695 (void) closefrom(0);
696 696
697 697 if (zone_enter(zoneid) == -1) {
698 698 _exit(errno);
699 699 }
700 700 if (opt != NULL) {
701 701 /*
702 702 * The mount() system call is incredibly annoying.
703 703 * If options are specified, we need to copy them
704 704 * into a temporary buffer since the mount() system
705 705 * call will overwrite the options string. It will
706 706 * also fail if the new option string it wants to
707 707 * write is bigger than the one we passed in, so
708 708 * you must pass in a buffer of the maximum possible
709 709 * option string length. sigh.
710 710 */
711 711 (void) strlcpy(opt_buf, opt, sizeof (opt_buf));
712 712 opt = opt_buf;
713 713 optlen = MAX_MNTOPT_STR;
714 714 mflag = MS_OPTIONSTR;
715 715 }
716 716 if (mount(spec, dir, mflag, fstype, NULL, 0, opt, optlen) != 0)
717 717 _exit(errno);
718 718 _exit(0);
719 719 }
720 720
721 721 /* parent */
722 722 if (contract_latest(&ct) == -1)
723 723 ct = -1;
724 724 (void) ct_tmpl_clear(tmpl_fd);
725 725 (void) close(tmpl_fd);
726 726 if (waitpid(child, &child_status, 0) != child) {
727 727 /* unexpected: we must have been signalled */
728 728 (void) contract_abandon_id(ct);
729 729 return (-1);
730 730 }
731 731 (void) contract_abandon_id(ct);
732 732 if (WEXITSTATUS(child_status) != 0) {
733 733 errno = WEXITSTATUS(child_status);
734 734 zerror(zlogp, B_TRUE, "mount of %s failed", dir);
735 735 return (-1);
736 736 }
737 737
738 738 return (0);
739 739 }
740 740
741 741 /*
742 742 * If retstr is not NULL, the output of the subproc is returned in the str,
743 743 * otherwise it is output using zerror(). Any memory allocated for retstr
744 744 * should be freed by the caller.
745 745 */
746 746 int
747 747 do_subproc(zlog_t *zlogp, char *cmdbuf, char **retstr)
748 748 {
749 749 char buf[1024]; /* arbitrary large amount */
750 750 char *inbuf;
751 751 FILE *file;
752 752 int status;
753 753 int rd_cnt;
754 754
755 755 if (retstr != NULL) {
756 756 if ((*retstr = malloc(1024)) == NULL) {
757 757 zerror(zlogp, B_FALSE, "out of memory");
758 758 return (-1);
759 759 }
760 760 inbuf = *retstr;
761 761 rd_cnt = 0;
762 762 } else {
763 763 inbuf = buf;
|
↓ open down ↓ |
763 lines elided |
↑ open up ↑ |
764 764 }
765 765
766 766 file = popen(cmdbuf, "r");
767 767 if (file == NULL) {
768 768 zerror(zlogp, B_TRUE, "could not launch: %s", cmdbuf);
769 769 return (-1);
770 770 }
771 771
772 772 while (fgets(inbuf, 1024, file) != NULL) {
773 773 if (retstr == NULL) {
774 - if (zlogp != &logsys)
774 + if (zlogp != &logsys) {
775 + int last = strlen(inbuf) - 1;
776 +
777 + if (inbuf[last] == '\n')
778 + inbuf[last] = '\0';
775 779 zerror(zlogp, B_FALSE, "%s", inbuf);
780 + }
776 781 } else {
777 782 char *p;
778 783
779 784 rd_cnt += 1024 - 1;
780 785 if ((p = realloc(*retstr, rd_cnt + 1024)) == NULL) {
781 786 zerror(zlogp, B_FALSE, "out of memory");
782 787 (void) pclose(file);
783 788 return (-1);
784 789 }
785 790
786 791 *retstr = p;
787 792 inbuf = *retstr + rd_cnt;
788 793 }
789 794 }
790 795 status = pclose(file);
791 796
792 797 if (WIFSIGNALED(status)) {
793 798 zerror(zlogp, B_FALSE, "%s unexpectedly terminated due to "
794 799 "signal %d", cmdbuf, WTERMSIG(status));
795 800 return (-1);
796 801 }
797 802 assert(WIFEXITED(status));
798 803 if (WEXITSTATUS(status) == ZEXIT_EXEC) {
799 804 zerror(zlogp, B_FALSE, "failed to exec %s", cmdbuf);
800 805 return (-1);
801 806 }
802 807 return (WEXITSTATUS(status));
803 808 }
804 809
805 810 static int
806 811 zone_bootup(zlog_t *zlogp, const char *bootargs, int zstate)
807 812 {
808 813 zoneid_t zoneid;
809 814 struct stat st;
810 815 char zpath[MAXPATHLEN], initpath[MAXPATHLEN], init_file[MAXPATHLEN];
811 816 char nbootargs[BOOTARGS_MAX];
812 817 char cmdbuf[MAXPATHLEN];
813 818 fs_callback_t cb;
814 819 brand_handle_t bh;
815 820 zone_iptype_t iptype;
816 821 boolean_t links_loaded = B_FALSE;
817 822 dladm_status_t status;
818 823 char errmsg[DLADM_STRSIZE];
819 824 int err;
820 825 boolean_t restart_init;
821 826
822 827 if (brand_prestatechg(zlogp, zstate, Z_BOOT) != 0)
823 828 return (-1);
824 829
825 830 if ((zoneid = getzoneidbyname(zone_name)) == -1) {
826 831 zerror(zlogp, B_TRUE, "unable to get zoneid");
827 832 goto bad;
828 833 }
829 834
830 835 cb.zlogp = zlogp;
831 836 cb.zoneid = zoneid;
832 837 cb.mount_cmd = B_FALSE;
833 838
834 839 /* Get a handle to the brand info for this zone */
835 840 if ((bh = brand_open(brand_name)) == NULL) {
836 841 zerror(zlogp, B_FALSE, "unable to determine zone brand");
837 842 goto bad;
838 843 }
839 844
840 845 /*
841 846 * Get the list of filesystems to mount from the brand
842 847 * configuration. These mounts are done via a thread that will
843 848 * enter the zone, so they are done from within the context of the
844 849 * zone.
845 850 */
846 851 if (brand_platform_iter_mounts(bh, mount_early_fs, &cb) != 0) {
847 852 zerror(zlogp, B_FALSE, "unable to mount filesystems");
848 853 brand_close(bh);
849 854 goto bad;
850 855 }
851 856
852 857 /*
853 858 * Get the brand's boot callback if it exists.
854 859 */
855 860 if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
856 861 zerror(zlogp, B_FALSE, "unable to determine zone path");
857 862 brand_close(bh);
858 863 goto bad;
859 864 }
860 865 (void) strcpy(cmdbuf, EXEC_PREFIX);
861 866 if (brand_get_boot(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
862 867 sizeof (cmdbuf) - EXEC_LEN) != 0) {
863 868 zerror(zlogp, B_FALSE,
864 869 "unable to determine branded zone's boot callback");
865 870 brand_close(bh);
866 871 goto bad;
867 872 }
868 873
869 874 /* Get the path for this zone's init(1M) (or equivalent) process. */
870 875 if (brand_get_initname(bh, init_file, MAXPATHLEN) != 0) {
871 876 zerror(zlogp, B_FALSE,
872 877 "unable to determine zone's init(1M) location");
873 878 brand_close(bh);
874 879 goto bad;
875 880 }
876 881
877 882 /* See if this zone's brand should restart init if it dies. */
878 883 restart_init = brand_restartinit(bh);
879 884
880 885 brand_close(bh);
881 886
882 887 err = filter_bootargs(zlogp, bootargs, nbootargs, init_file,
883 888 bad_boot_arg);
884 889 if (err == Z_INVAL)
885 890 eventstream_write(Z_EVT_ZONE_BADARGS);
886 891 else if (err != Z_OK)
887 892 goto bad;
888 893
889 894 assert(init_file[0] != '\0');
890 895
891 896 /* Try to anticipate possible problems: Make sure init is executable. */
892 897 if (zone_get_rootpath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
893 898 zerror(zlogp, B_FALSE, "unable to determine zone root");
894 899 goto bad;
895 900 }
896 901
897 902 (void) snprintf(initpath, sizeof (initpath), "%s%s", zpath, init_file);
898 903
899 904 if (stat(initpath, &st) == -1) {
900 905 zerror(zlogp, B_TRUE, "could not stat %s", initpath);
901 906 goto bad;
902 907 }
903 908
904 909 if ((st.st_mode & S_IXUSR) == 0) {
905 910 zerror(zlogp, B_FALSE, "%s is not executable", initpath);
906 911 goto bad;
907 912 }
908 913
909 914 /*
910 915 * Exclusive stack zones interact with the dlmgmtd running in the
911 916 * global zone. dladm_zone_boot() tells dlmgmtd that this zone is
912 917 * booting, and loads its datalinks from the zone's datalink
913 918 * configuration file.
914 919 */
915 920 if (vplat_get_iptype(zlogp, &iptype) == 0 && iptype == ZS_EXCLUSIVE) {
916 921 status = dladm_zone_boot(dld_handle, zoneid);
917 922 if (status != DLADM_STATUS_OK) {
918 923 zerror(zlogp, B_FALSE, "unable to load zone datalinks: "
919 924 " %s", dladm_status2str(status, errmsg));
920 925 goto bad;
921 926 }
922 927 links_loaded = B_TRUE;
923 928 }
924 929
925 930 /*
926 931 * If there is a brand 'boot' callback, execute it now to give the
927 932 * brand one last chance to do any additional setup before the zone
928 933 * is booted.
929 934 */
930 935 if ((strlen(cmdbuf) > EXEC_LEN) &&
931 936 (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
932 937 zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
933 938 goto bad;
934 939 }
935 940
936 941 if (zone_setattr(zoneid, ZONE_ATTR_INITNAME, init_file, 0) == -1) {
937 942 zerror(zlogp, B_TRUE, "could not set zone boot file");
938 943 goto bad;
939 944 }
940 945
941 946 if (zone_setattr(zoneid, ZONE_ATTR_BOOTARGS, nbootargs, 0) == -1) {
942 947 zerror(zlogp, B_TRUE, "could not set zone boot arguments");
943 948 goto bad;
944 949 }
945 950
946 951 if (!restart_init && zone_setattr(zoneid, ZONE_ATTR_INITNORESTART,
947 952 NULL, 0) == -1) {
948 953 zerror(zlogp, B_TRUE, "could not set zone init-no-restart");
949 954 goto bad;
950 955 }
951 956
952 957 /*
953 958 * Inform zonestatd of a new zone so that it can install a door for
954 959 * the zone to contact it.
955 960 */
956 961 notify_zonestatd(zone_id);
957 962
958 963 if (zone_boot(zoneid) == -1) {
959 964 zerror(zlogp, B_TRUE, "unable to boot zone");
960 965 goto bad;
961 966 }
962 967
963 968 if (brand_poststatechg(zlogp, zstate, Z_BOOT) != 0)
964 969 goto bad;
965 970
966 971 return (0);
967 972
968 973 bad:
969 974 /*
970 975 * If something goes wrong, we up the zones's state to the target
971 976 * state, RUNNING, and then invoke the hook as if we're halting.
972 977 */
973 978 (void) brand_poststatechg(zlogp, ZONE_STATE_RUNNING, Z_HALT);
974 979 if (links_loaded)
975 980 (void) dladm_zone_halt(dld_handle, zoneid);
976 981 return (-1);
977 982 }
978 983
979 984 static int
980 985 zone_halt(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting, int zstate)
981 986 {
982 987 int err;
983 988
984 989 if (brand_prestatechg(zlogp, zstate, Z_HALT) != 0)
985 990 return (-1);
986 991
987 992 if (vplat_teardown(zlogp, unmount_cmd, rebooting) != 0) {
988 993 if (!bringup_failure_recovery)
989 994 zerror(zlogp, B_FALSE, "unable to destroy zone");
990 995 return (-1);
991 996 }
992 997
993 998 if ((err = zonecfg_destroy_snapshot(zone_name)) != Z_OK)
994 999 zerror(zlogp, B_FALSE, "destroying snapshot: %s",
995 1000 zonecfg_strerror(err));
996 1001
997 1002 if (brand_poststatechg(zlogp, zstate, Z_HALT) != 0)
998 1003 return (-1);
999 1004
1000 1005 return (0);
1001 1006 }
1002 1007
1003 1008 static int
1004 1009 zone_graceful_shutdown(zlog_t *zlogp)
1005 1010 {
1006 1011 zoneid_t zoneid;
1007 1012 pid_t child;
1008 1013 char cmdbuf[MAXPATHLEN];
1009 1014 brand_handle_t bh = NULL;
1010 1015 char zpath[MAXPATHLEN];
1011 1016 ctid_t ct;
1012 1017 int tmpl_fd;
1013 1018 int child_status;
1014 1019
1015 1020 if (shutdown_in_progress) {
1016 1021 zerror(zlogp, B_FALSE, "shutdown already in progress");
1017 1022 return (-1);
1018 1023 }
1019 1024
1020 1025 if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1021 1026 zerror(zlogp, B_TRUE, "unable to get zoneid");
1022 1027 return (-1);
1023 1028 }
1024 1029
1025 1030 /* Get a handle to the brand info for this zone */
1026 1031 if ((bh = brand_open(brand_name)) == NULL) {
1027 1032 zerror(zlogp, B_FALSE, "unable to determine zone brand");
1028 1033 return (-1);
1029 1034 }
1030 1035
1031 1036 if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
1032 1037 zerror(zlogp, B_FALSE, "unable to determine zone path");
1033 1038 brand_close(bh);
1034 1039 return (-1);
1035 1040 }
1036 1041
1037 1042 /*
1038 1043 * If there is a brand 'shutdown' callback, execute it now to give the
1039 1044 * brand a chance to cleanup any custom configuration.
1040 1045 */
1041 1046 (void) strcpy(cmdbuf, EXEC_PREFIX);
1042 1047 if (brand_get_shutdown(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
1043 1048 sizeof (cmdbuf) - EXEC_LEN) != 0 || strlen(cmdbuf) <= EXEC_LEN) {
1044 1049 (void) strcat(cmdbuf, SHUTDOWN_DEFAULT);
1045 1050 }
1046 1051 brand_close(bh);
1047 1052
1048 1053 if ((tmpl_fd = init_template()) == -1) {
1049 1054 zerror(zlogp, B_TRUE, "failed to create contract");
1050 1055 return (-1);
1051 1056 }
1052 1057
1053 1058 if ((child = fork()) == -1) {
1054 1059 (void) ct_tmpl_clear(tmpl_fd);
1055 1060 (void) close(tmpl_fd);
1056 1061 zerror(zlogp, B_TRUE, "failed to fork");
1057 1062 return (-1);
1058 1063 } else if (child == 0) {
1059 1064 (void) ct_tmpl_clear(tmpl_fd);
1060 1065 if (zone_enter(zoneid) == -1) {
1061 1066 _exit(errno);
1062 1067 }
1063 1068 _exit(execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL));
1064 1069 }
1065 1070
1066 1071 if (contract_latest(&ct) == -1)
1067 1072 ct = -1;
1068 1073 (void) ct_tmpl_clear(tmpl_fd);
1069 1074 (void) close(tmpl_fd);
1070 1075
1071 1076 if (waitpid(child, &child_status, 0) != child) {
1072 1077 /* unexpected: we must have been signalled */
1073 1078 (void) contract_abandon_id(ct);
1074 1079 return (-1);
1075 1080 }
1076 1081
1077 1082 (void) contract_abandon_id(ct);
1078 1083 if (WEXITSTATUS(child_status) != 0) {
1079 1084 errno = WEXITSTATUS(child_status);
1080 1085 zerror(zlogp, B_FALSE, "unable to shutdown zone");
1081 1086 return (-1);
1082 1087 }
1083 1088
1084 1089 shutdown_in_progress = B_TRUE;
1085 1090
1086 1091 return (0);
1087 1092 }
1088 1093
1089 1094 static int
1090 1095 zone_wait_shutdown(zlog_t *zlogp)
1091 1096 {
1092 1097 zone_state_t zstate;
1093 1098 uint64_t *tm = NULL;
1094 1099 scf_simple_prop_t *prop = NULL;
1095 1100 int timeout;
1096 1101 int tries;
1097 1102 int rc = -1;
1098 1103
1099 1104 /* Get default stop timeout from SMF framework */
1100 1105 timeout = SHUTDOWN_WAIT;
1101 1106 if ((prop = scf_simple_prop_get(NULL, SHUTDOWN_FMRI, "stop",
1102 1107 SCF_PROPERTY_TIMEOUT)) != NULL) {
1103 1108 if ((tm = scf_simple_prop_next_count(prop)) != NULL) {
1104 1109 if (tm != 0)
1105 1110 timeout = *tm;
1106 1111 }
1107 1112 scf_simple_prop_free(prop);
1108 1113 }
1109 1114
1110 1115 /* allow time for zone to shutdown cleanly */
1111 1116 for (tries = 0; tries < timeout; tries ++) {
1112 1117 (void) sleep(1);
1113 1118 if (zone_get_state(zone_name, &zstate) == Z_OK &&
1114 1119 zstate == ZONE_STATE_INSTALLED) {
1115 1120 rc = 0;
1116 1121 break;
1117 1122 }
1118 1123 }
1119 1124
1120 1125 if (rc != 0)
1121 1126 zerror(zlogp, B_FALSE, "unable to shutdown zone");
1122 1127
1123 1128 shutdown_in_progress = B_FALSE;
1124 1129
1125 1130 return (rc);
1126 1131 }
1127 1132
1128 1133
1129 1134
1130 1135 /*
1131 1136 * Generate AUE_zone_state for a command that boots a zone.
1132 1137 */
1133 1138 static void
1134 1139 audit_put_record(zlog_t *zlogp, ucred_t *uc, int return_val,
1135 1140 char *new_state)
1136 1141 {
1137 1142 adt_session_data_t *ah;
1138 1143 adt_event_data_t *event;
1139 1144 int pass_fail, fail_reason;
1140 1145
1141 1146 if (!adt_audit_enabled())
1142 1147 return;
1143 1148
1144 1149 if (return_val == 0) {
1145 1150 pass_fail = ADT_SUCCESS;
1146 1151 fail_reason = ADT_SUCCESS;
1147 1152 } else {
1148 1153 pass_fail = ADT_FAILURE;
1149 1154 fail_reason = ADT_FAIL_VALUE_PROGRAM;
1150 1155 }
1151 1156
1152 1157 if (adt_start_session(&ah, NULL, 0)) {
1153 1158 zerror(zlogp, B_TRUE, gettext("audit failure."));
1154 1159 return;
1155 1160 }
1156 1161 if (adt_set_from_ucred(ah, uc, ADT_NEW)) {
1157 1162 zerror(zlogp, B_TRUE, gettext("audit failure."));
1158 1163 (void) adt_end_session(ah);
1159 1164 return;
1160 1165 }
1161 1166
1162 1167 event = adt_alloc_event(ah, ADT_zone_state);
1163 1168 if (event == NULL) {
1164 1169 zerror(zlogp, B_TRUE, gettext("audit failure."));
1165 1170 (void) adt_end_session(ah);
1166 1171 return;
1167 1172 }
1168 1173 event->adt_zone_state.zonename = zone_name;
1169 1174 event->adt_zone_state.new_state = new_state;
1170 1175
1171 1176 if (adt_put_event(event, pass_fail, fail_reason))
1172 1177 zerror(zlogp, B_TRUE, gettext("audit failure."));
1173 1178
1174 1179 adt_free_event(event);
1175 1180
1176 1181 (void) adt_end_session(ah);
1177 1182 }
1178 1183
1179 1184 /*
1180 1185 * The main routine for the door server that deals with zone state transitions.
1181 1186 */
1182 1187 /* ARGSUSED */
1183 1188 static void
1184 1189 server(void *cookie, char *args, size_t alen, door_desc_t *dp,
1185 1190 uint_t n_desc)
1186 1191 {
1187 1192 ucred_t *uc = NULL;
1188 1193 const priv_set_t *eset;
1189 1194
1190 1195 zone_state_t zstate;
1191 1196 zone_cmd_t cmd;
1192 1197 zone_cmd_arg_t *zargp;
1193 1198
1194 1199 boolean_t kernelcall;
1195 1200
1196 1201 int rval = -1;
1197 1202 uint64_t uniqid;
1198 1203 zoneid_t zoneid = -1;
1199 1204 zlog_t zlog;
1200 1205 zlog_t *zlogp;
1201 1206 zone_cmd_rval_t *rvalp;
1202 1207 size_t rlen = getpagesize(); /* conservative */
1203 1208 fs_callback_t cb;
1204 1209 brand_handle_t bh;
1205 1210 boolean_t wait_shut = B_FALSE;
1206 1211
1207 1212 /* LINTED E_BAD_PTR_CAST_ALIGN */
1208 1213 zargp = (zone_cmd_arg_t *)args;
1209 1214
1210 1215 /*
1211 1216 * When we get the door unref message, we've fdetach'd the door, and
1212 1217 * it is time for us to shut down zoneadmd.
1213 1218 */
1214 1219 if (zargp == DOOR_UNREF_DATA) {
1215 1220 /*
1216 1221 * See comment at end of main() for info on the last rites.
1217 1222 */
1218 1223 exit(0);
1219 1224 }
1220 1225
1221 1226 if (zargp == NULL) {
1222 1227 (void) door_return(NULL, 0, 0, 0);
1223 1228 }
1224 1229
1225 1230 rvalp = alloca(rlen);
1226 1231 bzero(rvalp, rlen);
1227 1232 zlog.logfile = NULL;
1228 1233 zlog.buflen = zlog.loglen = rlen - sizeof (zone_cmd_rval_t) + 1;
1229 1234 zlog.buf = rvalp->errbuf;
1230 1235 zlog.log = zlog.buf;
1231 1236 /* defer initialization of zlog.locale until after credential check */
1232 1237 zlogp = &zlog;
1233 1238
1234 1239 if (alen != sizeof (zone_cmd_arg_t)) {
1235 1240 /*
1236 1241 * This really shouldn't be happening.
1237 1242 */
1238 1243 zerror(&logsys, B_FALSE, "argument size (%d bytes) "
1239 1244 "unexpected (expected %d bytes)", alen,
1240 1245 sizeof (zone_cmd_arg_t));
1241 1246 goto out;
1242 1247 }
1243 1248 cmd = zargp->cmd;
1244 1249
1245 1250 if (door_ucred(&uc) != 0) {
1246 1251 zerror(&logsys, B_TRUE, "door_ucred");
1247 1252 goto out;
1248 1253 }
1249 1254 eset = ucred_getprivset(uc, PRIV_EFFECTIVE);
1250 1255 if (ucred_getzoneid(uc) != GLOBAL_ZONEID ||
1251 1256 (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
1252 1257 ucred_geteuid(uc) != 0)) {
1253 1258 zerror(&logsys, B_FALSE, "insufficient privileges");
1254 1259 goto out;
1255 1260 }
1256 1261
1257 1262 kernelcall = ucred_getpid(uc) == 0;
1258 1263
1259 1264 /*
1260 1265 * This is safe because we only use a zlog_t throughout the
1261 1266 * duration of a door call; i.e., by the time the pointer
1262 1267 * might become invalid, the door call would be over.
1263 1268 */
1264 1269 zlog.locale = kernelcall ? DEFAULT_LOCALE : zargp->locale;
1265 1270
1266 1271 (void) mutex_lock(&lock);
1267 1272
1268 1273 /*
1269 1274 * Once we start to really die off, we don't want more connections.
1270 1275 */
1271 1276 if (in_death_throes) {
1272 1277 (void) mutex_unlock(&lock);
1273 1278 ucred_free(uc);
1274 1279 (void) door_return(NULL, 0, 0, 0);
1275 1280 thr_exit(NULL);
1276 1281 }
1277 1282
1278 1283 /*
1279 1284 * Check for validity of command.
1280 1285 */
1281 1286 if (cmd != Z_READY && cmd != Z_BOOT && cmd != Z_FORCEBOOT &&
1282 1287 cmd != Z_REBOOT && cmd != Z_SHUTDOWN && cmd != Z_HALT &&
1283 1288 cmd != Z_NOTE_UNINSTALLING && cmd != Z_MOUNT &&
1284 1289 cmd != Z_FORCEMOUNT && cmd != Z_UNMOUNT) {
1285 1290 zerror(&logsys, B_FALSE, "invalid command %d", (int)cmd);
1286 1291 goto out;
1287 1292 }
1288 1293
1289 1294 if (kernelcall && (cmd != Z_HALT && cmd != Z_REBOOT)) {
1290 1295 /*
1291 1296 * Can't happen
1292 1297 */
1293 1298 zerror(&logsys, B_FALSE, "received unexpected kernel upcall %d",
1294 1299 cmd);
1295 1300 goto out;
1296 1301 }
1297 1302 /*
1298 1303 * We ignore the possibility of someone calling zone_create(2)
1299 1304 * explicitly; all requests must come through zoneadmd.
1300 1305 */
1301 1306 if (zone_get_state(zone_name, &zstate) != Z_OK) {
1302 1307 /*
1303 1308 * Something terribly wrong happened
1304 1309 */
1305 1310 zerror(&logsys, B_FALSE, "unable to determine state of zone");
1306 1311 goto out;
1307 1312 }
1308 1313
1309 1314 if (kernelcall) {
1310 1315 /*
1311 1316 * Kernel-initiated requests may lose their validity if the
1312 1317 * zone_t the kernel was referring to has gone away.
1313 1318 */
1314 1319 if ((zoneid = getzoneidbyname(zone_name)) == -1 ||
1315 1320 zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1316 1321 sizeof (uniqid)) == -1 || uniqid != zargp->uniqid) {
1317 1322 /*
1318 1323 * We're not talking about the same zone. The request
1319 1324 * must have arrived too late. Return error.
1320 1325 */
1321 1326 rval = -1;
1322 1327 goto out;
1323 1328 }
1324 1329 zlogp = &logsys; /* Log errors to syslog */
1325 1330 }
1326 1331
1327 1332 /*
1328 1333 * If we are being asked to forcibly mount or boot a zone, we
1329 1334 * pretend that an INCOMPLETE zone is actually INSTALLED.
1330 1335 */
1331 1336 if (zstate == ZONE_STATE_INCOMPLETE &&
1332 1337 (cmd == Z_FORCEBOOT || cmd == Z_FORCEMOUNT))
1333 1338 zstate = ZONE_STATE_INSTALLED;
1334 1339
1335 1340 switch (zstate) {
1336 1341 case ZONE_STATE_CONFIGURED:
1337 1342 case ZONE_STATE_INCOMPLETE:
1338 1343 /*
1339 1344 * Not our area of expertise; we just print a nice message
1340 1345 * and die off.
1341 1346 */
1342 1347 zerror(zlogp, B_FALSE,
1343 1348 "%s operation is invalid for zones in state '%s'",
1344 1349 z_cmd_name(cmd), zone_state_str(zstate));
1345 1350 break;
1346 1351
1347 1352 case ZONE_STATE_INSTALLED:
1348 1353 switch (cmd) {
1349 1354 case Z_READY:
1350 1355 rval = zone_ready(zlogp, Z_MNT_BOOT, zstate);
1351 1356 if (rval == 0)
1352 1357 eventstream_write(Z_EVT_ZONE_READIED);
1353 1358 break;
1354 1359 case Z_BOOT:
1355 1360 case Z_FORCEBOOT:
1356 1361 eventstream_write(Z_EVT_ZONE_BOOTING);
1357 1362 if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1358 1363 == 0) {
1359 1364 rval = zone_bootup(zlogp, zargp->bootbuf,
1360 1365 zstate);
1361 1366 }
1362 1367 audit_put_record(zlogp, uc, rval, "boot");
1363 1368 if (rval != 0) {
1364 1369 bringup_failure_recovery = B_TRUE;
1365 1370 (void) zone_halt(zlogp, B_FALSE, B_FALSE,
1366 1371 zstate);
1367 1372 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1368 1373 }
1369 1374 break;
1370 1375 case Z_SHUTDOWN:
1371 1376 case Z_HALT:
1372 1377 if (kernelcall) /* Invalid; can't happen */
1373 1378 abort();
1374 1379 /*
1375 1380 * We could have two clients racing to halt this
1376 1381 * zone; the second client loses, but his request
1377 1382 * doesn't fail, since the zone is now in the desired
1378 1383 * state.
1379 1384 */
1380 1385 zerror(zlogp, B_FALSE, "zone is already halted");
1381 1386 rval = 0;
1382 1387 break;
1383 1388 case Z_REBOOT:
1384 1389 if (kernelcall) /* Invalid; can't happen */
1385 1390 abort();
1386 1391 zerror(zlogp, B_FALSE, "%s operation is invalid "
1387 1392 "for zones in state '%s'", z_cmd_name(cmd),
1388 1393 zone_state_str(zstate));
1389 1394 rval = -1;
1390 1395 break;
1391 1396 case Z_NOTE_UNINSTALLING:
1392 1397 if (kernelcall) /* Invalid; can't happen */
1393 1398 abort();
1394 1399 /*
1395 1400 * Tell the console to print out a message about this.
1396 1401 * Once it does, we will be in_death_throes.
1397 1402 */
1398 1403 eventstream_write(Z_EVT_ZONE_UNINSTALLING);
1399 1404 break;
1400 1405 case Z_MOUNT:
1401 1406 case Z_FORCEMOUNT:
1402 1407 if (kernelcall) /* Invalid; can't happen */
1403 1408 abort();
1404 1409 if (!zone_isnative && !zone_iscluster &&
1405 1410 !zone_islabeled) {
1406 1411 /*
1407 1412 * -U mounts the zone without lofs mounting
1408 1413 * zone file systems back into the scratch
1409 1414 * zone. This is required when mounting
1410 1415 * non-native branded zones.
1411 1416 */
1412 1417 (void) strlcpy(zargp->bootbuf, "-U",
1413 1418 BOOTARGS_MAX);
1414 1419 }
1415 1420
1416 1421 rval = zone_ready(zlogp,
1417 1422 strcmp(zargp->bootbuf, "-U") == 0 ?
1418 1423 Z_MNT_UPDATE : Z_MNT_SCRATCH, zstate);
1419 1424 if (rval != 0)
1420 1425 break;
1421 1426
1422 1427 eventstream_write(Z_EVT_ZONE_READIED);
1423 1428
1424 1429 /*
1425 1430 * Get a handle to the default brand info.
1426 1431 * We must always use the default brand file system
1427 1432 * list when mounting the zone.
1428 1433 */
1429 1434 if ((bh = brand_open(default_brand)) == NULL) {
1430 1435 rval = -1;
1431 1436 break;
1432 1437 }
1433 1438
1434 1439 /*
1435 1440 * Get the list of filesystems to mount from
1436 1441 * the brand configuration. These mounts are done
1437 1442 * via a thread that will enter the zone, so they
1438 1443 * are done from within the context of the zone.
1439 1444 */
1440 1445 cb.zlogp = zlogp;
1441 1446 cb.zoneid = zone_id;
1442 1447 cb.mount_cmd = B_TRUE;
1443 1448 rval = brand_platform_iter_mounts(bh,
1444 1449 mount_early_fs, &cb);
1445 1450
1446 1451 brand_close(bh);
1447 1452
1448 1453 /*
1449 1454 * Ordinarily, /dev/fd would be mounted inside the zone
1450 1455 * by svc:/system/filesystem/usr:default, but since
1451 1456 * we're not booting the zone, we need to do this
1452 1457 * manually.
1453 1458 */
1454 1459 if (rval == 0)
1455 1460 rval = mount_early_fs(&cb,
1456 1461 "fd", "/dev/fd", "fd", NULL);
1457 1462 break;
1458 1463 case Z_UNMOUNT:
1459 1464 if (kernelcall) /* Invalid; can't happen */
1460 1465 abort();
1461 1466 zerror(zlogp, B_FALSE, "zone is already unmounted");
1462 1467 rval = 0;
1463 1468 break;
1464 1469 }
1465 1470 break;
1466 1471
1467 1472 case ZONE_STATE_READY:
1468 1473 switch (cmd) {
1469 1474 case Z_READY:
|
↓ open down ↓ |
684 lines elided |
↑ open up ↑ |
1470 1475 /*
1471 1476 * We could have two clients racing to ready this
1472 1477 * zone; the second client loses, but his request
1473 1478 * doesn't fail, since the zone is now in the desired
1474 1479 * state.
1475 1480 */
1476 1481 zerror(zlogp, B_FALSE, "zone is already ready");
1477 1482 rval = 0;
1478 1483 break;
1479 1484 case Z_BOOT:
1485 + case Z_FORCEBOOT:
1480 1486 (void) strlcpy(boot_args, zargp->bootbuf,
1481 1487 sizeof (boot_args));
1482 1488 eventstream_write(Z_EVT_ZONE_BOOTING);
1483 1489 rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1484 1490 audit_put_record(zlogp, uc, rval, "boot");
1485 1491 if (rval != 0) {
1486 1492 bringup_failure_recovery = B_TRUE;
1487 1493 (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1488 1494 zstate);
1489 1495 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1490 1496 }
1491 1497 boot_args[0] = '\0';
1492 1498 break;
1493 1499 case Z_HALT:
1494 1500 if (kernelcall) /* Invalid; can't happen */
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1495 1501 abort();
1496 1502 if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1497 1503 != 0)
1498 1504 break;
1499 1505 eventstream_write(Z_EVT_ZONE_HALTED);
1500 1506 break;
1501 1507 case Z_SHUTDOWN:
1502 1508 case Z_REBOOT:
1503 1509 case Z_NOTE_UNINSTALLING:
1504 1510 case Z_MOUNT:
1511 + case Z_FORCEMOUNT:
1505 1512 case Z_UNMOUNT:
1506 1513 if (kernelcall) /* Invalid; can't happen */
1507 1514 abort();
1508 1515 zerror(zlogp, B_FALSE, "%s operation is invalid "
1509 1516 "for zones in state '%s'", z_cmd_name(cmd),
1510 1517 zone_state_str(zstate));
1511 1518 rval = -1;
1512 1519 break;
1513 1520 }
1514 1521 break;
1515 1522
1516 1523 case ZONE_STATE_MOUNTED:
1517 1524 switch (cmd) {
1518 1525 case Z_UNMOUNT:
1519 1526 if (kernelcall) /* Invalid; can't happen */
1520 1527 abort();
1521 1528 rval = zone_halt(zlogp, B_TRUE, B_FALSE, zstate);
1522 1529 if (rval == 0) {
1523 1530 eventstream_write(Z_EVT_ZONE_HALTED);
1524 1531 (void) sema_post(&scratch_sem);
1525 1532 }
1526 1533 break;
1527 1534 default:
1528 1535 if (kernelcall) /* Invalid; can't happen */
1529 1536 abort();
1530 1537 zerror(zlogp, B_FALSE, "%s operation is invalid "
1531 1538 "for zones in state '%s'", z_cmd_name(cmd),
1532 1539 zone_state_str(zstate));
1533 1540 rval = -1;
1534 1541 break;
1535 1542 }
1536 1543 break;
1537 1544
1538 1545 case ZONE_STATE_RUNNING:
1539 1546 case ZONE_STATE_SHUTTING_DOWN:
1540 1547 case ZONE_STATE_DOWN:
1541 1548 switch (cmd) {
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
1542 1549 case Z_READY:
1543 1550 if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1544 1551 != 0)
1545 1552 break;
1546 1553 if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate)) == 0)
1547 1554 eventstream_write(Z_EVT_ZONE_READIED);
1548 1555 else
1549 1556 eventstream_write(Z_EVT_ZONE_HALTED);
1550 1557 break;
1551 1558 case Z_BOOT:
1559 + case Z_FORCEBOOT:
1552 1560 /*
1553 1561 * We could have two clients racing to boot this
1554 1562 * zone; the second client loses, but his request
1555 1563 * doesn't fail, since the zone is now in the desired
1556 1564 * state.
1557 1565 */
1558 1566 zerror(zlogp, B_FALSE, "zone is already booted");
1559 1567 rval = 0;
1560 1568 break;
1561 1569 case Z_HALT:
1562 1570 if ((rval = zone_halt(zlogp, B_FALSE, B_FALSE, zstate))
1563 1571 != 0)
1564 1572 break;
1565 1573 eventstream_write(Z_EVT_ZONE_HALTED);
1566 1574 break;
1567 1575 case Z_REBOOT:
1568 1576 (void) strlcpy(boot_args, zargp->bootbuf,
1569 1577 sizeof (boot_args));
1570 1578 eventstream_write(Z_EVT_ZONE_REBOOTING);
1571 1579 if ((rval = zone_halt(zlogp, B_FALSE, B_TRUE, zstate))
1572 1580 != 0) {
1573 1581 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1574 1582 boot_args[0] = '\0';
1575 1583 break;
1576 1584 }
1577 1585 if ((rval = zone_ready(zlogp, Z_MNT_BOOT, zstate))
1578 1586 != 0) {
1579 1587 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
1580 1588 boot_args[0] = '\0';
1581 1589 break;
1582 1590 }
1583 1591 rval = zone_bootup(zlogp, zargp->bootbuf, zstate);
1584 1592 audit_put_record(zlogp, uc, rval, "reboot");
1585 1593 if (rval != 0) {
1586 1594 (void) zone_halt(zlogp, B_FALSE, B_TRUE,
1587 1595 zstate);
1588 1596 eventstream_write(Z_EVT_ZONE_BOOTFAILED);
|
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
1589 1597 }
1590 1598 boot_args[0] = '\0';
1591 1599 break;
1592 1600 case Z_SHUTDOWN:
1593 1601 if ((rval = zone_graceful_shutdown(zlogp)) == 0) {
1594 1602 wait_shut = B_TRUE;
1595 1603 }
1596 1604 break;
1597 1605 case Z_NOTE_UNINSTALLING:
1598 1606 case Z_MOUNT:
1607 + case Z_FORCEMOUNT:
1599 1608 case Z_UNMOUNT:
1600 1609 zerror(zlogp, B_FALSE, "%s operation is invalid "
1601 1610 "for zones in state '%s'", z_cmd_name(cmd),
1602 1611 zone_state_str(zstate));
1603 1612 rval = -1;
1604 1613 break;
1605 1614 }
1606 1615 break;
1607 1616 default:
1608 1617 abort();
1609 1618 }
1610 1619
1611 1620 /*
1612 1621 * Because the state of the zone may have changed, we make sure
1613 1622 * to wake the console poller, which is in charge of initiating
1614 1623 * the shutdown procedure as necessary.
1615 1624 */
1616 1625 eventstream_write(Z_EVT_NULL);
1617 1626
1618 1627 out:
1619 1628 (void) mutex_unlock(&lock);
1620 1629
1621 1630 /* Wait for the Z_SHUTDOWN commands to complete */
1622 1631 if (wait_shut)
1623 1632 rval = zone_wait_shutdown(zlogp);
1624 1633
1625 1634 if (kernelcall) {
1626 1635 rvalp = NULL;
1627 1636 rlen = 0;
1628 1637 } else {
1629 1638 rvalp->rval = rval;
1630 1639 }
1631 1640 if (uc != NULL)
1632 1641 ucred_free(uc);
1633 1642 (void) door_return((char *)rvalp, rlen, NULL, 0);
1634 1643 thr_exit(NULL);
1635 1644 }
1636 1645
1637 1646 static int
1638 1647 setup_door(zlog_t *zlogp)
1639 1648 {
1640 1649 if ((zone_door = door_create(server, NULL,
1641 1650 DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
1642 1651 zerror(zlogp, B_TRUE, "%s failed", "door_create");
1643 1652 return (-1);
1644 1653 }
1645 1654 (void) fdetach(zone_door_path);
1646 1655
1647 1656 if (fattach(zone_door, zone_door_path) != 0) {
1648 1657 zerror(zlogp, B_TRUE, "fattach to %s failed", zone_door_path);
1649 1658 (void) door_revoke(zone_door);
1650 1659 (void) fdetach(zone_door_path);
1651 1660 zone_door = -1;
1652 1661 return (-1);
1653 1662 }
1654 1663 return (0);
1655 1664 }
1656 1665
1657 1666 /*
1658 1667 * zoneadm(1m) will start zoneadmd if it thinks it isn't running; this
1659 1668 * is where zoneadmd itself will check to see that another instance of
1660 1669 * zoneadmd isn't already controlling this zone.
1661 1670 *
1662 1671 * The idea here is that we want to open the path to which we will
1663 1672 * attach our door, lock it, and then make sure that no-one has beat us
1664 1673 * to fattach(3c)ing onto it.
1665 1674 *
1666 1675 * fattach(3c) is really a mount, so there are actually two possible
1667 1676 * vnodes we could be dealing with. Our strategy is as follows:
1668 1677 *
1669 1678 * - If the file we opened is a regular file (common case):
1670 1679 * There is no fattach(3c)ed door, so we have a chance of becoming
1671 1680 * the managing zoneadmd. We attempt to lock the file: if it is
1672 1681 * already locked, that means someone else raced us here, so we
1673 1682 * lose and give up. zoneadm(1m) will try to contact the zoneadmd
1674 1683 * that beat us to it.
1675 1684 *
1676 1685 * - If the file we opened is a namefs file:
1677 1686 * This means there is already an established door fattach(3c)'ed
1678 1687 * to the rendezvous path. We've lost the race, so we give up.
1679 1688 * Note that in this case we also try to grab the file lock, and
1680 1689 * will succeed in acquiring it since the vnode locked by the
1681 1690 * "winning" zoneadmd was a regular one, and the one we locked was
1682 1691 * the fattach(3c)'ed door node. At any rate, no harm is done, and
1683 1692 * we just return to zoneadm(1m) which knows to retry.
1684 1693 */
1685 1694 static int
1686 1695 make_daemon_exclusive(zlog_t *zlogp)
1687 1696 {
1688 1697 int doorfd = -1;
1689 1698 int err, ret = -1;
1690 1699 struct stat st;
1691 1700 struct flock flock;
1692 1701 zone_state_t zstate;
1693 1702
1694 1703 top:
1695 1704 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1696 1705 zerror(zlogp, B_FALSE, "failed to get zone state: %s",
1697 1706 zonecfg_strerror(err));
1698 1707 goto out;
1699 1708 }
1700 1709 if ((doorfd = open(zone_door_path, O_CREAT|O_RDWR,
1701 1710 S_IREAD|S_IWRITE)) < 0) {
1702 1711 zerror(zlogp, B_TRUE, "failed to open %s", zone_door_path);
1703 1712 goto out;
1704 1713 }
1705 1714 if (fstat(doorfd, &st) < 0) {
1706 1715 zerror(zlogp, B_TRUE, "failed to stat %s", zone_door_path);
1707 1716 goto out;
1708 1717 }
1709 1718 /*
1710 1719 * Lock the file to synchronize with other zoneadmd
1711 1720 */
1712 1721 flock.l_type = F_WRLCK;
1713 1722 flock.l_whence = SEEK_SET;
1714 1723 flock.l_start = (off_t)0;
1715 1724 flock.l_len = (off_t)0;
1716 1725 if (fcntl(doorfd, F_SETLK, &flock) < 0) {
1717 1726 /*
1718 1727 * Someone else raced us here and grabbed the lock file
1719 1728 * first. A warning here is inappropriate since nothing
1720 1729 * went wrong.
1721 1730 */
1722 1731 goto out;
1723 1732 }
1724 1733
1725 1734 if (strcmp(st.st_fstype, "namefs") == 0) {
1726 1735 struct door_info info;
1727 1736
1728 1737 /*
1729 1738 * There is already something fattach()'ed to this file.
1730 1739 * Lets see what the door is up to.
1731 1740 */
1732 1741 if (door_info(doorfd, &info) == 0 && info.di_target != -1) {
1733 1742 /*
1734 1743 * Another zoneadmd process seems to be in
1735 1744 * control of the situation and we don't need to
1736 1745 * be here. A warning here is inappropriate
1737 1746 * since nothing went wrong.
1738 1747 *
1739 1748 * If the door has been revoked, the zoneadmd
1740 1749 * process currently managing the zone is going
1741 1750 * away. We'll return control to zoneadm(1m)
1742 1751 * which will try again (by which time zoneadmd
1743 1752 * will hopefully have exited).
1744 1753 */
1745 1754 goto out;
1746 1755 }
1747 1756
1748 1757 /*
1749 1758 * If we got this far, there's a fattach(3c)'ed door
1750 1759 * that belongs to a process that has exited, which can
1751 1760 * happen if the previous zoneadmd died unexpectedly.
1752 1761 *
1753 1762 * Let user know that something is amiss, but that we can
1754 1763 * recover; if the zone is in the installed state, then don't
1755 1764 * message, since having a running zoneadmd isn't really
1756 1765 * expected/needed. We want to keep occurences of this message
1757 1766 * limited to times when zoneadmd is picking back up from a
1758 1767 * zoneadmd that died while the zone was in some non-trivial
1759 1768 * state.
1760 1769 */
1761 1770 if (zstate > ZONE_STATE_INSTALLED) {
1762 1771 zerror(zlogp, B_FALSE,
1763 1772 "zone '%s': WARNING: zone is in state '%s', but "
1764 1773 "zoneadmd does not appear to be available; "
1765 1774 "restarted zoneadmd to recover.",
1766 1775 zone_name, zone_state_str(zstate));
1767 1776 }
1768 1777
1769 1778 (void) fdetach(zone_door_path);
1770 1779 (void) close(doorfd);
1771 1780 goto top;
1772 1781 }
1773 1782 ret = 0;
1774 1783 out:
1775 1784 (void) close(doorfd);
1776 1785 return (ret);
1777 1786 }
1778 1787
1779 1788 /*
1780 1789 * Setup the brand's pre and post state change callbacks, as well as the
1781 1790 * query callback, if any of these exist.
1782 1791 */
1783 1792 static int
1784 1793 brand_callback_init(brand_handle_t bh, char *zone_name)
1785 1794 {
1786 1795 char zpath[MAXPATHLEN];
1787 1796
1788 1797 if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK)
1789 1798 return (-1);
1790 1799
1791 1800 (void) strlcpy(pre_statechg_hook, EXEC_PREFIX,
1792 1801 sizeof (pre_statechg_hook));
1793 1802
1794 1803 if (brand_get_prestatechange(bh, zone_name, zpath,
1795 1804 pre_statechg_hook + EXEC_LEN,
1796 1805 sizeof (pre_statechg_hook) - EXEC_LEN) != 0)
1797 1806 return (-1);
1798 1807
1799 1808 if (strlen(pre_statechg_hook) <= EXEC_LEN)
1800 1809 pre_statechg_hook[0] = '\0';
1801 1810
1802 1811 (void) strlcpy(post_statechg_hook, EXEC_PREFIX,
1803 1812 sizeof (post_statechg_hook));
1804 1813
1805 1814 if (brand_get_poststatechange(bh, zone_name, zpath,
1806 1815 post_statechg_hook + EXEC_LEN,
1807 1816 sizeof (post_statechg_hook) - EXEC_LEN) != 0)
1808 1817 return (-1);
1809 1818
1810 1819 if (strlen(post_statechg_hook) <= EXEC_LEN)
1811 1820 post_statechg_hook[0] = '\0';
1812 1821
1813 1822 (void) strlcpy(query_hook, EXEC_PREFIX,
1814 1823 sizeof (query_hook));
1815 1824
1816 1825 if (brand_get_query(bh, zone_name, zpath, query_hook + EXEC_LEN,
1817 1826 sizeof (query_hook) - EXEC_LEN) != 0)
1818 1827 return (-1);
1819 1828
1820 1829 if (strlen(query_hook) <= EXEC_LEN)
1821 1830 query_hook[0] = '\0';
1822 1831
1823 1832 return (0);
1824 1833 }
1825 1834
1826 1835 int
1827 1836 main(int argc, char *argv[])
1828 1837 {
1829 1838 int opt;
1830 1839 zoneid_t zid;
1831 1840 priv_set_t *privset;
1832 1841 zone_state_t zstate;
1833 1842 char parents_locale[MAXPATHLEN];
1834 1843 brand_handle_t bh;
1835 1844 int err;
1836 1845
1837 1846 pid_t pid;
1838 1847 sigset_t blockset;
1839 1848 sigset_t block_cld;
1840 1849
1841 1850 struct {
1842 1851 sema_t sem;
1843 1852 int status;
1844 1853 zlog_t log;
1845 1854 } *shstate;
1846 1855 size_t shstatelen = getpagesize();
1847 1856
1848 1857 zlog_t errlog;
1849 1858 zlog_t *zlogp;
1850 1859
1851 1860 int ctfd;
1852 1861
1853 1862 progname = get_execbasename(argv[0]);
1854 1863
1855 1864 /*
1856 1865 * Make sure stderr is unbuffered
1857 1866 */
1858 1867 (void) setbuffer(stderr, NULL, 0);
1859 1868
1860 1869 /*
1861 1870 * Get out of the way of mounted filesystems, since we will daemonize
1862 1871 * soon.
1863 1872 */
1864 1873 (void) chdir("/");
1865 1874
1866 1875 /*
1867 1876 * Use the default system umask per PSARC 1998/110 rather than
1868 1877 * anything that may have been set by the caller.
1869 1878 */
1870 1879 (void) umask(CMASK);
1871 1880
1872 1881 /*
1873 1882 * Initially we want to use our parent's locale.
1874 1883 */
1875 1884 (void) setlocale(LC_ALL, "");
1876 1885 (void) textdomain(TEXT_DOMAIN);
1877 1886 (void) strlcpy(parents_locale, setlocale(LC_MESSAGES, NULL),
1878 1887 sizeof (parents_locale));
1879 1888
1880 1889 /*
1881 1890 * This zlog_t is used for writing to stderr
1882 1891 */
1883 1892 errlog.logfile = stderr;
1884 1893 errlog.buflen = errlog.loglen = 0;
1885 1894 errlog.buf = errlog.log = NULL;
1886 1895 errlog.locale = parents_locale;
1887 1896
1888 1897 /*
1889 1898 * We start off writing to stderr until we're ready to daemonize.
1890 1899 */
1891 1900 zlogp = &errlog;
1892 1901
1893 1902 /*
1894 1903 * Process options.
1895 1904 */
1896 1905 while ((opt = getopt(argc, argv, "R:z:")) != EOF) {
1897 1906 switch (opt) {
1898 1907 case 'R':
1899 1908 zonecfg_set_root(optarg);
1900 1909 break;
1901 1910 case 'z':
1902 1911 zone_name = optarg;
1903 1912 break;
1904 1913 default:
1905 1914 usage();
1906 1915 }
1907 1916 }
1908 1917
1909 1918 if (zone_name == NULL)
1910 1919 usage();
1911 1920
1912 1921 /*
1913 1922 * Because usage() prints directly to stderr, it has gettext()
1914 1923 * wrapping, which depends on the locale. But since zerror() calls
1915 1924 * localize() which tweaks the locale, it is not safe to call zerror()
1916 1925 * until after the last call to usage(). Fortunately, the last call
1917 1926 * to usage() is just above and the first call to zerror() is just
1918 1927 * below. Don't mess this up.
1919 1928 */
1920 1929 if (strcmp(zone_name, GLOBAL_ZONENAME) == 0) {
1921 1930 zerror(zlogp, B_FALSE, "cannot manage the %s zone",
1922 1931 GLOBAL_ZONENAME);
1923 1932 return (1);
1924 1933 }
1925 1934
1926 1935 if (zone_get_id(zone_name, &zid) != 0) {
1927 1936 zerror(zlogp, B_FALSE, "could not manage %s: %s", zone_name,
1928 1937 zonecfg_strerror(Z_NO_ZONE));
1929 1938 return (1);
1930 1939 }
1931 1940
1932 1941 if ((err = zone_get_state(zone_name, &zstate)) != Z_OK) {
1933 1942 zerror(zlogp, B_FALSE, "failed to get zone state: %s",
1934 1943 zonecfg_strerror(err));
1935 1944 return (1);
1936 1945 }
1937 1946 if (zstate < ZONE_STATE_INCOMPLETE) {
1938 1947 zerror(zlogp, B_FALSE,
1939 1948 "cannot manage a zone which is in state '%s'",
1940 1949 zone_state_str(zstate));
1941 1950 return (1);
1942 1951 }
1943 1952
1944 1953 if (zonecfg_default_brand(default_brand,
1945 1954 sizeof (default_brand)) != Z_OK) {
1946 1955 zerror(zlogp, B_FALSE, "unable to determine default brand");
1947 1956 return (1);
1948 1957 }
1949 1958
1950 1959 /* Get a handle to the brand info for this zone */
1951 1960 if (zone_get_brand(zone_name, brand_name, sizeof (brand_name))
1952 1961 != Z_OK) {
1953 1962 zerror(zlogp, B_FALSE, "unable to determine zone brand");
1954 1963 return (1);
1955 1964 }
1956 1965 zone_isnative = (strcmp(brand_name, NATIVE_BRAND_NAME) == 0);
1957 1966 zone_islabeled = (strcmp(brand_name, LABELED_BRAND_NAME) == 0);
1958 1967
1959 1968 /*
1960 1969 * In the alternate root environment, the only supported
1961 1970 * operations are mount and unmount. In this case, just treat
1962 1971 * the zone as native if it is cluster. Cluster zones can be
1963 1972 * native for the purpose of LU or upgrade, and the cluster
1964 1973 * brand may not exist in the miniroot (such as in net install
1965 1974 * upgrade).
1966 1975 */
1967 1976 if (strcmp(brand_name, CLUSTER_BRAND_NAME) == 0) {
1968 1977 zone_iscluster = B_TRUE;
1969 1978 if (zonecfg_in_alt_root()) {
1970 1979 (void) strlcpy(brand_name, default_brand,
1971 1980 sizeof (brand_name));
1972 1981 }
1973 1982 } else {
1974 1983 zone_iscluster = B_FALSE;
1975 1984 }
1976 1985
1977 1986 if ((bh = brand_open(brand_name)) == NULL) {
1978 1987 zerror(zlogp, B_FALSE, "unable to open zone brand");
1979 1988 return (1);
1980 1989 }
1981 1990
1982 1991 /* Get state change brand hooks. */
1983 1992 if (brand_callback_init(bh, zone_name) == -1) {
1984 1993 zerror(zlogp, B_TRUE,
1985 1994 "failed to initialize brand state change hooks");
1986 1995 brand_close(bh);
1987 1996 return (1);
1988 1997 }
1989 1998
1990 1999 brand_close(bh);
1991 2000
1992 2001 /*
1993 2002 * Check that we have all privileges. It would be nice to pare
1994 2003 * this down, but this is at least a first cut.
1995 2004 */
1996 2005 if ((privset = priv_allocset()) == NULL) {
1997 2006 zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
1998 2007 return (1);
1999 2008 }
2000 2009
2001 2010 if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
2002 2011 zerror(zlogp, B_TRUE, "%s failed", "getppriv");
2003 2012 priv_freeset(privset);
2004 2013 return (1);
2005 2014 }
2006 2015
2007 2016 if (priv_isfullset(privset) == B_FALSE) {
2008 2017 zerror(zlogp, B_FALSE, "You lack sufficient privilege to "
2009 2018 "run this command (all privs required)");
2010 2019 priv_freeset(privset);
2011 2020 return (1);
2012 2021 }
2013 2022 priv_freeset(privset);
2014 2023
2015 2024 if (mkzonedir(zlogp) != 0)
2016 2025 return (1);
2017 2026
2018 2027 /*
2019 2028 * Pre-fork: setup shared state
2020 2029 */
2021 2030 if ((shstate = (void *)mmap(NULL, shstatelen,
2022 2031 PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, (off_t)0)) ==
2023 2032 MAP_FAILED) {
2024 2033 zerror(zlogp, B_TRUE, "%s failed", "mmap");
2025 2034 return (1);
2026 2035 }
2027 2036 if (sema_init(&shstate->sem, 0, USYNC_PROCESS, NULL) != 0) {
2028 2037 zerror(zlogp, B_TRUE, "%s failed", "sema_init()");
2029 2038 (void) munmap((char *)shstate, shstatelen);
2030 2039 return (1);
2031 2040 }
2032 2041 shstate->log.logfile = NULL;
2033 2042 shstate->log.buflen = shstatelen - sizeof (*shstate);
2034 2043 shstate->log.loglen = shstate->log.buflen;
2035 2044 shstate->log.buf = (char *)shstate + sizeof (*shstate);
2036 2045 shstate->log.log = shstate->log.buf;
2037 2046 shstate->log.locale = parents_locale;
2038 2047 shstate->status = -1;
2039 2048
2040 2049 /*
2041 2050 * We need a SIGCHLD handler so the sema_wait() below will wake
2042 2051 * up if the child dies without doing a sema_post().
2043 2052 */
2044 2053 (void) sigset(SIGCHLD, sigchld);
2045 2054 /*
2046 2055 * We must mask SIGCHLD until after we've coped with the fork
2047 2056 * sufficiently to deal with it; otherwise we can race and
2048 2057 * receive the signal before pid has been initialized
2049 2058 * (yes, this really happens).
2050 2059 */
2051 2060 (void) sigemptyset(&block_cld);
2052 2061 (void) sigaddset(&block_cld, SIGCHLD);
2053 2062 (void) sigprocmask(SIG_BLOCK, &block_cld, NULL);
2054 2063
2055 2064 if ((ctfd = init_template()) == -1) {
2056 2065 zerror(zlogp, B_TRUE, "failed to create contract");
2057 2066 return (1);
2058 2067 }
2059 2068
2060 2069 /*
2061 2070 * Do not let another thread localize a message while we are forking.
2062 2071 */
2063 2072 (void) mutex_lock(&msglock);
2064 2073 pid = fork();
2065 2074 (void) mutex_unlock(&msglock);
2066 2075
2067 2076 /*
2068 2077 * In all cases (parent, child, and in the event of an error) we
2069 2078 * don't want to cause creation of contracts on subsequent fork()s.
2070 2079 */
2071 2080 (void) ct_tmpl_clear(ctfd);
2072 2081 (void) close(ctfd);
2073 2082
2074 2083 if (pid == -1) {
2075 2084 zerror(zlogp, B_TRUE, "could not fork");
2076 2085 return (1);
2077 2086
2078 2087 } else if (pid > 0) { /* parent */
2079 2088 (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2080 2089 /*
2081 2090 * This marks a window of vulnerability in which we receive
2082 2091 * the SIGCLD before falling into sema_wait (normally we would
2083 2092 * get woken up from sema_wait with EINTR upon receipt of
2084 2093 * SIGCLD). So we may need to use some other scheme like
2085 2094 * sema_posting in the sigcld handler.
2086 2095 * blech
2087 2096 */
2088 2097 (void) sema_wait(&shstate->sem);
2089 2098 (void) sema_destroy(&shstate->sem);
2090 2099 if (shstate->status != 0)
2091 2100 (void) waitpid(pid, NULL, WNOHANG);
2092 2101 /*
2093 2102 * It's ok if we die with SIGPIPE. It's not like we could have
2094 2103 * done anything about it.
2095 2104 */
2096 2105 (void) fprintf(stderr, "%s", shstate->log.buf);
2097 2106 _exit(shstate->status == 0 ? 0 : 1);
2098 2107 }
2099 2108
2100 2109 /*
2101 2110 * The child charges on.
2102 2111 */
2103 2112 (void) sigset(SIGCHLD, SIG_DFL);
2104 2113 (void) sigprocmask(SIG_UNBLOCK, &block_cld, NULL);
2105 2114
2106 2115 /*
2107 2116 * SIGPIPE can be delivered if we write to a socket for which the
2108 2117 * peer endpoint is gone. That can lead to too-early termination
2109 2118 * of zoneadmd, and that's not good eats.
2110 2119 */
2111 2120 (void) sigset(SIGPIPE, SIG_IGN);
2112 2121 /*
2113 2122 * Stop using stderr
2114 2123 */
2115 2124 zlogp = &shstate->log;
2116 2125
2117 2126 /*
2118 2127 * We don't need stdout/stderr from now on.
2119 2128 */
2120 2129 closefrom(0);
2121 2130
2122 2131 /*
2123 2132 * Initialize the syslog zlog_t. This needs to be done after
2124 2133 * the call to closefrom().
2125 2134 */
2126 2135 logsys.buf = logsys.log = NULL;
2127 2136 logsys.buflen = logsys.loglen = 0;
2128 2137 logsys.logfile = NULL;
2129 2138 logsys.locale = DEFAULT_LOCALE;
2130 2139
2131 2140 openlog("zoneadmd", LOG_PID, LOG_DAEMON);
2132 2141
2133 2142 /*
2134 2143 * The eventstream is used to publish state changes in the zone
2135 2144 * from the door threads to the console I/O poller.
2136 2145 */
2137 2146 if (eventstream_init() == -1) {
2138 2147 zerror(zlogp, B_TRUE, "unable to create eventstream");
2139 2148 goto child_out;
2140 2149 }
2141 2150
2142 2151 (void) snprintf(zone_door_path, sizeof (zone_door_path),
2143 2152 "%s" ZONE_DOOR_PATH, zonecfg_get_root(), zone_name);
2144 2153
2145 2154 /*
2146 2155 * See if another zoneadmd is running for this zone. If not, then we
2147 2156 * can now modify system state.
2148 2157 */
2149 2158 if (make_daemon_exclusive(zlogp) == -1)
2150 2159 goto child_out;
2151 2160
2152 2161
2153 2162 /*
2154 2163 * Create/join a new session; we need to be careful of what we do with
2155 2164 * the console from now on so we don't end up being the session leader
2156 2165 * for the terminal we're going to be handing out.
2157 2166 */
2158 2167 (void) setsid();
2159 2168
2160 2169 /*
2161 2170 * This thread shouldn't be receiving any signals; in particular,
2162 2171 * SIGCHLD should be received by the thread doing the fork().
2163 2172 */
2164 2173 (void) sigfillset(&blockset);
2165 2174 (void) thr_sigsetmask(SIG_BLOCK, &blockset, NULL);
2166 2175
2167 2176 /*
2168 2177 * Setup the console device and get ready to serve the console;
2169 2178 * once this has completed, we're ready to let console clients
2170 2179 * make an attempt to connect (they will block until
2171 2180 * serve_console_sock() below gets called, and any pending
2172 2181 * connection is accept()ed).
2173 2182 */
2174 2183 if (!zonecfg_in_alt_root() && init_console(zlogp) < 0)
2175 2184 goto child_out;
2176 2185
2177 2186 /*
2178 2187 * Take the lock now, so that when the door server gets going, we
2179 2188 * are guaranteed that it won't take a request until we are sure
2180 2189 * that everything is completely set up. See the child_out: label
2181 2190 * below to see why this matters.
2182 2191 */
2183 2192 (void) mutex_lock(&lock);
2184 2193
2185 2194 /* Init semaphore for scratch zones. */
2186 2195 if (sema_init(&scratch_sem, 0, USYNC_THREAD, NULL) == -1) {
2187 2196 zerror(zlogp, B_TRUE,
2188 2197 "failed to initialize semaphore for scratch zone");
2189 2198 goto child_out;
2190 2199 }
2191 2200
2192 2201 /* open the dladm handle */
2193 2202 if (dladm_open(&dld_handle) != DLADM_STATUS_OK) {
2194 2203 zerror(zlogp, B_FALSE, "failed to open dladm handle");
2195 2204 goto child_out;
2196 2205 }
2197 2206
2198 2207 /*
2199 2208 * Note: door setup must occur *after* the console is setup.
2200 2209 * This is so that as zlogin tests the door to see if zoneadmd
2201 2210 * is ready yet, we know that the console will get serviced
2202 2211 * once door_info() indicates that the door is "up".
2203 2212 */
2204 2213 if (setup_door(zlogp) == -1)
2205 2214 goto child_out;
2206 2215
2207 2216 /*
2208 2217 * Things seem OK so far; tell the parent process that we're done
2209 2218 * with setup tasks. This will cause the parent to exit, signalling
2210 2219 * to zoneadm, zlogin, or whatever forked it that we are ready to
2211 2220 * service requests.
2212 2221 */
2213 2222 shstate->status = 0;
2214 2223 (void) sema_post(&shstate->sem);
2215 2224 (void) munmap((char *)shstate, shstatelen);
2216 2225 shstate = NULL;
2217 2226
2218 2227 (void) mutex_unlock(&lock);
2219 2228
2220 2229 /*
2221 2230 * zlogp is now invalid, so reset it to the syslog logger.
2222 2231 */
2223 2232 zlogp = &logsys;
2224 2233
2225 2234 /*
2226 2235 * Now that we are free of any parents, switch to the default locale.
2227 2236 */
2228 2237 (void) setlocale(LC_ALL, DEFAULT_LOCALE);
2229 2238
2230 2239 /*
2231 2240 * At this point the setup portion of main() is basically done, so
2232 2241 * we reuse this thread to manage the zone console. When
2233 2242 * serve_console() has returned, we are past the point of no return
2234 2243 * in the life of this zoneadmd.
2235 2244 */
2236 2245 if (zonecfg_in_alt_root()) {
2237 2246 /*
2238 2247 * This is just awful, but mounted scratch zones don't (and
2239 2248 * can't) have consoles. We just wait for unmount instead.
2240 2249 */
2241 2250 while (sema_wait(&scratch_sem) == EINTR)
2242 2251 ;
2243 2252 } else {
2244 2253 serve_console(zlogp);
2245 2254 assert(in_death_throes);
2246 2255 }
2247 2256
2248 2257 /*
2249 2258 * This is the next-to-last part of the exit interlock. Upon calling
2250 2259 * fdetach(), the door will go unreferenced; once any
2251 2260 * outstanding requests (like the door thread doing Z_HALT) are
2252 2261 * done, the door will get an UNREF notification; when it handles
2253 2262 * the UNREF, the door server will cause the exit. It's possible
2254 2263 * that fdetach() can fail because the file is in use, in which
2255 2264 * case we'll retry the operation.
2256 2265 */
2257 2266 assert(!MUTEX_HELD(&lock));
2258 2267 for (;;) {
2259 2268 if ((fdetach(zone_door_path) == 0) || (errno != EBUSY))
2260 2269 break;
2261 2270 yield();
2262 2271 }
2263 2272
2264 2273 for (;;)
2265 2274 (void) pause();
2266 2275
2267 2276 child_out:
2268 2277 assert(pid == 0);
2269 2278 if (shstate != NULL) {
2270 2279 shstate->status = -1;
2271 2280 (void) sema_post(&shstate->sem);
2272 2281 (void) munmap((char *)shstate, shstatelen);
2273 2282 }
2274 2283
2275 2284 /*
2276 2285 * This might trigger an unref notification, but if so,
2277 2286 * we are still holding the lock, so our call to exit will
2278 2287 * ultimately win the race and will publish the right exit
2279 2288 * code.
2280 2289 */
2281 2290 if (zone_door != -1) {
2282 2291 assert(MUTEX_HELD(&lock));
2283 2292 (void) door_revoke(zone_door);
2284 2293 (void) fdetach(zone_door_path);
2285 2294 }
2286 2295
2287 2296 if (dld_handle != NULL)
2288 2297 dladm_close(dld_handle);
2289 2298
2290 2299 return (1); /* return from main() forcibly exits an MT process */
2291 2300 }
|
↓ open down ↓ |
683 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX