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