Print this page
OS-5330 zoneadm mounting an lx or joyent branded zone fails
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
(NOTE: Manual port, because of divergence from SmartOS.)
Network interfaces need to configure in /native/dev for LX.
Mismerged snap_hndl (should be handle) blocked lipkg zone boot
(NOTE: There are other instances of snap_hndl we pulled in from
illumos-joyent that may need to be nuked too.)
OS-1571 Placate gcc -Wparentheses
Reviewed by: Robert Mustacchi <rm@joyent.com>
OS-5292 zoneadmd should infer zone.max-processes
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4915 want FX high priority zone configuration option
OS-4925 ps pri shows misleading value for zone in RT scheduling class
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4254 libbrand token substitution incomplete for mount entries
OS-3776 project rctls should be in sync with zone rctls
OS-3524 in order to support interaction with docker containers, need to be able to connect to stdio for init from GZ
OS-3525 in order to support 'docker logs' need to be able to get stdio from zone to log file
OS-399 zone phys. mem. cap should be a rctl and have associated kstat
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/zoneadmd/vplat.c
+++ new/usr/src/cmd/zoneadmd/vplat.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
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 - * Copyright (c) 2013, Joyent Inc. All rights reserved.
25 24 * Copyright (c) 2015 by Delphix. All rights reserved.
25 + * Copyright 2016, Joyent Inc.
26 26 */
27 27
28 28 /*
29 29 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
30 30 */
31 31
32 32 /*
33 33 * This module contains functions used to bring up and tear down the
34 34 * Virtual Platform: [un]mounting file-systems, [un]plumbing network
35 35 * interfaces, [un]configuring devices, establishing resource controls,
36 36 * and creating/destroying the zone in the kernel. These actions, on
37 37 * the way up, ready the zone; on the way down, they halt the zone.
38 38 * See the much longer block comment at the beginning of zoneadmd.c
39 39 * for a bigger picture of how the whole program functions.
40 40 *
41 41 * This module also has primary responsibility for the layout of "scratch
42 42 * zones." These are mounted, but inactive, zones that are used during
43 43 * operating system upgrade and potentially other administrative action. The
44 44 * scratch zone environment is similar to the miniroot environment. The zone's
45 45 * actual root is mounted read-write on /a, and the standard paths (/usr,
46 46 * /sbin, /lib) all lead to read-only copies of the running system's binaries.
47 47 * This allows the administrative tools to manipulate the zone using "-R /a"
48 48 * without relying on any binaries in the zone itself.
49 49 *
50 50 * If the scratch zone is on an alternate root (Live Upgrade [LU] boot
51 51 * environment), then we must resolve the lofs mounts used there to uncover
52 52 * writable (unshared) resources. Shared resources, though, are always
53 53 * read-only. In addition, if the "same" zone with a different root path is
54 54 * currently running, then "/b" inside the zone points to the running zone's
55 55 * root. This allows LU to synchronize configuration files during the upgrade
56 56 * process.
57 57 *
58 58 * To construct this environment, this module creates a tmpfs mount on
59 59 * $ZONEPATH/lu. Inside this scratch area, the miniroot-like environment as
60 60 * described above is constructed on the fly. The zone is then created using
61 61 * $ZONEPATH/lu as the root.
62 62 *
63 63 * Note that scratch zones are inactive. The zone's bits are not running and
64 64 * likely cannot be run correctly until upgrade is done. Init is not running
65 65 * there, nor is SMF. Because of this, the "mounted" state of a scratch zone
66 66 * is not a part of the usual halt/ready/boot state machine.
67 67 */
68 68
69 69 #include <sys/param.h>
70 70 #include <sys/mount.h>
71 71 #include <sys/mntent.h>
72 72 #include <sys/socket.h>
73 73 #include <sys/utsname.h>
74 74 #include <sys/types.h>
75 75 #include <sys/stat.h>
76 76 #include <sys/sockio.h>
77 77 #include <sys/stropts.h>
78 78 #include <sys/conf.h>
79 79 #include <sys/systeminfo.h>
80 80
81 81 #include <libdlpi.h>
82 82 #include <libdllink.h>
83 83 #include <libdlvlan.h>
84 84
85 85 #include <inet/tcp.h>
86 86 #include <arpa/inet.h>
87 87 #include <netinet/in.h>
88 88 #include <net/route.h>
89 89
90 90 #include <stdio.h>
91 91 #include <errno.h>
92 92 #include <fcntl.h>
93 93 #include <unistd.h>
94 94 #include <rctl.h>
95 95 #include <stdlib.h>
96 96 #include <string.h>
97 97 #include <strings.h>
98 98 #include <wait.h>
99 99 #include <limits.h>
100 100 #include <libgen.h>
101 101 #include <libzfs.h>
102 102 #include <libdevinfo.h>
103 103 #include <zone.h>
104 104 #include <assert.h>
105 105 #include <libcontract.h>
106 106 #include <libcontract_priv.h>
107 107 #include <uuid/uuid.h>
108 108
109 109 #include <sys/mntio.h>
110 110 #include <sys/mnttab.h>
111 111 #include <sys/fs/autofs.h> /* for _autofssys() */
112 112 #include <sys/fs/lofs_info.h>
113 113 #include <sys/fs/zfs.h>
114 114
115 115 #include <pool.h>
116 116 #include <sys/pool.h>
117 117 #include <sys/priocntl.h>
118 118
119 119 #include <libbrand.h>
120 120 #include <sys/brand.h>
121 121 #include <libzonecfg.h>
122 122 #include <synch.h>
123 123
124 124 #include "zoneadmd.h"
125 125 #include <tsol/label.h>
126 126 #include <libtsnet.h>
127 127 #include <sys/priv.h>
128 128 #include <libinetutil.h>
|
↓ open down ↓ |
93 lines elided |
↑ open up ↑ |
129 129
130 130 #define V4_ADDR_LEN 32
131 131 #define V6_ADDR_LEN 128
132 132
133 133 #define RESOURCE_DEFAULT_OPTS \
134 134 MNTOPT_RO "," MNTOPT_LOFS_NOSUB "," MNTOPT_NODEVICES
135 135
136 136 #define DFSTYPES "/etc/dfs/fstypes"
137 137 #define MAXTNZLEN 2048
138 138
139 -#define ALT_MOUNT(mount_cmd) ((mount_cmd) != Z_MNT_BOOT)
140 -
141 139 /* a reasonable estimate for the number of lwps per process */
142 140 #define LWPS_PER_PROCESS 10
143 141
144 142 /* for routing socket */
145 143 static int rts_seqno = 0;
146 144
147 145 /* mangled zone name when mounting in an alternate root environment */
148 146 static char kernzone[ZONENAME_MAX];
149 147
150 148 /* array of cached mount entries for resolve_lofs */
151 149 static struct mnttab *resolve_lofs_mnts, *resolve_lofs_mnt_max;
152 150
153 151 /* for Trusted Extensions */
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
154 152 static tsol_zcent_t *get_zone_label(zlog_t *, priv_set_t *);
155 153 static int tsol_mounts(zlog_t *, char *, char *);
156 154 static void tsol_unmounts(zlog_t *, char *);
157 155
158 156 static m_label_t *zlabel = NULL;
159 157 static m_label_t *zid_label = NULL;
160 158 static priv_set_t *zprivs = NULL;
161 159
162 160 static const char *DFLT_FS_ALLOWED = "hsfs,smbfs,nfs,nfs3,nfs4,nfsdyn";
163 161
162 +typedef struct zone_proj_rctl_map {
163 + char *zpr_zone_rctl;
164 + char *zpr_project_rctl;
165 +} zone_proj_rctl_map_t;
166 +
167 +static zone_proj_rctl_map_t zone_proj_rctl_map[] = {
168 + {"zone.max-msg-ids", "project.max-msg-ids"},
169 + {"zone.max-sem-ids", "project.max-sem-ids"},
170 + {"zone.max-shm-ids", "project.max-shm-ids"},
171 + {"zone.max-shm-memory", "project.max-shm-memory"},
172 + {NULL, NULL}
173 +};
174 +
164 175 /* from libsocket, not in any header file */
165 176 extern int getnetmaskbyaddr(struct in_addr, struct in_addr *);
166 177
167 178 /* from zoneadmd */
168 179 extern char query_hook[];
169 180
170 181 /*
171 182 * For each "net" resource configured in zonecfg, we track a zone_addr_list_t
172 183 * node in a linked list that is sorted by linkid. The list is constructed as
173 184 * the xml configuration file is parsed, and the information
174 185 * contained in each node is added to the kernel before the zone is
175 186 * booted, to be retrieved and applied from within the exclusive-IP NGZ
176 187 * on boot.
177 188 */
178 189 typedef struct zone_addr_list {
179 190 struct zone_addr_list *za_next;
180 191 datalink_id_t za_linkid; /* datalink_id_t of interface */
181 192 struct zone_nwiftab za_nwiftab; /* address, defrouter properties */
182 193 } zone_addr_list_t;
183 194
184 195 /*
185 196 * An optimization for build_mnttable: reallocate (and potentially copy the
186 197 * data) only once every N times through the loop.
187 198 */
188 199 #define MNTTAB_HUNK 32
189 200
190 201 /* some handy macros */
191 202 #define SIN(s) ((struct sockaddr_in *)s)
192 203 #define SIN6(s) ((struct sockaddr_in6 *)s)
193 204
194 205 /*
195 206 * Private autofs system call
196 207 */
197 208 extern int _autofssys(int, void *);
198 209
199 210 static int
200 211 autofs_cleanup(zoneid_t zoneid)
201 212 {
202 213 /*
203 214 * Ask autofs to unmount all trigger nodes in the given zone.
204 215 */
205 216 return (_autofssys(AUTOFS_UNMOUNTALL, (void *)zoneid));
206 217 }
207 218
208 219 static void
209 220 free_mnttable(struct mnttab *mnt_array, uint_t nelem)
210 221 {
211 222 uint_t i;
212 223
213 224 if (mnt_array == NULL)
214 225 return;
215 226 for (i = 0; i < nelem; i++) {
216 227 free(mnt_array[i].mnt_mountp);
217 228 free(mnt_array[i].mnt_fstype);
218 229 free(mnt_array[i].mnt_special);
219 230 free(mnt_array[i].mnt_mntopts);
220 231 assert(mnt_array[i].mnt_time == NULL);
221 232 }
222 233 free(mnt_array);
223 234 }
224 235
225 236 /*
226 237 * Build the mount table for the zone rooted at "zroot", storing the resulting
227 238 * array of struct mnttabs in "mnt_arrayp" and the number of elements in the
228 239 * array in "nelemp".
229 240 */
230 241 static int
231 242 build_mnttable(zlog_t *zlogp, const char *zroot, size_t zrootlen, FILE *mnttab,
232 243 struct mnttab **mnt_arrayp, uint_t *nelemp)
233 244 {
234 245 struct mnttab mnt;
235 246 struct mnttab *mnts;
236 247 struct mnttab *mnp;
237 248 uint_t nmnt;
238 249
239 250 rewind(mnttab);
240 251 resetmnttab(mnttab);
241 252 nmnt = 0;
242 253 mnts = NULL;
243 254 while (getmntent(mnttab, &mnt) == 0) {
244 255 struct mnttab *tmp_array;
245 256
246 257 if (strncmp(mnt.mnt_mountp, zroot, zrootlen) != 0)
247 258 continue;
248 259 if (nmnt % MNTTAB_HUNK == 0) {
249 260 tmp_array = realloc(mnts,
250 261 (nmnt + MNTTAB_HUNK) * sizeof (*mnts));
251 262 if (tmp_array == NULL) {
252 263 free_mnttable(mnts, nmnt);
253 264 return (-1);
254 265 }
255 266 mnts = tmp_array;
256 267 }
257 268 mnp = &mnts[nmnt++];
258 269
259 270 /*
260 271 * Zero out any fields we're not using.
261 272 */
262 273 (void) memset(mnp, 0, sizeof (*mnp));
263 274
264 275 if (mnt.mnt_special != NULL)
265 276 mnp->mnt_special = strdup(mnt.mnt_special);
266 277 if (mnt.mnt_mntopts != NULL)
267 278 mnp->mnt_mntopts = strdup(mnt.mnt_mntopts);
268 279 mnp->mnt_mountp = strdup(mnt.mnt_mountp);
269 280 mnp->mnt_fstype = strdup(mnt.mnt_fstype);
270 281 if ((mnt.mnt_special != NULL && mnp->mnt_special == NULL) ||
271 282 (mnt.mnt_mntopts != NULL && mnp->mnt_mntopts == NULL) ||
272 283 mnp->mnt_mountp == NULL || mnp->mnt_fstype == NULL) {
273 284 zerror(zlogp, B_TRUE, "memory allocation failed");
274 285 free_mnttable(mnts, nmnt);
275 286 return (-1);
276 287 }
277 288 }
278 289 *mnt_arrayp = mnts;
279 290 *nelemp = nmnt;
280 291 return (0);
281 292 }
282 293
283 294 /*
284 295 * This is an optimization. The resolve_lofs function is used quite frequently
285 296 * to manipulate file paths, and on a machine with a large number of zones,
286 297 * there will be a huge number of mounted file systems. Thus, we trigger a
287 298 * reread of the list of mount points
288 299 */
289 300 static void
290 301 lofs_discard_mnttab(void)
291 302 {
292 303 free_mnttable(resolve_lofs_mnts,
293 304 resolve_lofs_mnt_max - resolve_lofs_mnts);
294 305 resolve_lofs_mnts = resolve_lofs_mnt_max = NULL;
295 306 }
296 307
297 308 static int
298 309 lofs_read_mnttab(zlog_t *zlogp)
299 310 {
300 311 FILE *mnttab;
301 312 uint_t nmnts;
302 313
303 314 if ((mnttab = fopen(MNTTAB, "r")) == NULL)
304 315 return (-1);
305 316 if (build_mnttable(zlogp, "", 0, mnttab, &resolve_lofs_mnts,
306 317 &nmnts) == -1) {
307 318 (void) fclose(mnttab);
308 319 return (-1);
309 320 }
310 321 (void) fclose(mnttab);
311 322 resolve_lofs_mnt_max = resolve_lofs_mnts + nmnts;
312 323 return (0);
313 324 }
314 325
315 326 /*
316 327 * This function loops over potential loopback mounts and symlinks in a given
317 328 * path and resolves them all down to an absolute path.
318 329 */
319 330 void
320 331 resolve_lofs(zlog_t *zlogp, char *path, size_t pathlen)
321 332 {
322 333 int len, arlen;
323 334 const char *altroot;
324 335 char tmppath[MAXPATHLEN];
325 336 boolean_t outside_altroot;
326 337
327 338 if ((len = resolvepath(path, tmppath, sizeof (tmppath))) == -1)
328 339 return;
329 340 tmppath[len] = '\0';
330 341 (void) strlcpy(path, tmppath, sizeof (tmppath));
331 342
332 343 /* This happens once per zoneadmd operation. */
333 344 if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1)
334 345 return;
335 346
336 347 altroot = zonecfg_get_root();
337 348 arlen = strlen(altroot);
338 349 outside_altroot = B_FALSE;
339 350 for (;;) {
340 351 struct mnttab *mnp;
341 352
342 353 /* Search in reverse order to find longest match */
343 354 for (mnp = resolve_lofs_mnt_max - 1; mnp >= resolve_lofs_mnts;
344 355 mnp--) {
345 356 if (mnp->mnt_fstype == NULL ||
346 357 mnp->mnt_mountp == NULL ||
347 358 mnp->mnt_special == NULL)
348 359 continue;
349 360 len = strlen(mnp->mnt_mountp);
350 361 if (strncmp(mnp->mnt_mountp, path, len) == 0 &&
351 362 (path[len] == '/' || path[len] == '\0'))
352 363 break;
353 364 }
354 365 if (mnp < resolve_lofs_mnts)
355 366 break;
356 367 /* If it's not a lofs then we're done */
357 368 if (strcmp(mnp->mnt_fstype, MNTTYPE_LOFS) != 0)
358 369 break;
359 370 if (outside_altroot) {
360 371 char *cp;
361 372 int olen = sizeof (MNTOPT_RO) - 1;
362 373
363 374 /*
364 375 * If we run into a read-only mount outside of the
365 376 * alternate root environment, then the user doesn't
366 377 * want this path to be made read-write.
367 378 */
368 379 if (mnp->mnt_mntopts != NULL &&
369 380 (cp = strstr(mnp->mnt_mntopts, MNTOPT_RO)) !=
370 381 NULL &&
371 382 (cp == mnp->mnt_mntopts || cp[-1] == ',') &&
372 383 (cp[olen] == '\0' || cp[olen] == ',')) {
373 384 break;
374 385 }
375 386 } else if (arlen > 0 &&
376 387 (strncmp(mnp->mnt_special, altroot, arlen) != 0 ||
377 388 (mnp->mnt_special[arlen] != '\0' &&
378 389 mnp->mnt_special[arlen] != '/'))) {
379 390 outside_altroot = B_TRUE;
380 391 }
381 392 /* use temporary buffer because new path might be longer */
382 393 (void) snprintf(tmppath, sizeof (tmppath), "%s%s",
383 394 mnp->mnt_special, path + len);
384 395 if ((len = resolvepath(tmppath, path, pathlen)) == -1)
385 396 break;
386 397 path[len] = '\0';
387 398 }
388 399 }
389 400
390 401 /*
391 402 * For a regular mount, check if a replacement lofs mount is needed because the
392 403 * referenced device is already mounted somewhere.
393 404 */
394 405 static int
395 406 check_lofs_needed(zlog_t *zlogp, struct zone_fstab *fsptr)
396 407 {
397 408 struct mnttab *mnp;
398 409 zone_fsopt_t *optptr, *onext;
399 410
400 411 /* This happens once per zoneadmd operation. */
401 412 if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1)
402 413 return (-1);
403 414
404 415 /*
405 416 * If this special node isn't already in use, then it's ours alone;
406 417 * no need to worry about conflicting mounts.
407 418 */
408 419 for (mnp = resolve_lofs_mnts; mnp < resolve_lofs_mnt_max;
409 420 mnp++) {
410 421 if (strcmp(mnp->mnt_special, fsptr->zone_fs_special) == 0)
411 422 break;
412 423 }
413 424 if (mnp >= resolve_lofs_mnt_max)
414 425 return (0);
415 426
416 427 /*
417 428 * Convert this duplicate mount into a lofs mount.
418 429 */
419 430 (void) strlcpy(fsptr->zone_fs_special, mnp->mnt_mountp,
420 431 sizeof (fsptr->zone_fs_special));
421 432 (void) strlcpy(fsptr->zone_fs_type, MNTTYPE_LOFS,
422 433 sizeof (fsptr->zone_fs_type));
423 434 fsptr->zone_fs_raw[0] = '\0';
424 435
425 436 /*
426 437 * Discard all but one of the original options and set that to our
427 438 * default set of options used for resources.
428 439 */
429 440 optptr = fsptr->zone_fs_options;
430 441 if (optptr == NULL) {
431 442 optptr = malloc(sizeof (*optptr));
432 443 if (optptr == NULL) {
433 444 zerror(zlogp, B_TRUE, "cannot mount %s",
434 445 fsptr->zone_fs_dir);
435 446 return (-1);
436 447 }
437 448 } else {
438 449 while ((onext = optptr->zone_fsopt_next) != NULL) {
439 450 optptr->zone_fsopt_next = onext->zone_fsopt_next;
440 451 free(onext);
441 452 }
442 453 }
443 454 (void) strcpy(optptr->zone_fsopt_opt, RESOURCE_DEFAULT_OPTS);
444 455 optptr->zone_fsopt_next = NULL;
445 456 fsptr->zone_fs_options = optptr;
446 457 return (0);
447 458 }
448 459
449 460 int
450 461 make_one_dir(zlog_t *zlogp, const char *prefix, const char *subdir, mode_t mode,
451 462 uid_t userid, gid_t groupid)
452 463 {
453 464 char path[MAXPATHLEN];
454 465 struct stat st;
455 466
456 467 if (snprintf(path, sizeof (path), "%s%s", prefix, subdir) >
457 468 sizeof (path)) {
458 469 zerror(zlogp, B_FALSE, "pathname %s%s is too long", prefix,
459 470 subdir);
460 471 return (-1);
461 472 }
462 473
463 474 if (lstat(path, &st) == 0) {
464 475 /*
465 476 * We don't check the file mode since presumably the zone
466 477 * administrator may have had good reason to change the mode,
467 478 * and we don't need to second guess him.
468 479 */
469 480 if (!S_ISDIR(st.st_mode)) {
470 481 if (S_ISREG(st.st_mode)) {
471 482 /*
472 483 * Allow readonly mounts of /etc/ files; this
473 484 * is needed most by Trusted Extensions.
474 485 */
475 486 if (strncmp(subdir, "/etc/",
476 487 strlen("/etc/")) != 0) {
477 488 zerror(zlogp, B_FALSE,
478 489 "%s is not in /etc", path);
479 490 return (-1);
480 491 }
481 492 } else {
482 493 zerror(zlogp, B_FALSE,
483 494 "%s is not a directory", path);
484 495 return (-1);
485 496 }
486 497 }
487 498 return (0);
488 499 }
489 500
490 501 if (mkdirp(path, mode) != 0) {
491 502 if (errno == EROFS)
492 503 zerror(zlogp, B_FALSE, "Could not mkdir %s.\nIt is on "
493 504 "a read-only file system in this local zone.\nMake "
494 505 "sure %s exists in the global zone.", path, subdir);
495 506 else
496 507 zerror(zlogp, B_TRUE, "mkdirp of %s failed", path);
497 508 return (-1);
498 509 }
499 510
500 511 (void) chown(path, userid, groupid);
501 512 return (0);
502 513 }
503 514
504 515 static void
505 516 free_remote_fstypes(char **types)
506 517 {
507 518 uint_t i;
508 519
509 520 if (types == NULL)
510 521 return;
511 522 for (i = 0; types[i] != NULL; i++)
512 523 free(types[i]);
513 524 free(types);
514 525 }
515 526
516 527 static char **
517 528 get_remote_fstypes(zlog_t *zlogp)
518 529 {
519 530 char **types = NULL;
520 531 FILE *fp;
521 532 char buf[MAXPATHLEN];
522 533 char fstype[MAXPATHLEN];
523 534 uint_t lines = 0;
524 535 uint_t i;
525 536
526 537 if ((fp = fopen(DFSTYPES, "r")) == NULL) {
527 538 zerror(zlogp, B_TRUE, "failed to open %s", DFSTYPES);
528 539 return (NULL);
529 540 }
530 541 /*
531 542 * Count the number of lines
532 543 */
533 544 while (fgets(buf, sizeof (buf), fp) != NULL)
534 545 lines++;
535 546 if (lines == 0) /* didn't read anything; empty file */
536 547 goto out;
537 548 rewind(fp);
538 549 /*
539 550 * Allocate enough space for a NULL-terminated array.
540 551 */
541 552 types = calloc(lines + 1, sizeof (char *));
542 553 if (types == NULL) {
543 554 zerror(zlogp, B_TRUE, "memory allocation failed");
544 555 goto out;
545 556 }
546 557 i = 0;
547 558 while (fgets(buf, sizeof (buf), fp) != NULL) {
548 559 /* LINTED - fstype is big enough to hold buf */
549 560 if (sscanf(buf, "%s", fstype) == 0) {
550 561 zerror(zlogp, B_FALSE, "unable to parse %s", DFSTYPES);
551 562 free_remote_fstypes(types);
552 563 types = NULL;
553 564 goto out;
554 565 }
555 566 types[i] = strdup(fstype);
556 567 if (types[i] == NULL) {
557 568 zerror(zlogp, B_TRUE, "memory allocation failed");
558 569 free_remote_fstypes(types);
559 570 types = NULL;
560 571 goto out;
561 572 }
562 573 i++;
563 574 }
564 575 out:
565 576 (void) fclose(fp);
566 577 return (types);
567 578 }
568 579
569 580 static boolean_t
570 581 is_remote_fstype(const char *fstype, char *const *remote_fstypes)
571 582 {
572 583 uint_t i;
573 584
574 585 if (remote_fstypes == NULL)
575 586 return (B_FALSE);
576 587 for (i = 0; remote_fstypes[i] != NULL; i++) {
577 588 if (strcmp(remote_fstypes[i], fstype) == 0)
578 589 return (B_TRUE);
579 590 }
580 591 return (B_FALSE);
581 592 }
582 593
583 594 /*
584 595 * This converts a zone root path (normally of the form .../root) to a Live
585 596 * Upgrade scratch zone root (of the form .../lu).
586 597 */
587 598 static void
588 599 root_to_lu(zlog_t *zlogp, char *zroot, size_t zrootlen, boolean_t isresolved)
589 600 {
590 601 if (!isresolved && zonecfg_in_alt_root())
591 602 resolve_lofs(zlogp, zroot, zrootlen);
592 603 (void) strcpy(strrchr(zroot, '/') + 1, "lu");
593 604 }
594 605
595 606 /*
596 607 * The general strategy for unmounting filesystems is as follows:
597 608 *
598 609 * - Remote filesystems may be dead, and attempting to contact them as
599 610 * part of a regular unmount may hang forever; we want to always try to
600 611 * forcibly unmount such filesystems and only fall back to regular
601 612 * unmounts if the filesystem doesn't support forced unmounts.
602 613 *
603 614 * - We don't want to unnecessarily corrupt metadata on local
604 615 * filesystems (ie UFS), so we want to start off with graceful unmounts,
605 616 * and only escalate to doing forced unmounts if we get stuck.
606 617 *
607 618 * We start off walking backwards through the mount table. This doesn't
608 619 * give us strict ordering but ensures that we try to unmount submounts
609 620 * first. We thus limit the number of failed umount2(2) calls.
610 621 *
611 622 * The mechanism for determining if we're stuck is to count the number
612 623 * of failed unmounts each iteration through the mount table. This
613 624 * gives us an upper bound on the number of filesystems which remain
614 625 * mounted (autofs trigger nodes are dealt with separately). If at the
615 626 * end of one unmount+autofs_cleanup cycle we still have the same number
616 627 * of mounts that we started out with, we're stuck and try a forced
617 628 * unmount. If that fails (filesystem doesn't support forced unmounts)
618 629 * then we bail and are unable to teardown the zone. If it succeeds,
619 630 * we're no longer stuck so we continue with our policy of trying
620 631 * graceful mounts first.
621 632 *
622 633 * Zone must be down (ie, no processes or threads active).
623 634 */
624 635 static int
625 636 unmount_filesystems(zlog_t *zlogp, zoneid_t zoneid, boolean_t unmount_cmd)
626 637 {
627 638 int error = 0;
628 639 FILE *mnttab;
629 640 struct mnttab *mnts;
630 641 uint_t nmnt;
631 642 char zroot[MAXPATHLEN + 1];
632 643 size_t zrootlen;
633 644 uint_t oldcount = UINT_MAX;
634 645 boolean_t stuck = B_FALSE;
635 646 char **remote_fstypes = NULL;
636 647
637 648 if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) {
638 649 zerror(zlogp, B_FALSE, "unable to determine zone root");
639 650 return (-1);
640 651 }
641 652 if (unmount_cmd)
642 653 root_to_lu(zlogp, zroot, sizeof (zroot), B_FALSE);
643 654
644 655 (void) strcat(zroot, "/");
645 656 zrootlen = strlen(zroot);
646 657
647 658 /*
648 659 * For Trusted Extensions unmount each higher level zone's mount
649 660 * of our zone's /export/home
650 661 */
651 662 if (!unmount_cmd)
652 663 tsol_unmounts(zlogp, zone_name);
653 664
654 665 if ((mnttab = fopen(MNTTAB, "r")) == NULL) {
655 666 zerror(zlogp, B_TRUE, "failed to open %s", MNTTAB);
656 667 return (-1);
657 668 }
658 669 /*
659 670 * Use our hacky mntfs ioctl so we see everything, even mounts with
660 671 * MS_NOMNTTAB.
661 672 */
662 673 if (ioctl(fileno(mnttab), MNTIOC_SHOWHIDDEN, NULL) < 0) {
663 674 zerror(zlogp, B_TRUE, "unable to configure %s", MNTTAB);
664 675 error++;
665 676 goto out;
666 677 }
667 678
668 679 /*
669 680 * Build the list of remote fstypes so we know which ones we
670 681 * should forcibly unmount.
671 682 */
672 683 remote_fstypes = get_remote_fstypes(zlogp);
673 684 for (; /* ever */; ) {
674 685 uint_t newcount = 0;
675 686 boolean_t unmounted;
676 687 struct mnttab *mnp;
677 688 char *path;
678 689 uint_t i;
679 690
680 691 mnts = NULL;
681 692 nmnt = 0;
682 693 /*
683 694 * MNTTAB gives us a way to walk through mounted
684 695 * filesystems; we need to be able to walk them in
685 696 * reverse order, so we build a list of all mounted
686 697 * filesystems.
687 698 */
688 699 if (build_mnttable(zlogp, zroot, zrootlen, mnttab, &mnts,
689 700 &nmnt) != 0) {
690 701 error++;
691 702 goto out;
692 703 }
693 704 for (i = 0; i < nmnt; i++) {
694 705 mnp = &mnts[nmnt - i - 1]; /* access in reverse order */
695 706 path = mnp->mnt_mountp;
696 707 unmounted = B_FALSE;
697 708 /*
698 709 * Try forced unmount first for remote filesystems.
699 710 *
700 711 * Not all remote filesystems support forced unmounts,
701 712 * so if this fails (ENOTSUP) we'll continue on
702 713 * and try a regular unmount.
703 714 */
704 715 if (is_remote_fstype(mnp->mnt_fstype, remote_fstypes)) {
705 716 if (umount2(path, MS_FORCE) == 0)
706 717 unmounted = B_TRUE;
707 718 }
708 719 /*
709 720 * Try forced unmount if we're stuck.
710 721 */
711 722 if (stuck) {
712 723 if (umount2(path, MS_FORCE) == 0) {
713 724 unmounted = B_TRUE;
714 725 stuck = B_FALSE;
715 726 } else {
716 727 /*
717 728 * The first failure indicates a
718 729 * mount we won't be able to get
719 730 * rid of automatically, so we
720 731 * bail.
721 732 */
722 733 error++;
723 734 zerror(zlogp, B_FALSE,
724 735 "unable to unmount '%s'", path);
725 736 free_mnttable(mnts, nmnt);
726 737 goto out;
727 738 }
728 739 }
729 740 /*
730 741 * Try regular unmounts for everything else.
731 742 */
732 743 if (!unmounted && umount2(path, 0) != 0)
733 744 newcount++;
734 745 }
735 746 free_mnttable(mnts, nmnt);
736 747
737 748 if (newcount == 0)
738 749 break;
739 750 if (newcount >= oldcount) {
740 751 /*
741 752 * Last round didn't unmount anything; we're stuck and
742 753 * should start trying forced unmounts.
743 754 */
744 755 stuck = B_TRUE;
745 756 }
746 757 oldcount = newcount;
747 758
748 759 /*
749 760 * Autofs doesn't let you unmount its trigger nodes from
750 761 * userland so we have to tell the kernel to cleanup for us.
751 762 */
752 763 if (autofs_cleanup(zoneid) != 0) {
753 764 zerror(zlogp, B_TRUE, "unable to remove autofs nodes");
754 765 error++;
755 766 goto out;
756 767 }
757 768 }
758 769
759 770 out:
760 771 free_remote_fstypes(remote_fstypes);
761 772 (void) fclose(mnttab);
762 773 return (error ? -1 : 0);
763 774 }
764 775
765 776 static int
766 777 fs_compare(const void *m1, const void *m2)
767 778 {
768 779 struct zone_fstab *i = (struct zone_fstab *)m1;
769 780 struct zone_fstab *j = (struct zone_fstab *)m2;
770 781
771 782 return (strcmp(i->zone_fs_dir, j->zone_fs_dir));
772 783 }
773 784
774 785 /*
775 786 * Fork and exec (and wait for) the mentioned binary with the provided
776 787 * arguments. Returns (-1) if something went wrong with fork(2) or exec(2),
777 788 * returns the exit status otherwise.
778 789 *
779 790 * If we were unable to exec the provided pathname (for whatever
780 791 * reason), we return the special token ZEXIT_EXEC. The current value
781 792 * of ZEXIT_EXEC doesn't conflict with legitimate exit codes of the
782 793 * consumers of this function; any future consumers must make sure this
783 794 * remains the case.
784 795 */
785 796 static int
786 797 forkexec(zlog_t *zlogp, const char *path, char *const argv[])
787 798 {
788 799 pid_t child_pid;
789 800 int child_status = 0;
790 801
791 802 /*
792 803 * Do not let another thread localize a message while we are forking.
793 804 */
794 805 (void) mutex_lock(&msglock);
795 806 child_pid = fork();
796 807 (void) mutex_unlock(&msglock);
797 808 if (child_pid == -1) {
798 809 zerror(zlogp, B_TRUE, "could not fork for %s", argv[0]);
799 810 return (-1);
800 811 } else if (child_pid == 0) {
801 812 closefrom(0);
802 813 /* redirect stdin, stdout & stderr to /dev/null */
803 814 (void) open("/dev/null", O_RDONLY); /* stdin */
804 815 (void) open("/dev/null", O_WRONLY); /* stdout */
805 816 (void) open("/dev/null", O_WRONLY); /* stderr */
806 817 (void) execv(path, argv);
807 818 /*
808 819 * Since we are in the child, there is no point calling zerror()
809 820 * since there is nobody waiting to consume it. So exit with a
810 821 * special code that the parent will recognize and call zerror()
811 822 * accordingly.
812 823 */
813 824
814 825 _exit(ZEXIT_EXEC);
815 826 } else {
816 827 (void) waitpid(child_pid, &child_status, 0);
817 828 }
818 829
819 830 if (WIFSIGNALED(child_status)) {
820 831 zerror(zlogp, B_FALSE, "%s unexpectedly terminated due to "
821 832 "signal %d", path, WTERMSIG(child_status));
822 833 return (-1);
823 834 }
824 835 assert(WIFEXITED(child_status));
825 836 if (WEXITSTATUS(child_status) == ZEXIT_EXEC) {
826 837 zerror(zlogp, B_FALSE, "failed to exec %s", path);
827 838 return (-1);
828 839 }
829 840 return (WEXITSTATUS(child_status));
830 841 }
831 842
832 843 static int
833 844 isregfile(const char *path)
834 845 {
835 846 struct stat64 st;
836 847
837 848 if (stat64(path, &st) == -1)
838 849 return (-1);
839 850
840 851 return (S_ISREG(st.st_mode));
841 852 }
842 853
843 854 static int
844 855 dofsck(zlog_t *zlogp, const char *fstype, const char *rawdev)
845 856 {
846 857 char cmdbuf[MAXPATHLEN];
847 858 char *argv[5];
848 859 int status;
849 860
850 861 /*
851 862 * We could alternatively have called /usr/sbin/fsck -F <fstype>, but
852 863 * that would cost us an extra fork/exec without buying us anything.
853 864 */
854 865 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck", fstype)
855 866 >= sizeof (cmdbuf)) {
856 867 zerror(zlogp, B_FALSE, "file-system type %s too long", fstype);
857 868 return (-1);
858 869 }
859 870
860 871 /*
861 872 * If it doesn't exist, that's OK: we verified this previously
862 873 * in zoneadm.
863 874 */
864 875 if (isregfile(cmdbuf) == -1)
865 876 return (0);
866 877
867 878 argv[0] = "fsck";
868 879 argv[1] = "-o";
869 880 argv[2] = "p";
870 881 argv[3] = (char *)rawdev;
871 882 argv[4] = NULL;
872 883
873 884 status = forkexec(zlogp, cmdbuf, argv);
874 885 if (status == 0 || status == -1)
875 886 return (status);
876 887 zerror(zlogp, B_FALSE, "fsck of '%s' failed with exit status %d; "
877 888 "run fsck manually", rawdev, status);
878 889 return (-1);
879 890 }
880 891
881 892 static int
882 893 domount(zlog_t *zlogp, const char *fstype, const char *opts,
883 894 const char *special, const char *directory)
884 895 {
885 896 char cmdbuf[MAXPATHLEN];
886 897 char *argv[6];
887 898 int status;
888 899
889 900 /*
890 901 * We could alternatively have called /usr/sbin/mount -F <fstype>, but
891 902 * that would cost us an extra fork/exec without buying us anything.
892 903 */
893 904 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount", fstype)
894 905 >= sizeof (cmdbuf)) {
895 906 zerror(zlogp, B_FALSE, "file-system type %s too long", fstype);
896 907 return (-1);
897 908 }
898 909 argv[0] = "mount";
899 910 if (opts[0] == '\0') {
900 911 argv[1] = (char *)special;
901 912 argv[2] = (char *)directory;
902 913 argv[3] = NULL;
903 914 } else {
904 915 argv[1] = "-o";
905 916 argv[2] = (char *)opts;
906 917 argv[3] = (char *)special;
907 918 argv[4] = (char *)directory;
908 919 argv[5] = NULL;
909 920 }
910 921
911 922 status = forkexec(zlogp, cmdbuf, argv);
912 923 if (status == 0 || status == -1)
913 924 return (status);
914 925 if (opts[0] == '\0')
915 926 zerror(zlogp, B_FALSE, "\"%s %s %s\" "
916 927 "failed with exit code %d",
917 928 cmdbuf, special, directory, status);
918 929 else
919 930 zerror(zlogp, B_FALSE, "\"%s -o %s %s %s\" "
920 931 "failed with exit code %d",
921 932 cmdbuf, opts, special, directory, status);
922 933 return (-1);
923 934 }
924 935
925 936 /*
926 937 * Check if a given mount point path exists.
927 938 * If it does, make sure it doesn't contain any symlinks.
928 939 * Note that if "leaf" is false we're checking an intermediate
929 940 * component of the mount point path, so it must be a directory.
930 941 * If "leaf" is true, then we're checking the entire mount point
931 942 * path, so the mount point itself can be anything aside from a
932 943 * symbolic link.
933 944 *
934 945 * If the path is invalid then a negative value is returned. If the
935 946 * path exists and is a valid mount point path then 0 is returned.
936 947 * If the path doesn't exist return a positive value.
937 948 */
938 949 static int
939 950 valid_mount_point(zlog_t *zlogp, const char *path, const boolean_t leaf)
940 951 {
941 952 struct stat statbuf;
942 953 char respath[MAXPATHLEN];
943 954 int res;
944 955
945 956 if (lstat(path, &statbuf) != 0) {
946 957 if (errno == ENOENT)
947 958 return (1);
948 959 zerror(zlogp, B_TRUE, "can't stat %s", path);
949 960 return (-1);
950 961 }
951 962 if (S_ISLNK(statbuf.st_mode)) {
952 963 zerror(zlogp, B_FALSE, "%s is a symlink", path);
953 964 return (-1);
954 965 }
955 966 if (!leaf && !S_ISDIR(statbuf.st_mode)) {
956 967 zerror(zlogp, B_FALSE, "%s is not a directory", path);
957 968 return (-1);
958 969 }
959 970 if ((res = resolvepath(path, respath, sizeof (respath))) == -1) {
960 971 zerror(zlogp, B_TRUE, "unable to resolve path %s", path);
961 972 return (-1);
962 973 }
963 974 respath[res] = '\0';
964 975 if (strcmp(path, respath) != 0) {
965 976 /*
966 977 * We don't like ".."s, "."s, or "//"s throwing us off
967 978 */
968 979 zerror(zlogp, B_FALSE, "%s is not a canonical path", path);
969 980 return (-1);
970 981 }
971 982 return (0);
972 983 }
973 984
974 985 /*
975 986 * Validate a mount point path. A valid mount point path is an
976 987 * absolute path that either doesn't exist, or, if it does exists it
977 988 * must be an absolute canonical path that doesn't have any symbolic
978 989 * links in it. The target of a mount point path can be any filesystem
979 990 * object. (Different filesystems can support different mount points,
980 991 * for example "lofs" and "mntfs" both support files and directories
981 992 * while "ufs" just supports directories.)
982 993 *
983 994 * If the path is invalid then a negative value is returned. If the
984 995 * path exists and is a valid mount point path then 0 is returned.
985 996 * If the path doesn't exist return a positive value.
986 997 */
987 998 int
988 999 valid_mount_path(zlog_t *zlogp, const char *rootpath, const char *spec,
989 1000 const char *dir, const char *fstype)
990 1001 {
991 1002 char abspath[MAXPATHLEN], *slashp, *slashp_next;
992 1003 int rv;
993 1004
994 1005 /*
995 1006 * Sanity check the target mount point path.
996 1007 * It must be a non-null string that starts with a '/'.
997 1008 */
998 1009 if (dir[0] != '/') {
999 1010 /* Something went wrong. */
1000 1011 zerror(zlogp, B_FALSE, "invalid mount directory, "
1001 1012 "type: \"%s\", special: \"%s\", dir: \"%s\"",
1002 1013 fstype, spec, dir);
1003 1014 return (-1);
1004 1015 }
1005 1016
1006 1017 /*
1007 1018 * Join rootpath and dir. Make sure abspath ends with '/', this
1008 1019 * is added to all paths (even non-directory paths) to allow us
1009 1020 * to detect the end of paths below. If the path already ends
1010 1021 * in a '/', then that's ok too (although we'll fail the
1011 1022 * cannonical path check in valid_mount_point()).
1012 1023 */
1013 1024 if (snprintf(abspath, sizeof (abspath),
1014 1025 "%s%s/", rootpath, dir) >= sizeof (abspath)) {
1015 1026 zerror(zlogp, B_FALSE, "pathname %s%s is too long",
1016 1027 rootpath, dir);
1017 1028 return (-1);
1018 1029 }
1019 1030
1020 1031 /*
1021 1032 * Starting with rootpath, verify the mount path one component
1022 1033 * at a time. Continue until we've evaluated all of abspath.
1023 1034 */
1024 1035 slashp = &abspath[strlen(rootpath)];
1025 1036 assert(*slashp == '/');
1026 1037 do {
1027 1038 slashp_next = strchr(slashp + 1, '/');
1028 1039 *slashp = '\0';
1029 1040 if (slashp_next != NULL) {
1030 1041 /* This is an intermediary mount path component. */
1031 1042 rv = valid_mount_point(zlogp, abspath, B_FALSE);
1032 1043 } else {
1033 1044 /* This is the last component of the mount path. */
1034 1045 rv = valid_mount_point(zlogp, abspath, B_TRUE);
1035 1046 }
1036 1047 if (rv < 0)
1037 1048 return (rv);
1038 1049 *slashp = '/';
1039 1050 } while ((slashp = slashp_next) != NULL);
1040 1051 return (rv);
1041 1052 }
1042 1053
1043 1054 static int
1044 1055 mount_one_dev_device_cb(void *arg, const char *match, const char *name)
1045 1056 {
1046 1057 di_prof_t prof = arg;
1047 1058
1048 1059 if (name == NULL)
1049 1060 return (di_prof_add_dev(prof, match));
1050 1061 return (di_prof_add_map(prof, match, name));
1051 1062 }
1052 1063
1053 1064 static int
1054 1065 mount_one_dev_symlink_cb(void *arg, const char *source, const char *target)
1055 1066 {
1056 1067 di_prof_t prof = arg;
1057 1068
1058 1069 return (di_prof_add_symlink(prof, source, target));
1059 1070 }
1060 1071
1061 1072 int
1062 1073 vplat_get_iptype(zlog_t *zlogp, zone_iptype_t *iptypep)
1063 1074 {
1064 1075 zone_dochandle_t handle;
1065 1076
1066 1077 if ((handle = zonecfg_init_handle()) == NULL) {
1067 1078 zerror(zlogp, B_TRUE, "getting zone configuration handle");
1068 1079 return (-1);
1069 1080 }
1070 1081 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
1071 1082 zerror(zlogp, B_FALSE, "invalid configuration");
1072 1083 zonecfg_fini_handle(handle);
1073 1084 return (-1);
1074 1085 }
1075 1086 if (zonecfg_get_iptype(handle, iptypep) != Z_OK) {
1076 1087 zerror(zlogp, B_FALSE, "invalid ip-type configuration");
1077 1088 zonecfg_fini_handle(handle);
1078 1089 return (-1);
1079 1090 }
1080 1091 zonecfg_fini_handle(handle);
1081 1092 return (0);
1082 1093 }
1083 1094
1084 1095 /*
1085 1096 * Apply the standard lists of devices/symlinks/mappings and the user-specified
1086 1097 * list of devices (via zonecfg) to the /dev filesystem. The filesystem will
1087 1098 * use these as a profile/filter to determine what exists in /dev.
1088 1099 */
1089 1100 static int
1090 1101 mount_one_dev(zlog_t *zlogp, char *devpath, zone_mnt_t mount_cmd)
1091 1102 {
1092 1103 char brand[MAXNAMELEN];
1093 1104 zone_dochandle_t handle = NULL;
1094 1105 brand_handle_t bh = NULL;
1095 1106 struct zone_devtab ztab;
1096 1107 di_prof_t prof = NULL;
1097 1108 int err;
1098 1109 int retval = -1;
1099 1110 zone_iptype_t iptype;
1100 1111 const char *curr_iptype;
1101 1112
1102 1113 if (di_prof_init(devpath, &prof)) {
1103 1114 zerror(zlogp, B_TRUE, "failed to initialize profile");
1104 1115 goto cleanup;
1105 1116 }
1106 1117
1107 1118 /*
1108 1119 * Get a handle to the brand info for this zone.
1109 1120 * If we are mounting the zone, then we must always use the default
1110 1121 * brand device mounts.
1111 1122 */
1112 1123 if (ALT_MOUNT(mount_cmd)) {
1113 1124 (void) strlcpy(brand, default_brand, sizeof (brand));
1114 1125 } else {
1115 1126 (void) strlcpy(brand, brand_name, sizeof (brand));
1116 1127 }
1117 1128
1118 1129 if ((bh = brand_open(brand)) == NULL) {
1119 1130 zerror(zlogp, B_FALSE, "unable to determine zone brand");
1120 1131 goto cleanup;
1121 1132 }
1122 1133
1123 1134 if (vplat_get_iptype(zlogp, &iptype) < 0) {
1124 1135 zerror(zlogp, B_TRUE, "unable to determine ip-type");
1125 1136 goto cleanup;
1126 1137 }
1127 1138 switch (iptype) {
1128 1139 case ZS_SHARED:
1129 1140 curr_iptype = "shared";
1130 1141 break;
1131 1142 case ZS_EXCLUSIVE:
1132 1143 curr_iptype = "exclusive";
1133 1144 break;
1134 1145 }
1135 1146
1136 1147 if (brand_platform_iter_devices(bh, zone_name,
1137 1148 mount_one_dev_device_cb, prof, curr_iptype) != 0) {
1138 1149 zerror(zlogp, B_TRUE, "failed to add standard device");
1139 1150 goto cleanup;
1140 1151 }
1141 1152
1142 1153 if (brand_platform_iter_link(bh,
|
↓ open down ↓ |
969 lines elided |
↑ open up ↑ |
1143 1154 mount_one_dev_symlink_cb, prof) != 0) {
1144 1155 zerror(zlogp, B_TRUE, "failed to add standard symlink");
1145 1156 goto cleanup;
1146 1157 }
1147 1158
1148 1159 /* Add user-specified devices and directories */
1149 1160 if ((handle = zonecfg_init_handle()) == NULL) {
1150 1161 zerror(zlogp, B_FALSE, "can't initialize zone handle");
1151 1162 goto cleanup;
1152 1163 }
1153 - if (err = zonecfg_get_handle(zone_name, handle)) {
1164 + if ((err = zonecfg_get_handle(zone_name, handle)) != 0) {
1154 1165 zerror(zlogp, B_FALSE, "can't get handle for zone "
1155 1166 "%s: %s", zone_name, zonecfg_strerror(err));
1156 1167 goto cleanup;
1157 1168 }
1158 - if (err = zonecfg_setdevent(handle)) {
1169 + if ((err = zonecfg_setdevent(handle)) != 0) {
1159 1170 zerror(zlogp, B_FALSE, "%s: %s", zone_name,
1160 1171 zonecfg_strerror(err));
1161 1172 goto cleanup;
1162 1173 }
1163 1174 while (zonecfg_getdevent(handle, &ztab) == Z_OK) {
1164 1175 if (di_prof_add_dev(prof, ztab.zone_dev_match)) {
1165 1176 zerror(zlogp, B_TRUE, "failed to add "
1166 1177 "user-specified device");
1167 1178 goto cleanup;
1168 1179 }
1169 1180 }
1170 1181 (void) zonecfg_enddevent(handle);
1171 1182
1172 1183 /* Send profile to kernel */
1173 1184 if (di_prof_commit(prof)) {
1174 1185 zerror(zlogp, B_TRUE, "failed to commit profile");
1175 1186 goto cleanup;
1176 1187 }
1177 1188
1178 1189 retval = 0;
1179 1190
1180 1191 cleanup:
1181 1192 if (bh != NULL)
1182 1193 brand_close(bh);
1183 1194 if (handle != NULL)
1184 1195 zonecfg_fini_handle(handle);
1185 1196 if (prof)
1186 1197 di_prof_fini(prof);
1187 1198 return (retval);
1188 1199 }
1189 1200
1190 1201 static int
1191 1202 mount_one(zlog_t *zlogp, struct zone_fstab *fsptr, const char *rootpath,
1192 1203 zone_mnt_t mount_cmd)
1193 1204 {
1194 1205 char path[MAXPATHLEN];
1195 1206 char optstr[MAX_MNTOPT_STR];
1196 1207 zone_fsopt_t *optptr;
1197 1208 int rv;
1198 1209
1199 1210 if ((rv = valid_mount_path(zlogp, rootpath, fsptr->zone_fs_special,
1200 1211 fsptr->zone_fs_dir, fsptr->zone_fs_type)) < 0) {
1201 1212 zerror(zlogp, B_FALSE, "%s%s is not a valid mount point",
1202 1213 rootpath, fsptr->zone_fs_dir);
1203 1214 return (-1);
1204 1215 } else if (rv > 0) {
1205 1216 /* The mount point path doesn't exist, create it now. */
1206 1217 if (make_one_dir(zlogp, rootpath, fsptr->zone_fs_dir,
1207 1218 DEFAULT_DIR_MODE, DEFAULT_DIR_USER,
1208 1219 DEFAULT_DIR_GROUP) != 0) {
1209 1220 zerror(zlogp, B_FALSE, "failed to create mount point");
1210 1221 return (-1);
1211 1222 }
1212 1223
1213 1224 /*
1214 1225 * Now this might seem weird, but we need to invoke
1215 1226 * valid_mount_path() again. Why? Because it checks
1216 1227 * to make sure that the mount point path is canonical,
1217 1228 * which it can only do if the path exists, so now that
1218 1229 * we've created the path we have to verify it again.
1219 1230 */
1220 1231 if ((rv = valid_mount_path(zlogp, rootpath,
1221 1232 fsptr->zone_fs_special, fsptr->zone_fs_dir,
1222 1233 fsptr->zone_fs_type)) < 0) {
1223 1234 zerror(zlogp, B_FALSE,
1224 1235 "%s%s is not a valid mount point",
1225 1236 rootpath, fsptr->zone_fs_dir);
1226 1237 return (-1);
1227 1238 }
1228 1239 }
1229 1240
1230 1241 (void) snprintf(path, sizeof (path), "%s%s", rootpath,
1231 1242 fsptr->zone_fs_dir);
1232 1243
1233 1244 /*
1234 1245 * In general the strategy here is to do just as much verification as
1235 1246 * necessary to avoid crashing or otherwise doing something bad; if the
1236 1247 * administrator initiated the operation via zoneadm(1m), he'll get
1237 1248 * auto-verification which will let him know what's wrong. If he
1238 1249 * modifies the zone configuration of a running zone and doesn't attempt
1239 1250 * to verify that it's OK we won't crash but won't bother trying to be
1240 1251 * too helpful either. zoneadm verify is only a couple keystrokes away.
1241 1252 */
1242 1253 if (!zonecfg_valid_fs_type(fsptr->zone_fs_type)) {
1243 1254 zerror(zlogp, B_FALSE, "cannot mount %s on %s: "
1244 1255 "invalid file-system type %s", fsptr->zone_fs_special,
1245 1256 fsptr->zone_fs_dir, fsptr->zone_fs_type);
1246 1257 return (-1);
1247 1258 }
1248 1259
1249 1260 /*
1250 1261 * If we're looking at an alternate root environment, then construct
1251 1262 * read-only loopback mounts as necessary. Note that any special
1252 1263 * paths for lofs zone mounts in an alternate root must have
1253 1264 * already been pre-pended with any alternate root path by the
1254 1265 * time we get here.
1255 1266 */
1256 1267 if (zonecfg_in_alt_root()) {
1257 1268 struct stat64 st;
1258 1269
1259 1270 if (stat64(fsptr->zone_fs_special, &st) != -1 &&
1260 1271 S_ISBLK(st.st_mode)) {
1261 1272 /*
1262 1273 * If we're going to mount a block device we need
1263 1274 * to check if that device is already mounted
1264 1275 * somewhere else, and if so, do a lofs mount
1265 1276 * of the device instead of a direct mount
1266 1277 */
1267 1278 if (check_lofs_needed(zlogp, fsptr) == -1)
1268 1279 return (-1);
1269 1280 } else if (strcmp(fsptr->zone_fs_type, MNTTYPE_LOFS) == 0) {
1270 1281 /*
1271 1282 * For lofs mounts, the special node is inside the
1272 1283 * alternate root. We need lofs resolution for
1273 1284 * this case in order to get at the underlying
1274 1285 * read-write path.
1275 1286 */
1276 1287 resolve_lofs(zlogp, fsptr->zone_fs_special,
1277 1288 sizeof (fsptr->zone_fs_special));
1278 1289 }
1279 1290 }
1280 1291
1281 1292 /*
1282 1293 * Run 'fsck -m' if there's a device to fsck.
1283 1294 */
1284 1295 if (fsptr->zone_fs_raw[0] != '\0' &&
1285 1296 dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_raw) != 0) {
1286 1297 return (-1);
1287 1298 } else if (isregfile(fsptr->zone_fs_special) == 1 &&
1288 1299 dofsck(zlogp, fsptr->zone_fs_type, fsptr->zone_fs_special) != 0) {
1289 1300 return (-1);
1290 1301 }
1291 1302
1292 1303 /*
1293 1304 * Build up mount option string.
1294 1305 */
1295 1306 optstr[0] = '\0';
1296 1307 if (fsptr->zone_fs_options != NULL) {
1297 1308 (void) strlcpy(optstr, fsptr->zone_fs_options->zone_fsopt_opt,
1298 1309 sizeof (optstr));
1299 1310 for (optptr = fsptr->zone_fs_options->zone_fsopt_next;
1300 1311 optptr != NULL; optptr = optptr->zone_fsopt_next) {
1301 1312 (void) strlcat(optstr, ",", sizeof (optstr));
1302 1313 (void) strlcat(optstr, optptr->zone_fsopt_opt,
1303 1314 sizeof (optstr));
1304 1315 }
1305 1316 }
1306 1317
1307 1318 if ((rv = domount(zlogp, fsptr->zone_fs_type, optstr,
1308 1319 fsptr->zone_fs_special, path)) != 0)
1309 1320 return (rv);
1310 1321
1311 1322 /*
1312 1323 * The mount succeeded. If this was not a mount of /dev then
1313 1324 * we're done.
1314 1325 */
1315 1326 if (strcmp(fsptr->zone_fs_type, MNTTYPE_DEV) != 0)
1316 1327 return (0);
1317 1328
1318 1329 /*
1319 1330 * We just mounted an instance of a /dev filesystem, so now we
1320 1331 * need to configure it.
1321 1332 */
1322 1333 return (mount_one_dev(zlogp, path, mount_cmd));
1323 1334 }
1324 1335
1325 1336 static void
1326 1337 free_fs_data(struct zone_fstab *fsarray, uint_t nelem)
1327 1338 {
1328 1339 uint_t i;
1329 1340
1330 1341 if (fsarray == NULL)
1331 1342 return;
1332 1343 for (i = 0; i < nelem; i++)
1333 1344 zonecfg_free_fs_option_list(fsarray[i].zone_fs_options);
1334 1345 free(fsarray);
1335 1346 }
1336 1347
1337 1348 /*
1338 1349 * This function initiates the creation of a small Solaris Environment for
1339 1350 * scratch zone. The Environment creation process is split up into two
1340 1351 * functions(build_mounted_pre_var() and build_mounted_post_var()). It
1341 1352 * is done this way because:
1342 1353 * We need to have both /etc and /var in the root of the scratchzone.
1343 1354 * We loopback mount zone's own /etc and /var into the root of the
1344 1355 * scratch zone. Unlike /etc, /var can be a seperate filesystem. So we
1345 1356 * need to delay the mount of /var till the zone's root gets populated.
1346 1357 * So mounting of localdirs[](/etc and /var) have been moved to the
1347 1358 * build_mounted_post_var() which gets called only after the zone
1348 1359 * specific filesystems are mounted.
1349 1360 *
1350 1361 * Note that the scratch zone we set up for updating the zone (Z_MNT_UPDATE)
1351 1362 * does not loopback mount the zone's own /etc and /var into the root of the
1352 1363 * scratch zone.
1353 1364 */
1354 1365 static boolean_t
1355 1366 build_mounted_pre_var(zlog_t *zlogp, char *rootpath,
1356 1367 size_t rootlen, const char *zonepath, char *luroot, size_t lurootlen)
1357 1368 {
1358 1369 char tmp[MAXPATHLEN], fromdir[MAXPATHLEN];
1359 1370 const char **cpp;
1360 1371 static const char *mkdirs[] = {
1361 1372 "/system", "/system/contract", "/system/object", "/proc",
1362 1373 "/dev", "/tmp", "/a", NULL
1363 1374 };
1364 1375 char *altstr;
1365 1376 FILE *fp;
1366 1377 uuid_t uuid;
1367 1378
1368 1379 resolve_lofs(zlogp, rootpath, rootlen);
1369 1380 (void) snprintf(luroot, lurootlen, "%s/lu", zonepath);
1370 1381 resolve_lofs(zlogp, luroot, lurootlen);
1371 1382 (void) snprintf(tmp, sizeof (tmp), "%s/bin", luroot);
1372 1383 (void) symlink("./usr/bin", tmp);
1373 1384
1374 1385 /*
1375 1386 * These are mostly special mount points; not handled here. (See
1376 1387 * zone_mount_early.)
1377 1388 */
1378 1389 for (cpp = mkdirs; *cpp != NULL; cpp++) {
1379 1390 (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp);
1380 1391 if (mkdir(tmp, 0755) != 0) {
1381 1392 zerror(zlogp, B_TRUE, "cannot create %s", tmp);
1382 1393 return (B_FALSE);
1383 1394 }
1384 1395 }
1385 1396 /*
1386 1397 * This is here to support lucopy. If there's an instance of this same
1387 1398 * zone on the current running system, then we mount its root up as
1388 1399 * read-only inside the scratch zone.
1389 1400 */
1390 1401 (void) zonecfg_get_uuid(zone_name, uuid);
1391 1402 altstr = strdup(zonecfg_get_root());
1392 1403 if (altstr == NULL) {
1393 1404 zerror(zlogp, B_TRUE, "memory allocation failed");
1394 1405 return (B_FALSE);
1395 1406 }
1396 1407 zonecfg_set_root("");
1397 1408 (void) strlcpy(tmp, zone_name, sizeof (tmp));
1398 1409 (void) zonecfg_get_name_by_uuid(uuid, tmp, sizeof (tmp));
1399 1410 if (zone_get_rootpath(tmp, fromdir, sizeof (fromdir)) == Z_OK &&
1400 1411 strcmp(fromdir, rootpath) != 0) {
1401 1412 (void) snprintf(tmp, sizeof (tmp), "%s/b", luroot);
1402 1413 if (mkdir(tmp, 0755) != 0) {
1403 1414 zerror(zlogp, B_TRUE, "cannot create %s", tmp);
1404 1415 return (B_FALSE);
1405 1416 }
1406 1417 if (domount(zlogp, MNTTYPE_LOFS, RESOURCE_DEFAULT_OPTS, fromdir,
1407 1418 tmp) != 0) {
1408 1419 zerror(zlogp, B_TRUE, "cannot mount %s on %s", tmp,
1409 1420 fromdir);
1410 1421 return (B_FALSE);
1411 1422 }
1412 1423 }
1413 1424 zonecfg_set_root(altstr);
1414 1425 free(altstr);
1415 1426
1416 1427 if ((fp = zonecfg_open_scratch(luroot, B_TRUE)) == NULL) {
1417 1428 zerror(zlogp, B_TRUE, "cannot open zone mapfile");
1418 1429 return (B_FALSE);
1419 1430 }
1420 1431 (void) ftruncate(fileno(fp), 0);
1421 1432 if (zonecfg_add_scratch(fp, zone_name, kernzone, "/") == -1) {
1422 1433 zerror(zlogp, B_TRUE, "cannot add zone mapfile entry");
1423 1434 }
1424 1435 zonecfg_close_scratch(fp);
1425 1436 (void) snprintf(tmp, sizeof (tmp), "%s/a", luroot);
1426 1437 if (domount(zlogp, MNTTYPE_LOFS, "", rootpath, tmp) != 0)
1427 1438 return (B_FALSE);
1428 1439 (void) strlcpy(rootpath, tmp, rootlen);
1429 1440 return (B_TRUE);
1430 1441 }
1431 1442
1432 1443
1433 1444 static boolean_t
1434 1445 build_mounted_post_var(zlog_t *zlogp, zone_mnt_t mount_cmd, char *rootpath,
1435 1446 const char *luroot)
1436 1447 {
1437 1448 char tmp[MAXPATHLEN], fromdir[MAXPATHLEN];
1438 1449 const char **cpp;
1439 1450 const char **loopdirs;
1440 1451 const char **tmpdirs;
1441 1452 static const char *localdirs[] = {
1442 1453 "/etc", "/var", NULL
1443 1454 };
1444 1455 static const char *scr_loopdirs[] = {
1445 1456 "/etc/lib", "/etc/fs", "/lib", "/sbin", "/platform",
1446 1457 "/usr", NULL
1447 1458 };
1448 1459 static const char *upd_loopdirs[] = {
1449 1460 "/etc", "/kernel", "/lib", "/opt", "/platform", "/sbin",
1450 1461 "/usr", "/var", NULL
1451 1462 };
1452 1463 static const char *scr_tmpdirs[] = {
1453 1464 "/tmp", "/var/run", NULL
1454 1465 };
1455 1466 static const char *upd_tmpdirs[] = {
1456 1467 "/tmp", "/var/run", "/var/tmp", NULL
1457 1468 };
1458 1469 struct stat st;
1459 1470
1460 1471 if (mount_cmd == Z_MNT_SCRATCH) {
1461 1472 /*
1462 1473 * These are mounted read-write from the zone undergoing
1463 1474 * upgrade. We must be careful not to 'leak' things from the
1464 1475 * main system into the zone, and this accomplishes that goal.
1465 1476 */
1466 1477 for (cpp = localdirs; *cpp != NULL; cpp++) {
1467 1478 (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot,
1468 1479 *cpp);
1469 1480 (void) snprintf(fromdir, sizeof (fromdir), "%s%s",
1470 1481 rootpath, *cpp);
1471 1482 if (mkdir(tmp, 0755) != 0) {
1472 1483 zerror(zlogp, B_TRUE, "cannot create %s", tmp);
1473 1484 return (B_FALSE);
1474 1485 }
1475 1486 if (domount(zlogp, MNTTYPE_LOFS, "", fromdir, tmp)
1476 1487 != 0) {
1477 1488 zerror(zlogp, B_TRUE, "cannot mount %s on %s",
1478 1489 tmp, *cpp);
1479 1490 return (B_FALSE);
1480 1491 }
1481 1492 }
1482 1493 }
1483 1494
1484 1495 if (mount_cmd == Z_MNT_UPDATE)
1485 1496 loopdirs = upd_loopdirs;
1486 1497 else
1487 1498 loopdirs = scr_loopdirs;
1488 1499
1489 1500 /*
1490 1501 * These are things mounted read-only from the running system because
1491 1502 * they contain binaries that must match system.
1492 1503 */
1493 1504 for (cpp = loopdirs; *cpp != NULL; cpp++) {
1494 1505 (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp);
1495 1506 if (mkdir(tmp, 0755) != 0) {
1496 1507 if (errno != EEXIST) {
1497 1508 zerror(zlogp, B_TRUE, "cannot create %s", tmp);
1498 1509 return (B_FALSE);
1499 1510 }
1500 1511 if (lstat(tmp, &st) != 0) {
1501 1512 zerror(zlogp, B_TRUE, "cannot stat %s", tmp);
1502 1513 return (B_FALSE);
1503 1514 }
1504 1515 /*
1505 1516 * Ignore any non-directories encountered. These are
1506 1517 * things that have been converted into symlinks
1507 1518 * (/etc/fs and /etc/lib) and no longer need a lofs
1508 1519 * fixup.
1509 1520 */
1510 1521 if (!S_ISDIR(st.st_mode))
1511 1522 continue;
1512 1523 }
1513 1524 if (domount(zlogp, MNTTYPE_LOFS, RESOURCE_DEFAULT_OPTS, *cpp,
1514 1525 tmp) != 0) {
1515 1526 zerror(zlogp, B_TRUE, "cannot mount %s on %s", tmp,
1516 1527 *cpp);
1517 1528 return (B_FALSE);
1518 1529 }
1519 1530 }
1520 1531
1521 1532 if (mount_cmd == Z_MNT_UPDATE)
1522 1533 tmpdirs = upd_tmpdirs;
1523 1534 else
1524 1535 tmpdirs = scr_tmpdirs;
1525 1536
1526 1537 /*
1527 1538 * These are things with tmpfs mounted inside.
1528 1539 */
1529 1540 for (cpp = tmpdirs; *cpp != NULL; cpp++) {
1530 1541 (void) snprintf(tmp, sizeof (tmp), "%s%s", luroot, *cpp);
1531 1542 if (mount_cmd == Z_MNT_SCRATCH && mkdir(tmp, 0755) != 0 &&
1532 1543 errno != EEXIST) {
1533 1544 zerror(zlogp, B_TRUE, "cannot create %s", tmp);
1534 1545 return (B_FALSE);
1535 1546 }
1536 1547
1537 1548 /*
1538 1549 * We could set the mode for /tmp when we do the mkdir but
1539 1550 * since that can be modified by the umask we will just set
1540 1551 * the correct mode for /tmp now.
1541 1552 */
1542 1553 if (strcmp(*cpp, "/tmp") == 0 && chmod(tmp, 01777) != 0) {
1543 1554 zerror(zlogp, B_TRUE, "cannot chmod %s", tmp);
1544 1555 return (B_FALSE);
1545 1556 }
1546 1557
1547 1558 if (domount(zlogp, MNTTYPE_TMPFS, "", "swap", tmp) != 0) {
1548 1559 zerror(zlogp, B_TRUE, "cannot mount swap on %s", *cpp);
1549 1560 return (B_FALSE);
1550 1561 }
1551 1562 }
1552 1563 return (B_TRUE);
1553 1564 }
1554 1565
1555 1566 typedef struct plat_gmount_cb_data {
1556 1567 zlog_t *pgcd_zlogp;
1557 1568 struct zone_fstab **pgcd_fs_tab;
1558 1569 int *pgcd_num_fs;
1559 1570 } plat_gmount_cb_data_t;
1560 1571
1561 1572 /*
1562 1573 * plat_gmount_cb() is a callback function invoked by libbrand to iterate
1563 1574 * through all global brand platform mounts.
1564 1575 */
1565 1576 int
1566 1577 plat_gmount_cb(void *data, const char *spec, const char *dir,
1567 1578 const char *fstype, const char *opt)
1568 1579 {
1569 1580 plat_gmount_cb_data_t *cp = data;
1570 1581 zlog_t *zlogp = cp->pgcd_zlogp;
1571 1582 struct zone_fstab *fs_ptr = *cp->pgcd_fs_tab;
1572 1583 int num_fs = *cp->pgcd_num_fs;
1573 1584 struct zone_fstab *fsp, *tmp_ptr;
1574 1585
1575 1586 num_fs++;
1576 1587 if ((tmp_ptr = realloc(fs_ptr, num_fs * sizeof (*tmp_ptr))) == NULL) {
1577 1588 zerror(zlogp, B_TRUE, "memory allocation failed");
1578 1589 return (-1);
1579 1590 }
1580 1591
1581 1592 fs_ptr = tmp_ptr;
1582 1593 fsp = &fs_ptr[num_fs - 1];
1583 1594
1584 1595 /* update the callback struct passed in */
1585 1596 *cp->pgcd_fs_tab = fs_ptr;
1586 1597 *cp->pgcd_num_fs = num_fs;
1587 1598
1588 1599 fsp->zone_fs_raw[0] = '\0';
1589 1600 (void) strlcpy(fsp->zone_fs_special, spec,
1590 1601 sizeof (fsp->zone_fs_special));
1591 1602 (void) strlcpy(fsp->zone_fs_dir, dir, sizeof (fsp->zone_fs_dir));
1592 1603 (void) strlcpy(fsp->zone_fs_type, fstype, sizeof (fsp->zone_fs_type));
1593 1604 fsp->zone_fs_options = NULL;
1594 1605 if ((opt != NULL) &&
1595 1606 (zonecfg_add_fs_option(fsp, (char *)opt) != Z_OK)) {
1596 1607 zerror(zlogp, B_FALSE, "error adding property");
1597 1608 return (-1);
1598 1609 }
1599 1610
1600 1611 return (0);
1601 1612 }
1602 1613
1603 1614 static int
1604 1615 mount_filesystems_fsent(zone_dochandle_t handle, zlog_t *zlogp,
1605 1616 struct zone_fstab **fs_tabp, int *num_fsp, zone_mnt_t mount_cmd)
1606 1617 {
1607 1618 struct zone_fstab *tmp_ptr, *fs_ptr, *fsp, fstab;
1608 1619 int num_fs;
1609 1620
1610 1621 num_fs = *num_fsp;
1611 1622 fs_ptr = *fs_tabp;
1612 1623
1613 1624 if (zonecfg_setfsent(handle) != Z_OK) {
1614 1625 zerror(zlogp, B_FALSE, "invalid configuration");
1615 1626 return (-1);
1616 1627 }
1617 1628 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
1618 1629 /*
1619 1630 * ZFS filesystems will not be accessible under an alternate
1620 1631 * root, since the pool will not be known. Ignore them in this
1621 1632 * case.
1622 1633 */
1623 1634 if (ALT_MOUNT(mount_cmd) &&
1624 1635 strcmp(fstab.zone_fs_type, MNTTYPE_ZFS) == 0)
1625 1636 continue;
1626 1637
1627 1638 num_fs++;
1628 1639 if ((tmp_ptr = realloc(fs_ptr,
1629 1640 num_fs * sizeof (*tmp_ptr))) == NULL) {
1630 1641 zerror(zlogp, B_TRUE, "memory allocation failed");
1631 1642 (void) zonecfg_endfsent(handle);
1632 1643 return (-1);
1633 1644 }
1634 1645 /* update the pointers passed in */
1635 1646 *fs_tabp = tmp_ptr;
1636 1647 *num_fsp = num_fs;
1637 1648
1638 1649 fs_ptr = tmp_ptr;
1639 1650 fsp = &fs_ptr[num_fs - 1];
1640 1651 (void) strlcpy(fsp->zone_fs_dir,
1641 1652 fstab.zone_fs_dir, sizeof (fsp->zone_fs_dir));
1642 1653 (void) strlcpy(fsp->zone_fs_raw, fstab.zone_fs_raw,
1643 1654 sizeof (fsp->zone_fs_raw));
1644 1655 (void) strlcpy(fsp->zone_fs_type, fstab.zone_fs_type,
1645 1656 sizeof (fsp->zone_fs_type));
1646 1657 fsp->zone_fs_options = fstab.zone_fs_options;
1647 1658
1648 1659 /*
1649 1660 * For all lofs mounts, make sure that the 'special'
1650 1661 * entry points inside the alternate root. The
1651 1662 * source path for a lofs mount in a given zone needs
1652 1663 * to be relative to the root of the boot environment
1653 1664 * that contains the zone. Note that we don't do this
1654 1665 * for non-lofs mounts since they will have a device
1655 1666 * as a backing store and device paths must always be
1656 1667 * specified relative to the current boot environment.
1657 1668 */
1658 1669 fsp->zone_fs_special[0] = '\0';
1659 1670 if (strcmp(fsp->zone_fs_type, MNTTYPE_LOFS) == 0) {
1660 1671 (void) strlcat(fsp->zone_fs_special, zonecfg_get_root(),
1661 1672 sizeof (fsp->zone_fs_special));
1662 1673 }
1663 1674 (void) strlcat(fsp->zone_fs_special, fstab.zone_fs_special,
|
↓ open down ↓ |
495 lines elided |
↑ open up ↑ |
1664 1675 sizeof (fsp->zone_fs_special));
1665 1676 }
1666 1677 (void) zonecfg_endfsent(handle);
1667 1678 return (0);
1668 1679 }
1669 1680
1670 1681 static int
1671 1682 mount_filesystems(zlog_t *zlogp, zone_mnt_t mount_cmd)
1672 1683 {
1673 1684 char rootpath[MAXPATHLEN];
1674 - char zonepath[MAXPATHLEN];
1675 1685 char brand[MAXNAMELEN];
1676 1686 char luroot[MAXPATHLEN];
1677 1687 int i, num_fs = 0;
1678 1688 struct zone_fstab *fs_ptr = NULL;
1679 1689 zone_dochandle_t handle = NULL;
1680 1690 zone_state_t zstate;
1681 1691 brand_handle_t bh;
1682 1692 plat_gmount_cb_data_t cb;
1683 1693
1684 1694 if (zone_get_state(zone_name, &zstate) != Z_OK ||
1685 1695 (zstate != ZONE_STATE_READY && zstate != ZONE_STATE_MOUNTED)) {
1686 1696 zerror(zlogp, B_FALSE,
1687 1697 "zone must be in '%s' or '%s' state to mount file-systems",
1688 1698 zone_state_str(ZONE_STATE_READY),
1689 1699 zone_state_str(ZONE_STATE_MOUNTED));
1690 1700 goto bad;
1691 1701 }
1692 1702
1693 - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
1694 - zerror(zlogp, B_TRUE, "unable to determine zone path");
1695 - goto bad;
1696 - }
1697 -
1698 1703 if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
1699 1704 zerror(zlogp, B_TRUE, "unable to determine zone root");
1700 1705 goto bad;
1701 1706 }
1702 1707
1703 1708 if ((handle = zonecfg_init_handle()) == NULL) {
1704 1709 zerror(zlogp, B_TRUE, "getting zone configuration handle");
1705 1710 goto bad;
1706 1711 }
1707 1712 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK ||
1708 1713 zonecfg_setfsent(handle) != Z_OK) {
1709 1714 zerror(zlogp, B_FALSE, "invalid configuration");
1710 1715 goto bad;
1711 1716 }
1712 1717
1713 1718 /*
1714 1719 * If we are mounting the zone, then we must always use the default
1715 1720 * brand global mounts.
1716 1721 */
1717 1722 if (ALT_MOUNT(mount_cmd)) {
1718 1723 (void) strlcpy(brand, default_brand, sizeof (brand));
1719 1724 } else {
1720 1725 (void) strlcpy(brand, brand_name, sizeof (brand));
1721 1726 }
1722 1727
1723 1728 /* Get a handle to the brand info for this zone */
1724 1729 if ((bh = brand_open(brand)) == NULL) {
1725 1730 zerror(zlogp, B_FALSE, "unable to determine zone brand");
1726 1731 zonecfg_fini_handle(handle);
1727 1732 return (-1);
1728 1733 }
1729 1734
1730 1735 /*
1731 1736 * Get the list of global filesystems to mount from the brand
1732 1737 * configuration.
1733 1738 */
1734 1739 cb.pgcd_zlogp = zlogp;
1735 1740 cb.pgcd_fs_tab = &fs_ptr;
1736 1741 cb.pgcd_num_fs = &num_fs;
1737 1742 if (brand_platform_iter_gmounts(bh, zone_name, zonepath,
1738 1743 plat_gmount_cb, &cb) != 0) {
1739 1744 zerror(zlogp, B_FALSE, "unable to mount filesystems");
1740 1745 brand_close(bh);
1741 1746 zonecfg_fini_handle(handle);
1742 1747 return (-1);
1743 1748 }
1744 1749 brand_close(bh);
1745 1750
1746 1751 /*
1747 1752 * Iterate through the rest of the filesystems. Sort them all,
1748 1753 * then mount them in sorted order. This is to make sure the
1749 1754 * higher level directories (e.g., /usr) get mounted before
1750 1755 * any beneath them (e.g., /usr/local).
1751 1756 */
1752 1757 if (mount_filesystems_fsent(handle, zlogp, &fs_ptr, &num_fs,
1753 1758 mount_cmd) != 0)
1754 1759 goto bad;
1755 1760
1756 1761 zonecfg_fini_handle(handle);
1757 1762 handle = NULL;
1758 1763
1759 1764 /*
1760 1765 * Normally when we mount a zone all the zone filesystems
1761 1766 * get mounted relative to rootpath, which is usually
1762 1767 * <zonepath>/root. But when mounting a zone for administration
1763 1768 * purposes via the zone "mount" state, build_mounted_pre_var()
1764 1769 * updates rootpath to be <zonepath>/lu/a so we'll mount all
1765 1770 * the zones filesystems there instead.
1766 1771 *
1767 1772 * build_mounted_pre_var() and build_mounted_post_var() will
1768 1773 * also do some extra work to create directories and lofs mount
1769 1774 * a bunch of global zone file system paths into <zonepath>/lu.
1770 1775 *
1771 1776 * This allows us to be able to enter the zone (now rooted at
1772 1777 * <zonepath>/lu) and run the upgrade/patch tools that are in the
1773 1778 * global zone and have them upgrade the to-be-modified zone's
1774 1779 * files mounted on /a. (Which mirrors the existing standard
1775 1780 * upgrade environment.)
1776 1781 *
1777 1782 * There is of course one catch. When doing the upgrade
1778 1783 * we need <zoneroot>/lu/dev to be the /dev filesystem
1779 1784 * for the zone and we don't want to have any /dev filesystem
1780 1785 * mounted at <zoneroot>/lu/a/dev. Since /dev is specified
1781 1786 * as a normal zone filesystem by default we'll try to mount
1782 1787 * it at <zoneroot>/lu/a/dev, so we have to detect this
1783 1788 * case and instead mount it at <zoneroot>/lu/dev.
1784 1789 *
1785 1790 * All this work is done in three phases:
1786 1791 * 1) Create and populate lu directory (build_mounted_pre_var()).
1787 1792 * 2) Mount the required filesystems as per the zone configuration.
|
↓ open down ↓ |
80 lines elided |
↑ open up ↑ |
1788 1793 * 3) Set up the rest of the scratch zone environment
1789 1794 * (build_mounted_post_var()).
1790 1795 */
1791 1796 if (ALT_MOUNT(mount_cmd) && !build_mounted_pre_var(zlogp,
1792 1797 rootpath, sizeof (rootpath), zonepath, luroot, sizeof (luroot)))
1793 1798 goto bad;
1794 1799
1795 1800 qsort(fs_ptr, num_fs, sizeof (*fs_ptr), fs_compare);
1796 1801
1797 1802 for (i = 0; i < num_fs; i++) {
1798 - if (ALT_MOUNT(mount_cmd) &&
1799 - strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
1800 - size_t slen = strlen(rootpath) - 2;
1803 + if (ALT_MOUNT(mount_cmd)) {
1804 + if (strcmp(fs_ptr[i].zone_fs_dir, "/dev") == 0) {
1805 + size_t slen = strlen(rootpath) - 2;
1801 1806
1802 - /*
1803 - * By default we'll try to mount /dev as /a/dev
1804 - * but /dev is special and always goes at the top
1805 - * so strip the trailing '/a' from the rootpath.
1806 - */
1807 - assert(strcmp(&rootpath[slen], "/a") == 0);
1808 - rootpath[slen] = '\0';
1809 - if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd)
1810 - != 0)
1811 - goto bad;
1812 - rootpath[slen] = '/';
1813 - continue;
1807 + /*
1808 + * By default we'll try to mount /dev
1809 + * as /a/dev but /dev is special and
1810 + * always goes at the top so strip the
1811 + * trailing '/a' from the rootpath.
1812 + */
1813 + assert(strcmp(&rootpath[slen], "/a") == 0);
1814 + rootpath[slen] = '\0';
1815 + if (mount_one(zlogp, &fs_ptr[i], rootpath,
1816 + mount_cmd) != 0)
1817 + goto bad;
1818 + rootpath[slen] = '/';
1819 + continue;
1820 + } else if (strcmp(brand_name, default_brand) != 0) {
1821 + /*
1822 + * If mounting non-native brand, skip
1823 + * mounting global mounts and
1824 + * filesystem entries since they are
1825 + * only needed for native pkg upgrade
1826 + * tools.
1827 + *
1828 + * The only exception right now is
1829 + * /dev (handled above), which is
1830 + * needed in the luroot in order to
1831 + * zlogin -S into the zone.
1832 + */
1833 + continue;
1834 + }
1814 1835 }
1836 +
1815 1837 if (mount_one(zlogp, &fs_ptr[i], rootpath, mount_cmd) != 0)
1816 1838 goto bad;
1817 1839 }
1818 1840 if (ALT_MOUNT(mount_cmd) &&
1819 1841 !build_mounted_post_var(zlogp, mount_cmd, rootpath, luroot))
1820 1842 goto bad;
1821 1843
1822 1844 /*
1823 1845 * For Trusted Extensions cross-mount each lower level /export/home
1824 1846 */
1825 1847 if (mount_cmd == Z_MNT_BOOT &&
1826 1848 tsol_mounts(zlogp, zone_name, rootpath) != 0)
1827 1849 goto bad;
1828 1850
1829 1851 free_fs_data(fs_ptr, num_fs);
1830 1852
1831 1853 /*
1832 1854 * Everything looks fine.
1833 1855 */
1834 1856 return (0);
1835 1857
1836 1858 bad:
1837 1859 if (handle != NULL)
1838 1860 zonecfg_fini_handle(handle);
1839 1861 free_fs_data(fs_ptr, num_fs);
1840 1862 return (-1);
1841 1863 }
1842 1864
1843 1865 /* caller makes sure neither parameter is NULL */
1844 1866 static int
1845 1867 addr2netmask(char *prefixstr, int maxprefixlen, uchar_t *maskstr)
1846 1868 {
1847 1869 int prefixlen;
1848 1870
1849 1871 prefixlen = atoi(prefixstr);
1850 1872 if (prefixlen < 0 || prefixlen > maxprefixlen)
1851 1873 return (1);
1852 1874 while (prefixlen > 0) {
1853 1875 if (prefixlen >= 8) {
1854 1876 *maskstr++ = 0xFF;
1855 1877 prefixlen -= 8;
1856 1878 continue;
1857 1879 }
1858 1880 *maskstr |= 1 << (8 - prefixlen);
1859 1881 prefixlen--;
1860 1882 }
1861 1883 return (0);
1862 1884 }
1863 1885
1864 1886 /*
1865 1887 * Tear down all interfaces belonging to the given zone. This should
1866 1888 * be called with the zone in a state other than "running", so that
1867 1889 * interfaces can't be assigned to the zone after this returns.
1868 1890 *
1869 1891 * If anything goes wrong, log an error message and return an error.
1870 1892 */
1871 1893 static int
1872 1894 unconfigure_shared_network_interfaces(zlog_t *zlogp, zoneid_t zone_id)
1873 1895 {
1874 1896 struct lifnum lifn;
1875 1897 struct lifconf lifc;
1876 1898 struct lifreq *lifrp, lifrl;
1877 1899 int64_t lifc_flags = LIFC_NOXMIT | LIFC_ALLZONES;
1878 1900 int num_ifs, s, i, ret_code = 0;
1879 1901 uint_t bufsize;
1880 1902 char *buf = NULL;
1881 1903
1882 1904 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1883 1905 zerror(zlogp, B_TRUE, "could not get socket");
1884 1906 ret_code = -1;
1885 1907 goto bad;
1886 1908 }
1887 1909 lifn.lifn_family = AF_UNSPEC;
1888 1910 lifn.lifn_flags = (int)lifc_flags;
1889 1911 if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
1890 1912 zerror(zlogp, B_TRUE,
1891 1913 "could not determine number of network interfaces");
1892 1914 ret_code = -1;
1893 1915 goto bad;
1894 1916 }
1895 1917 num_ifs = lifn.lifn_count;
1896 1918 bufsize = num_ifs * sizeof (struct lifreq);
1897 1919 if ((buf = malloc(bufsize)) == NULL) {
1898 1920 zerror(zlogp, B_TRUE, "memory allocation failed");
1899 1921 ret_code = -1;
1900 1922 goto bad;
1901 1923 }
1902 1924 lifc.lifc_family = AF_UNSPEC;
1903 1925 lifc.lifc_flags = (int)lifc_flags;
1904 1926 lifc.lifc_len = bufsize;
1905 1927 lifc.lifc_buf = buf;
1906 1928 if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
1907 1929 zerror(zlogp, B_TRUE, "could not get configured network "
1908 1930 "interfaces");
1909 1931 ret_code = -1;
1910 1932 goto bad;
1911 1933 }
1912 1934 lifrp = lifc.lifc_req;
1913 1935 for (i = lifc.lifc_len / sizeof (struct lifreq); i > 0; i--, lifrp++) {
1914 1936 (void) close(s);
1915 1937 if ((s = socket(lifrp->lifr_addr.ss_family, SOCK_DGRAM, 0)) <
1916 1938 0) {
1917 1939 zerror(zlogp, B_TRUE, "%s: could not get socket",
1918 1940 lifrl.lifr_name);
1919 1941 ret_code = -1;
1920 1942 continue;
1921 1943 }
1922 1944 (void) memset(&lifrl, 0, sizeof (lifrl));
1923 1945 (void) strncpy(lifrl.lifr_name, lifrp->lifr_name,
1924 1946 sizeof (lifrl.lifr_name));
1925 1947 if (ioctl(s, SIOCGLIFZONE, (caddr_t)&lifrl) < 0) {
1926 1948 if (errno == ENXIO)
1927 1949 /*
1928 1950 * Interface may have been removed by admin or
1929 1951 * another zone halting.
1930 1952 */
1931 1953 continue;
1932 1954 zerror(zlogp, B_TRUE,
1933 1955 "%s: could not determine the zone to which this "
1934 1956 "network interface is bound", lifrl.lifr_name);
1935 1957 ret_code = -1;
1936 1958 continue;
1937 1959 }
1938 1960 if (lifrl.lifr_zoneid == zone_id) {
1939 1961 if (ioctl(s, SIOCLIFREMOVEIF, (caddr_t)&lifrl) < 0) {
1940 1962 zerror(zlogp, B_TRUE,
1941 1963 "%s: could not remove network interface",
1942 1964 lifrl.lifr_name);
1943 1965 ret_code = -1;
1944 1966 continue;
1945 1967 }
1946 1968 }
1947 1969 }
1948 1970 bad:
1949 1971 if (s > 0)
1950 1972 (void) close(s);
1951 1973 if (buf)
1952 1974 free(buf);
1953 1975 return (ret_code);
1954 1976 }
1955 1977
1956 1978 static union sockunion {
1957 1979 struct sockaddr sa;
1958 1980 struct sockaddr_in sin;
1959 1981 struct sockaddr_dl sdl;
1960 1982 struct sockaddr_in6 sin6;
1961 1983 } so_dst, so_ifp;
1962 1984
1963 1985 static struct {
1964 1986 struct rt_msghdr hdr;
1965 1987 char space[512];
1966 1988 } rtmsg;
1967 1989
1968 1990 static int
1969 1991 salen(struct sockaddr *sa)
1970 1992 {
1971 1993 switch (sa->sa_family) {
1972 1994 case AF_INET:
1973 1995 return (sizeof (struct sockaddr_in));
1974 1996 case AF_LINK:
1975 1997 return (sizeof (struct sockaddr_dl));
1976 1998 case AF_INET6:
1977 1999 return (sizeof (struct sockaddr_in6));
1978 2000 default:
1979 2001 return (sizeof (struct sockaddr));
1980 2002 }
1981 2003 }
1982 2004
1983 2005 #define ROUNDUP_LONG(a) \
1984 2006 ((a) > 0 ? (1 + (((a) - 1) | (sizeof (long) - 1))) : sizeof (long))
1985 2007
1986 2008 /*
1987 2009 * Look up which zone is using a given IP address. The address in question
1988 2010 * is expected to have been stuffed into the structure to which lifr points
1989 2011 * via a previous SIOCGLIFADDR ioctl().
1990 2012 *
1991 2013 * This is done using black router socket magic.
1992 2014 *
1993 2015 * Return the name of the zone on success or NULL on failure.
1994 2016 *
1995 2017 * This is a lot of code for a simple task; a new ioctl request to take care
1996 2018 * of this might be a useful RFE.
1997 2019 */
1998 2020
1999 2021 static char *
2000 2022 who_is_using(zlog_t *zlogp, struct lifreq *lifr)
2001 2023 {
2002 2024 static char answer[ZONENAME_MAX];
2003 2025 pid_t pid;
2004 2026 int s, rlen, l, i;
2005 2027 char *cp = rtmsg.space;
2006 2028 struct sockaddr_dl *ifp = NULL;
2007 2029 struct sockaddr *sa;
2008 2030 char save_if_name[LIFNAMSIZ];
2009 2031
2010 2032 answer[0] = '\0';
2011 2033
2012 2034 pid = getpid();
2013 2035 if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
2014 2036 zerror(zlogp, B_TRUE, "could not get routing socket");
2015 2037 return (NULL);
2016 2038 }
2017 2039
2018 2040 if (lifr->lifr_addr.ss_family == AF_INET) {
2019 2041 struct sockaddr_in *sin4;
2020 2042
2021 2043 so_dst.sa.sa_family = AF_INET;
2022 2044 sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
2023 2045 so_dst.sin.sin_addr = sin4->sin_addr;
2024 2046 } else {
2025 2047 struct sockaddr_in6 *sin6;
2026 2048
2027 2049 so_dst.sa.sa_family = AF_INET6;
2028 2050 sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
2029 2051 so_dst.sin6.sin6_addr = sin6->sin6_addr;
2030 2052 }
2031 2053
2032 2054 so_ifp.sa.sa_family = AF_LINK;
2033 2055
2034 2056 (void) memset(&rtmsg, 0, sizeof (rtmsg));
2035 2057 rtmsg.hdr.rtm_type = RTM_GET;
2036 2058 rtmsg.hdr.rtm_flags = RTF_UP | RTF_HOST;
2037 2059 rtmsg.hdr.rtm_version = RTM_VERSION;
2038 2060 rtmsg.hdr.rtm_seq = ++rts_seqno;
2039 2061 rtmsg.hdr.rtm_addrs = RTA_IFP | RTA_DST;
2040 2062
2041 2063 l = ROUNDUP_LONG(salen(&so_dst.sa));
2042 2064 (void) memmove(cp, &(so_dst), l);
2043 2065 cp += l;
2044 2066 l = ROUNDUP_LONG(salen(&so_ifp.sa));
2045 2067 (void) memmove(cp, &(so_ifp), l);
2046 2068 cp += l;
2047 2069
2048 2070 rtmsg.hdr.rtm_msglen = l = cp - (char *)&rtmsg;
2049 2071
2050 2072 if ((rlen = write(s, &rtmsg, l)) < 0) {
2051 2073 zerror(zlogp, B_TRUE, "writing to routing socket");
2052 2074 return (NULL);
2053 2075 } else if (rlen < (int)rtmsg.hdr.rtm_msglen) {
2054 2076 zerror(zlogp, B_TRUE,
2055 2077 "write to routing socket got only %d for len\n", rlen);
2056 2078 return (NULL);
2057 2079 }
2058 2080 do {
2059 2081 l = read(s, &rtmsg, sizeof (rtmsg));
2060 2082 } while (l > 0 && (rtmsg.hdr.rtm_seq != rts_seqno ||
2061 2083 rtmsg.hdr.rtm_pid != pid));
2062 2084 if (l < 0) {
2063 2085 zerror(zlogp, B_TRUE, "reading from routing socket");
2064 2086 return (NULL);
2065 2087 }
2066 2088
2067 2089 if (rtmsg.hdr.rtm_version != RTM_VERSION) {
2068 2090 zerror(zlogp, B_FALSE,
2069 2091 "routing message version %d not understood",
2070 2092 rtmsg.hdr.rtm_version);
2071 2093 return (NULL);
2072 2094 }
2073 2095 if (rtmsg.hdr.rtm_msglen != (ushort_t)l) {
2074 2096 zerror(zlogp, B_FALSE, "message length mismatch, "
2075 2097 "expected %d bytes, returned %d bytes",
2076 2098 rtmsg.hdr.rtm_msglen, l);
2077 2099 return (NULL);
2078 2100 }
2079 2101 if (rtmsg.hdr.rtm_errno != 0) {
2080 2102 errno = rtmsg.hdr.rtm_errno;
2081 2103 zerror(zlogp, B_TRUE, "RTM_GET routing socket message");
2082 2104 return (NULL);
2083 2105 }
2084 2106 if ((rtmsg.hdr.rtm_addrs & RTA_IFP) == 0) {
2085 2107 zerror(zlogp, B_FALSE, "network interface not found");
2086 2108 return (NULL);
2087 2109 }
2088 2110 cp = ((char *)(&rtmsg.hdr + 1));
2089 2111 for (i = 1; i != 0; i <<= 1) {
2090 2112 /* LINTED E_BAD_PTR_CAST_ALIGN */
2091 2113 sa = (struct sockaddr *)cp;
2092 2114 if (i != RTA_IFP) {
2093 2115 if ((i & rtmsg.hdr.rtm_addrs) != 0)
2094 2116 cp += ROUNDUP_LONG(salen(sa));
2095 2117 continue;
2096 2118 }
2097 2119 if (sa->sa_family == AF_LINK &&
2098 2120 ((struct sockaddr_dl *)sa)->sdl_nlen != 0)
2099 2121 ifp = (struct sockaddr_dl *)sa;
2100 2122 break;
2101 2123 }
2102 2124 if (ifp == NULL) {
2103 2125 zerror(zlogp, B_FALSE, "network interface could not be "
2104 2126 "determined");
2105 2127 return (NULL);
2106 2128 }
2107 2129
2108 2130 /*
2109 2131 * We need to set the I/F name to what we got above, then do the
2110 2132 * appropriate ioctl to get its zone name. But lifr->lifr_name is
2111 2133 * used by the calling function to do a REMOVEIF, so if we leave the
2112 2134 * "good" zone's I/F name in place, *that* I/F will be removed instead
2113 2135 * of the bad one. So we save the old (bad) I/F name before over-
2114 2136 * writing it and doing the ioctl, then restore it after the ioctl.
2115 2137 */
2116 2138 (void) strlcpy(save_if_name, lifr->lifr_name, sizeof (save_if_name));
2117 2139 (void) strncpy(lifr->lifr_name, ifp->sdl_data, ifp->sdl_nlen);
2118 2140 lifr->lifr_name[ifp->sdl_nlen] = '\0';
2119 2141 i = ioctl(s, SIOCGLIFZONE, lifr);
2120 2142 (void) strlcpy(lifr->lifr_name, save_if_name, sizeof (save_if_name));
2121 2143 if (i < 0) {
2122 2144 zerror(zlogp, B_TRUE,
2123 2145 "%s: could not determine the zone network interface "
2124 2146 "belongs to", lifr->lifr_name);
2125 2147 return (NULL);
2126 2148 }
2127 2149 if (getzonenamebyid(lifr->lifr_zoneid, answer, sizeof (answer)) < 0)
2128 2150 (void) snprintf(answer, sizeof (answer), "%d",
2129 2151 lifr->lifr_zoneid);
2130 2152
2131 2153 if (strlen(answer) > 0)
2132 2154 return (answer);
2133 2155 return (NULL);
2134 2156 }
2135 2157
2136 2158 /*
2137 2159 * Configures a single interface: a new virtual interface is added, based on
2138 2160 * the physical interface nwiftabptr->zone_nwif_physical, with the address
2139 2161 * specified in nwiftabptr->zone_nwif_address, for zone zone_id. Note that
2140 2162 * the "address" can be an IPv6 address (with a /prefixlength required), an
2141 2163 * IPv4 address (with a /prefixlength optional), or a name; for the latter,
2142 2164 * an IPv4 name-to-address resolution will be attempted.
2143 2165 *
2144 2166 * If anything goes wrong, we log an detailed error message, attempt to tear
2145 2167 * down whatever we set up and return an error.
2146 2168 */
2147 2169 static int
2148 2170 configure_one_interface(zlog_t *zlogp, zoneid_t zone_id,
2149 2171 struct zone_nwiftab *nwiftabptr)
2150 2172 {
2151 2173 struct lifreq lifr;
2152 2174 struct sockaddr_in netmask4;
2153 2175 struct sockaddr_in6 netmask6;
2154 2176 struct sockaddr_storage laddr;
2155 2177 struct in_addr in4;
2156 2178 sa_family_t af;
2157 2179 char *slashp = strchr(nwiftabptr->zone_nwif_address, '/');
2158 2180 int s;
2159 2181 boolean_t got_netmask = B_FALSE;
2160 2182 boolean_t is_loopback = B_FALSE;
2161 2183 char addrstr4[INET_ADDRSTRLEN];
2162 2184 int res;
2163 2185
2164 2186 res = zonecfg_valid_net_address(nwiftabptr->zone_nwif_address, &lifr);
2165 2187 if (res != Z_OK) {
2166 2188 zerror(zlogp, B_FALSE, "%s: %s", zonecfg_strerror(res),
2167 2189 nwiftabptr->zone_nwif_address);
2168 2190 return (-1);
2169 2191 }
2170 2192 af = lifr.lifr_addr.ss_family;
2171 2193 if (af == AF_INET)
2172 2194 in4 = ((struct sockaddr_in *)(&lifr.lifr_addr))->sin_addr;
2173 2195 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
2174 2196 zerror(zlogp, B_TRUE, "could not get socket");
2175 2197 return (-1);
2176 2198 }
2177 2199
2178 2200 /*
2179 2201 * This is a similar kind of "hack" like in addif() to get around
2180 2202 * the problem of SIOCLIFADDIF. The problem is that this ioctl
2181 2203 * does not include the netmask when adding a logical interface.
2182 2204 * To get around this problem, we first add the logical interface
2183 2205 * with a 0 address. After that, we set the netmask if provided.
2184 2206 * Finally we set the interface address.
2185 2207 */
2186 2208 laddr = lifr.lifr_addr;
2187 2209 (void) strlcpy(lifr.lifr_name, nwiftabptr->zone_nwif_physical,
2188 2210 sizeof (lifr.lifr_name));
2189 2211 (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr));
2190 2212
2191 2213 if (ioctl(s, SIOCLIFADDIF, (caddr_t)&lifr) < 0) {
2192 2214 /*
2193 2215 * Here, we know that the interface can't be brought up.
2194 2216 * A similar warning message was already printed out to
2195 2217 * the console by zoneadm(1M) so instead we log the
2196 2218 * message to syslog and continue.
2197 2219 */
2198 2220 zerror(&logsys, B_TRUE, "WARNING: skipping network interface "
2199 2221 "'%s' which may not be present/plumbed in the "
2200 2222 "global zone.", lifr.lifr_name);
2201 2223 (void) close(s);
2202 2224 return (Z_OK);
2203 2225 }
2204 2226
2205 2227 /* Preserve literal IPv4 address for later potential printing. */
2206 2228 if (af == AF_INET)
2207 2229 (void) inet_ntop(AF_INET, &in4, addrstr4, INET_ADDRSTRLEN);
2208 2230
2209 2231 lifr.lifr_zoneid = zone_id;
2210 2232 if (ioctl(s, SIOCSLIFZONE, (caddr_t)&lifr) < 0) {
2211 2233 zerror(zlogp, B_TRUE, "%s: could not place network interface "
2212 2234 "into zone", lifr.lifr_name);
2213 2235 goto bad;
2214 2236 }
2215 2237
2216 2238 /*
2217 2239 * Loopback interface will use the default netmask assigned, if no
2218 2240 * netmask is found.
2219 2241 */
2220 2242 if (strcmp(nwiftabptr->zone_nwif_physical, "lo0") == 0) {
2221 2243 is_loopback = B_TRUE;
2222 2244 }
2223 2245 if (af == AF_INET) {
2224 2246 /*
2225 2247 * The IPv4 netmask can be determined either
2226 2248 * directly if a prefix length was supplied with
2227 2249 * the address or via the netmasks database. Not
2228 2250 * being able to determine it is a common failure,
2229 2251 * but it often is not fatal to operation of the
2230 2252 * interface. In that case, a warning will be
2231 2253 * printed after the rest of the interface's
2232 2254 * parameters have been configured.
2233 2255 */
2234 2256 (void) memset(&netmask4, 0, sizeof (netmask4));
2235 2257 if (slashp != NULL) {
2236 2258 if (addr2netmask(slashp + 1, V4_ADDR_LEN,
2237 2259 (uchar_t *)&netmask4.sin_addr) != 0) {
2238 2260 *slashp = '/';
2239 2261 zerror(zlogp, B_FALSE,
2240 2262 "%s: invalid prefix length in %s",
2241 2263 lifr.lifr_name,
2242 2264 nwiftabptr->zone_nwif_address);
2243 2265 goto bad;
2244 2266 }
2245 2267 got_netmask = B_TRUE;
2246 2268 } else if (getnetmaskbyaddr(in4,
2247 2269 &netmask4.sin_addr) == 0) {
2248 2270 got_netmask = B_TRUE;
2249 2271 }
2250 2272 if (got_netmask) {
2251 2273 netmask4.sin_family = af;
2252 2274 (void) memcpy(&lifr.lifr_addr, &netmask4,
2253 2275 sizeof (netmask4));
2254 2276 }
2255 2277 } else {
2256 2278 (void) memset(&netmask6, 0, sizeof (netmask6));
2257 2279 if (addr2netmask(slashp + 1, V6_ADDR_LEN,
2258 2280 (uchar_t *)&netmask6.sin6_addr) != 0) {
2259 2281 *slashp = '/';
2260 2282 zerror(zlogp, B_FALSE,
2261 2283 "%s: invalid prefix length in %s",
2262 2284 lifr.lifr_name,
2263 2285 nwiftabptr->zone_nwif_address);
2264 2286 goto bad;
2265 2287 }
2266 2288 got_netmask = B_TRUE;
2267 2289 netmask6.sin6_family = af;
2268 2290 (void) memcpy(&lifr.lifr_addr, &netmask6,
2269 2291 sizeof (netmask6));
2270 2292 }
2271 2293 if (got_netmask &&
2272 2294 ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) {
2273 2295 zerror(zlogp, B_TRUE, "%s: could not set netmask",
2274 2296 lifr.lifr_name);
2275 2297 goto bad;
2276 2298 }
2277 2299
2278 2300 /* Set the interface address */
2279 2301 lifr.lifr_addr = laddr;
2280 2302 if (ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr) < 0) {
2281 2303 zerror(zlogp, B_TRUE,
2282 2304 "%s: could not set IP address to %s",
2283 2305 lifr.lifr_name, nwiftabptr->zone_nwif_address);
2284 2306 goto bad;
2285 2307 }
2286 2308
2287 2309 if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
2288 2310 zerror(zlogp, B_TRUE, "%s: could not get flags",
2289 2311 lifr.lifr_name);
2290 2312 goto bad;
2291 2313 }
2292 2314 lifr.lifr_flags |= IFF_UP;
2293 2315 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
2294 2316 int save_errno = errno;
2295 2317 char *zone_using;
2296 2318
2297 2319 /*
2298 2320 * If we failed with something other than EADDRNOTAVAIL,
2299 2321 * then skip to the end. Otherwise, look up our address,
2300 2322 * then call a function to determine which zone is already
2301 2323 * using that address.
2302 2324 */
2303 2325 if (errno != EADDRNOTAVAIL) {
2304 2326 zerror(zlogp, B_TRUE,
2305 2327 "%s: could not bring network interface up",
2306 2328 lifr.lifr_name);
2307 2329 goto bad;
2308 2330 }
2309 2331 if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
2310 2332 zerror(zlogp, B_TRUE, "%s: could not get address",
2311 2333 lifr.lifr_name);
2312 2334 goto bad;
2313 2335 }
2314 2336 zone_using = who_is_using(zlogp, &lifr);
2315 2337 errno = save_errno;
2316 2338 if (zone_using == NULL)
2317 2339 zerror(zlogp, B_TRUE,
2318 2340 "%s: could not bring network interface up",
2319 2341 lifr.lifr_name);
2320 2342 else
2321 2343 zerror(zlogp, B_TRUE, "%s: could not bring network "
2322 2344 "interface up: address in use by zone '%s'",
2323 2345 lifr.lifr_name, zone_using);
2324 2346 goto bad;
2325 2347 }
2326 2348
2327 2349 if (!got_netmask && !is_loopback) {
2328 2350 /*
2329 2351 * A common, but often non-fatal problem, is that the system
2330 2352 * cannot find the netmask for an interface address. This is
2331 2353 * often caused by it being only in /etc/inet/netmasks, but
2332 2354 * /etc/nsswitch.conf says to use NIS or NIS+ and it's not
2333 2355 * in that. This doesn't show up at boot because the netmask
2334 2356 * is obtained from /etc/inet/netmasks when no network
2335 2357 * interfaces are up, but isn't consulted when NIS/NIS+ is
2336 2358 * available. We warn the user here that something like this
2337 2359 * has happened and we're just running with a default and
2338 2360 * possible incorrect netmask.
2339 2361 */
2340 2362 char buffer[INET6_ADDRSTRLEN];
2341 2363 void *addr;
2342 2364 const char *nomatch = "no matching subnet found in netmasks(4)";
2343 2365
2344 2366 if (af == AF_INET)
2345 2367 addr = &((struct sockaddr_in *)
2346 2368 (&lifr.lifr_addr))->sin_addr;
2347 2369 else
2348 2370 addr = &((struct sockaddr_in6 *)
2349 2371 (&lifr.lifr_addr))->sin6_addr;
2350 2372
2351 2373 /*
2352 2374 * Find out what netmask the interface is going to be using.
2353 2375 * If we just brought up an IPMP data address on an underlying
2354 2376 * interface above, the address will have already migrated, so
2355 2377 * the SIOCGLIFNETMASK won't be able to find it (but we need
2356 2378 * to bring the address up to get the actual netmask). Just
2357 2379 * omit printing the actual netmask in this corner-case.
2358 2380 */
2359 2381 if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0 ||
2360 2382 inet_ntop(af, addr, buffer, sizeof (buffer)) == NULL) {
2361 2383 zerror(zlogp, B_FALSE, "WARNING: %s; using default.",
2362 2384 nomatch);
2363 2385 } else {
2364 2386 zerror(zlogp, B_FALSE,
2365 2387 "WARNING: %s: %s: %s; using default of %s.",
2366 2388 lifr.lifr_name, nomatch, addrstr4, buffer);
2367 2389 }
2368 2390 }
2369 2391
2370 2392 /*
2371 2393 * If a default router was specified for this interface
2372 2394 * set the route now. Ignore if already set.
2373 2395 */
2374 2396 if (strlen(nwiftabptr->zone_nwif_defrouter) > 0) {
2375 2397 int status;
2376 2398 char *argv[7];
2377 2399
2378 2400 argv[0] = "route";
2379 2401 argv[1] = "add";
2380 2402 argv[2] = "-ifp";
2381 2403 argv[3] = nwiftabptr->zone_nwif_physical;
2382 2404 argv[4] = "default";
2383 2405 argv[5] = nwiftabptr->zone_nwif_defrouter;
2384 2406 argv[6] = NULL;
2385 2407
2386 2408 status = forkexec(zlogp, "/usr/sbin/route", argv);
2387 2409 if (status != 0 && status != EEXIST)
2388 2410 zerror(zlogp, B_FALSE, "Unable to set route for "
2389 2411 "interface %s to %s\n",
2390 2412 nwiftabptr->zone_nwif_physical,
2391 2413 nwiftabptr->zone_nwif_defrouter);
2392 2414 }
2393 2415
2394 2416 (void) close(s);
2395 2417 return (Z_OK);
2396 2418 bad:
2397 2419 (void) ioctl(s, SIOCLIFREMOVEIF, (caddr_t)&lifr);
2398 2420 (void) close(s);
2399 2421 return (-1);
2400 2422 }
2401 2423
2402 2424 /*
2403 2425 * Sets up network interfaces based on information from the zone configuration.
2404 2426 * IPv4 and IPv6 loopback interfaces are set up "for free", modeling the global
2405 2427 * system.
2406 2428 *
2407 2429 * If anything goes wrong, we log a general error message, attempt to tear down
2408 2430 * whatever we set up, and return an error.
2409 2431 */
2410 2432 static int
2411 2433 configure_shared_network_interfaces(zlog_t *zlogp)
2412 2434 {
2413 2435 zone_dochandle_t handle;
2414 2436 struct zone_nwiftab nwiftab, loopback_iftab;
2415 2437 zoneid_t zoneid;
2416 2438
2417 2439 if ((zoneid = getzoneidbyname(zone_name)) == ZONE_ID_UNDEFINED) {
2418 2440 zerror(zlogp, B_TRUE, "unable to get zoneid");
2419 2441 return (-1);
2420 2442 }
2421 2443
2422 2444 if ((handle = zonecfg_init_handle()) == NULL) {
2423 2445 zerror(zlogp, B_TRUE, "getting zone configuration handle");
2424 2446 return (-1);
2425 2447 }
2426 2448 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
2427 2449 zerror(zlogp, B_FALSE, "invalid configuration");
2428 2450 zonecfg_fini_handle(handle);
2429 2451 return (-1);
2430 2452 }
2431 2453 if (zonecfg_setnwifent(handle) == Z_OK) {
2432 2454 for (;;) {
2433 2455 if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
2434 2456 break;
2435 2457 if (configure_one_interface(zlogp, zoneid, &nwiftab) !=
2436 2458 Z_OK) {
2437 2459 (void) zonecfg_endnwifent(handle);
2438 2460 zonecfg_fini_handle(handle);
2439 2461 return (-1);
2440 2462 }
2441 2463 }
2442 2464 (void) zonecfg_endnwifent(handle);
2443 2465 }
2444 2466 zonecfg_fini_handle(handle);
2445 2467 if (is_system_labeled()) {
2446 2468 /*
2447 2469 * Labeled zones share the loopback interface
2448 2470 * so it is not plumbed for shared stack instances.
2449 2471 */
2450 2472 return (0);
2451 2473 }
2452 2474 (void) strlcpy(loopback_iftab.zone_nwif_physical, "lo0",
2453 2475 sizeof (loopback_iftab.zone_nwif_physical));
2454 2476 (void) strlcpy(loopback_iftab.zone_nwif_address, "127.0.0.1",
2455 2477 sizeof (loopback_iftab.zone_nwif_address));
2456 2478 loopback_iftab.zone_nwif_defrouter[0] = '\0';
2457 2479 if (configure_one_interface(zlogp, zoneid, &loopback_iftab) != Z_OK)
2458 2480 return (-1);
2459 2481
2460 2482 /* Always plumb up the IPv6 loopback interface. */
2461 2483 (void) strlcpy(loopback_iftab.zone_nwif_address, "::1/128",
2462 2484 sizeof (loopback_iftab.zone_nwif_address));
2463 2485 if (configure_one_interface(zlogp, zoneid, &loopback_iftab) != Z_OK)
2464 2486 return (-1);
2465 2487 return (0);
2466 2488 }
2467 2489
2468 2490 static void
2469 2491 zdlerror(zlog_t *zlogp, dladm_status_t err, const char *dlname, const char *str)
2470 2492 {
2471 2493 char errmsg[DLADM_STRSIZE];
2472 2494
2473 2495 (void) dladm_status2str(err, errmsg);
2474 2496 zerror(zlogp, B_FALSE, "%s '%s': %s", str, dlname, errmsg);
2475 2497 }
2476 2498
2477 2499 static int
2478 2500 add_datalink(zlog_t *zlogp, char *zone_name, datalink_id_t linkid, char *dlname)
2479 2501 {
2480 2502 dladm_status_t err;
2481 2503 boolean_t cpuset, poolset;
2482 2504 char *poolp;
2483 2505
2484 2506 /* First check if it's in use by global zone. */
2485 2507 if (zonecfg_ifname_exists(AF_INET, dlname) ||
2486 2508 zonecfg_ifname_exists(AF_INET6, dlname)) {
2487 2509 zerror(zlogp, B_FALSE, "WARNING: skipping network interface "
2488 2510 "'%s' which is used in the global zone", dlname);
2489 2511 return (-1);
2490 2512 }
2491 2513
2492 2514 /* Set zoneid of this link. */
2493 2515 err = dladm_set_linkprop(dld_handle, linkid, "zone", &zone_name, 1,
2494 2516 DLADM_OPT_ACTIVE);
2495 2517 if (err != DLADM_STATUS_OK) {
2496 2518 zdlerror(zlogp, err, dlname,
2497 2519 "WARNING: unable to add network interface");
2498 2520 return (-1);
2499 2521 }
2500 2522
2501 2523 /*
2502 2524 * Set the pool of this link if the zone has a pool and
2503 2525 * neither the cpus nor the pool datalink property is
2504 2526 * already set.
2505 2527 */
2506 2528 err = dladm_linkprop_is_set(dld_handle, linkid, DLADM_PROP_VAL_CURRENT,
2507 2529 "cpus", &cpuset);
2508 2530 if (err != DLADM_STATUS_OK) {
2509 2531 zdlerror(zlogp, err, dlname,
2510 2532 "WARNING: unable to check if cpus link property is set");
2511 2533 }
2512 2534 err = dladm_linkprop_is_set(dld_handle, linkid, DLADM_PROP_VAL_CURRENT,
2513 2535 "pool", &poolset);
2514 2536 if (err != DLADM_STATUS_OK) {
2515 2537 zdlerror(zlogp, err, dlname,
2516 2538 "WARNING: unable to check if pool link property is set");
2517 2539 }
2518 2540
2519 2541 if ((strlen(pool_name) != 0) && !cpuset && !poolset) {
2520 2542 poolp = pool_name;
2521 2543 err = dladm_set_linkprop(dld_handle, linkid, "pool",
2522 2544 &poolp, 1, DLADM_OPT_ACTIVE);
2523 2545 if (err != DLADM_STATUS_OK) {
2524 2546 zerror(zlogp, B_FALSE, "WARNING: unable to set "
2525 2547 "pool %s to datalink %s", pool_name, dlname);
2526 2548 bzero(pool_name, sizeof (pool_name));
2527 2549 }
2528 2550 } else {
2529 2551 bzero(pool_name, sizeof (pool_name));
2530 2552 }
2531 2553 return (0);
2532 2554 }
2533 2555
2534 2556 static boolean_t
2535 2557 sockaddr_to_str(sa_family_t af, const struct sockaddr *sockaddr,
2536 2558 char *straddr, size_t len)
2537 2559 {
2538 2560 struct sockaddr_in *sin;
2539 2561 struct sockaddr_in6 *sin6;
2540 2562 const char *str = NULL;
2541 2563
2542 2564 if (af == AF_INET) {
2543 2565 /* LINTED E_BAD_PTR_CAST_ALIGN */
2544 2566 sin = SIN(sockaddr);
2545 2567 str = inet_ntop(AF_INET, (void *)&sin->sin_addr, straddr, len);
2546 2568 } else if (af == AF_INET6) {
2547 2569 /* LINTED E_BAD_PTR_CAST_ALIGN */
2548 2570 sin6 = SIN6(sockaddr);
2549 2571 str = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, straddr,
2550 2572 len);
2551 2573 }
2552 2574
2553 2575 return (str != NULL);
2554 2576 }
2555 2577
2556 2578 static int
2557 2579 ipv4_prefixlen(struct sockaddr_in *sin)
2558 2580 {
2559 2581 struct sockaddr_in *m;
2560 2582 struct sockaddr_storage mask;
2561 2583
2562 2584 m = SIN(&mask);
2563 2585 m->sin_family = AF_INET;
2564 2586 if (getnetmaskbyaddr(sin->sin_addr, &m->sin_addr) == 0) {
2565 2587 return (mask2plen((struct sockaddr *)&mask));
2566 2588 } else if (IN_CLASSA(htonl(sin->sin_addr.s_addr))) {
2567 2589 return (8);
2568 2590 } else if (IN_CLASSB(ntohl(sin->sin_addr.s_addr))) {
2569 2591 return (16);
2570 2592 } else if (IN_CLASSC(ntohl(sin->sin_addr.s_addr))) {
2571 2593 return (24);
2572 2594 }
2573 2595 return (0);
2574 2596 }
2575 2597
2576 2598 static int
2577 2599 zone_setattr_network(int type, zoneid_t zoneid, datalink_id_t linkid,
2578 2600 void *buf, size_t bufsize)
2579 2601 {
2580 2602 zone_net_data_t *zndata;
2581 2603 size_t znsize;
2582 2604 int err;
2583 2605
2584 2606 znsize = sizeof (*zndata) + bufsize;
2585 2607 zndata = calloc(1, znsize);
2586 2608 if (zndata == NULL)
2587 2609 return (ENOMEM);
2588 2610 zndata->zn_type = type;
2589 2611 zndata->zn_len = bufsize;
2590 2612 zndata->zn_linkid = linkid;
2591 2613 bcopy(buf, zndata->zn_val, zndata->zn_len);
2592 2614 err = zone_setattr(zoneid, ZONE_ATTR_NETWORK, zndata, znsize);
2593 2615 free(zndata);
2594 2616 return (err);
2595 2617 }
2596 2618
2597 2619 static int
2598 2620 add_net_for_linkid(zlog_t *zlogp, zoneid_t zoneid, zone_addr_list_t *start)
2599 2621 {
2600 2622 struct lifreq lifr;
2601 2623 char **astr, *address;
2602 2624 dladm_status_t dlstatus;
2603 2625 char *ip_nospoof = "ip-nospoof";
2604 2626 int nnet, naddr, err = 0, j;
2605 2627 size_t zlen, cpleft;
2606 2628 zone_addr_list_t *ptr, *end;
2607 2629 char tmp[INET6_ADDRSTRLEN], *maskstr;
2608 2630 char *zaddr, *cp;
2609 2631 struct in6_addr *routes = NULL;
2610 2632 boolean_t is_set;
2611 2633 datalink_id_t linkid;
2612 2634
2613 2635 assert(start != NULL);
2614 2636 naddr = 0; /* number of addresses */
2615 2637 nnet = 0; /* number of net resources */
2616 2638 linkid = start->za_linkid;
2617 2639 for (ptr = start; ptr != NULL && ptr->za_linkid == linkid;
2618 2640 ptr = ptr->za_next) {
2619 2641 nnet++;
2620 2642 }
2621 2643 end = ptr;
2622 2644 zlen = nnet * (INET6_ADDRSTRLEN + 1);
2623 2645 astr = calloc(1, nnet * sizeof (uintptr_t));
2624 2646 zaddr = calloc(1, zlen);
2625 2647 if (astr == NULL || zaddr == NULL) {
2626 2648 err = ENOMEM;
2627 2649 goto done;
2628 2650 }
2629 2651 cp = zaddr;
2630 2652 cpleft = zlen;
2631 2653 j = 0;
2632 2654 for (ptr = start; ptr != end; ptr = ptr->za_next) {
2633 2655 address = ptr->za_nwiftab.zone_nwif_allowed_address;
2634 2656 if (address[0] == '\0')
2635 2657 continue;
2636 2658 (void) snprintf(tmp, sizeof (tmp), "%s", address);
2637 2659 /*
2638 2660 * Validate the data. zonecfg_valid_net_address() clobbers
2639 2661 * the /<mask> in the address string.
2640 2662 */
2641 2663 if (zonecfg_valid_net_address(address, &lifr) != Z_OK) {
2642 2664 zerror(zlogp, B_FALSE, "invalid address [%s]\n",
2643 2665 address);
2644 2666 err = EINVAL;
2645 2667 goto done;
2646 2668 }
2647 2669 /*
2648 2670 * convert any hostnames to numeric address strings.
2649 2671 */
2650 2672 if (!sockaddr_to_str(lifr.lifr_addr.ss_family,
2651 2673 (const struct sockaddr *)&lifr.lifr_addr, cp, cpleft)) {
2652 2674 err = EINVAL;
2653 2675 goto done;
2654 2676 }
2655 2677 /*
2656 2678 * make a copy of the numeric string for the data needed
2657 2679 * by the "allowed-ips" datalink property.
2658 2680 */
2659 2681 astr[j] = strdup(cp);
2660 2682 if (astr[j] == NULL) {
2661 2683 err = ENOMEM;
2662 2684 goto done;
2663 2685 }
2664 2686 j++;
2665 2687 /*
2666 2688 * compute the default netmask from the address, if necessary
2667 2689 */
2668 2690 if ((maskstr = strchr(tmp, '/')) == NULL) {
2669 2691 int prefixlen;
2670 2692
2671 2693 if (lifr.lifr_addr.ss_family == AF_INET) {
2672 2694 prefixlen = ipv4_prefixlen(
2673 2695 SIN(&lifr.lifr_addr));
2674 2696 } else {
2675 2697 struct sockaddr_in6 *sin6;
2676 2698
2677 2699 sin6 = SIN6(&lifr.lifr_addr);
2678 2700 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
2679 2701 prefixlen = 10;
2680 2702 else
2681 2703 prefixlen = 64;
2682 2704 }
2683 2705 (void) snprintf(tmp, sizeof (tmp), "%d", prefixlen);
2684 2706 maskstr = tmp;
2685 2707 } else {
2686 2708 maskstr++;
2687 2709 }
2688 2710 /* append the "/<netmask>" */
2689 2711 (void) strlcat(cp, "/", cpleft);
2690 2712 (void) strlcat(cp, maskstr, cpleft);
2691 2713 (void) strlcat(cp, ",", cpleft);
2692 2714 cp += strnlen(cp, zlen);
2693 2715 cpleft = &zaddr[INET6_ADDRSTRLEN] - cp;
2694 2716 }
2695 2717 naddr = j; /* the actual number of addresses in the net resource */
2696 2718 assert(naddr <= nnet);
2697 2719
2698 2720 /*
2699 2721 * zonecfg has already verified that the defrouter property can only
2700 2722 * be set if there is at least one address defined for the net resource.
2701 2723 * If j is 0, there are no addresses defined, and therefore no routers
2702 2724 * to configure, and we are done at that point.
2703 2725 */
2704 2726 if (j == 0)
2705 2727 goto done;
2706 2728
2707 2729 /* over-write last ',' with '\0' */
2708 2730 zaddr[strnlen(zaddr, zlen) + 1] = '\0';
2709 2731
2710 2732 /*
2711 2733 * First make sure L3 protection is not already set on the link.
2712 2734 */
2713 2735 dlstatus = dladm_linkprop_is_set(dld_handle, linkid, DLADM_OPT_ACTIVE,
2714 2736 "protection", &is_set);
2715 2737 if (dlstatus != DLADM_STATUS_OK) {
2716 2738 err = EINVAL;
2717 2739 zerror(zlogp, B_FALSE, "unable to check if protection is set");
2718 2740 goto done;
2719 2741 }
2720 2742 if (is_set) {
2721 2743 err = EINVAL;
2722 2744 zerror(zlogp, B_FALSE, "Protection is already set");
2723 2745 goto done;
2724 2746 }
2725 2747 dlstatus = dladm_linkprop_is_set(dld_handle, linkid, DLADM_OPT_ACTIVE,
2726 2748 "allowed-ips", &is_set);
2727 2749 if (dlstatus != DLADM_STATUS_OK) {
2728 2750 err = EINVAL;
2729 2751 zerror(zlogp, B_FALSE, "unable to check if allowed-ips is set");
2730 2752 goto done;
2731 2753 }
2732 2754 if (is_set) {
2733 2755 zerror(zlogp, B_FALSE, "allowed-ips is already set");
2734 2756 err = EINVAL;
2735 2757 goto done;
2736 2758 }
2737 2759
2738 2760 /*
2739 2761 * Enable ip-nospoof for the link, and add address to the allowed-ips
2740 2762 * list.
2741 2763 */
2742 2764 dlstatus = dladm_set_linkprop(dld_handle, linkid, "protection",
2743 2765 &ip_nospoof, 1, DLADM_OPT_ACTIVE);
2744 2766 if (dlstatus != DLADM_STATUS_OK) {
2745 2767 zerror(zlogp, B_FALSE, "could not set protection\n");
2746 2768 err = EINVAL;
2747 2769 goto done;
2748 2770 }
2749 2771 dlstatus = dladm_set_linkprop(dld_handle, linkid, "allowed-ips",
2750 2772 astr, naddr, DLADM_OPT_ACTIVE);
2751 2773 if (dlstatus != DLADM_STATUS_OK) {
2752 2774 zerror(zlogp, B_FALSE, "could not set allowed-ips\n");
2753 2775 err = EINVAL;
2754 2776 goto done;
2755 2777 }
2756 2778
2757 2779 /* now set the address in the data-store */
2758 2780 err = zone_setattr_network(ZONE_NETWORK_ADDRESS, zoneid, linkid,
2759 2781 zaddr, strnlen(zaddr, zlen) + 1);
2760 2782 if (err != 0)
2761 2783 goto done;
2762 2784
2763 2785 /*
2764 2786 * add the defaultrouters
2765 2787 */
2766 2788 routes = calloc(1, nnet * sizeof (*routes));
2767 2789 j = 0;
2768 2790 for (ptr = start; ptr != end; ptr = ptr->za_next) {
2769 2791 address = ptr->za_nwiftab.zone_nwif_defrouter;
2770 2792 if (address[0] == '\0')
2771 2793 continue;
2772 2794 if (strchr(address, '/') == NULL && strchr(address, ':') != 0) {
2773 2795 /*
2774 2796 * zonecfg_valid_net_address() expects numeric IPv6
2775 2797 * addresses to have a CIDR format netmask.
2776 2798 */
2777 2799 (void) snprintf(tmp, sizeof (tmp), "/%d", V6_ADDR_LEN);
2778 2800 (void) strlcat(address, tmp, INET6_ADDRSTRLEN);
2779 2801 }
2780 2802 if (zonecfg_valid_net_address(address, &lifr) != Z_OK) {
2781 2803 zerror(zlogp, B_FALSE,
2782 2804 "invalid router [%s]\n", address);
2783 2805 err = EINVAL;
2784 2806 goto done;
2785 2807 }
2786 2808 if (lifr.lifr_addr.ss_family == AF_INET6) {
2787 2809 routes[j] = SIN6(&lifr.lifr_addr)->sin6_addr;
2788 2810 } else {
2789 2811 IN6_INADDR_TO_V4MAPPED(&SIN(&lifr.lifr_addr)->sin_addr,
2790 2812 &routes[j]);
2791 2813 }
2792 2814 j++;
2793 2815 }
2794 2816 assert(j <= nnet);
2795 2817 if (j > 0) {
2796 2818 err = zone_setattr_network(ZONE_NETWORK_DEFROUTER, zoneid,
2797 2819 linkid, routes, j * sizeof (*routes));
2798 2820 }
2799 2821 done:
2800 2822 free(routes);
2801 2823 for (j = 0; j < naddr; j++)
2802 2824 free(astr[j]);
2803 2825 free(astr);
2804 2826 free(zaddr);
2805 2827 return (err);
2806 2828
2807 2829 }
2808 2830
2809 2831 static int
2810 2832 add_net(zlog_t *zlogp, zoneid_t zoneid, zone_addr_list_t *zalist)
2811 2833 {
2812 2834 zone_addr_list_t *ptr;
2813 2835 datalink_id_t linkid;
2814 2836 int err;
2815 2837
2816 2838 if (zalist == NULL)
2817 2839 return (0);
2818 2840
2819 2841 linkid = zalist->za_linkid;
2820 2842
2821 2843 err = add_net_for_linkid(zlogp, zoneid, zalist);
2822 2844 if (err != 0)
2823 2845 return (err);
2824 2846
2825 2847 for (ptr = zalist; ptr != NULL; ptr = ptr->za_next) {
2826 2848 if (ptr->za_linkid == linkid)
2827 2849 continue;
2828 2850 linkid = ptr->za_linkid;
2829 2851 err = add_net_for_linkid(zlogp, zoneid, ptr);
2830 2852 if (err != 0)
2831 2853 return (err);
2832 2854 }
2833 2855 return (0);
2834 2856 }
2835 2857
2836 2858 /*
2837 2859 * Add "new" to the list of network interfaces to be configured by
2838 2860 * add_net on zone boot in "old". The list of interfaces in "old" is
2839 2861 * sorted by datalink_id_t, with interfaces sorted FIFO for a given
2840 2862 * datalink_id_t.
2841 2863 *
2842 2864 * Returns the merged list of IP interfaces containing "old" and "new"
2843 2865 */
2844 2866 static zone_addr_list_t *
2845 2867 add_ip_interface(zone_addr_list_t *old, zone_addr_list_t *new)
2846 2868 {
2847 2869 zone_addr_list_t *ptr, *next;
2848 2870 datalink_id_t linkid = new->za_linkid;
2849 2871
2850 2872 assert(old != new);
2851 2873
2852 2874 if (old == NULL)
2853 2875 return (new);
2854 2876 for (ptr = old; ptr != NULL; ptr = ptr->za_next) {
2855 2877 if (ptr->za_linkid == linkid)
2856 2878 break;
2857 2879 }
2858 2880 if (ptr == NULL) {
2859 2881 /* linkid does not already exist, add to the beginning */
2860 2882 new->za_next = old;
2861 2883 return (new);
2862 2884 }
2863 2885 /*
2864 2886 * adding to the middle of the list; ptr points at the first
2865 2887 * occurrence of linkid. Find the last occurrence.
2866 2888 */
2867 2889 while ((next = ptr->za_next) != NULL) {
2868 2890 if (next->za_linkid != linkid)
2869 2891 break;
2870 2892 ptr = next;
2871 2893 }
2872 2894 /* insert new after ptr */
2873 2895 new->za_next = next;
2874 2896 ptr->za_next = new;
2875 2897 return (old);
2876 2898 }
2877 2899
2878 2900 void
2879 2901 free_ip_interface(zone_addr_list_t *zalist)
2880 2902 {
|
↓ open down ↓ |
1056 lines elided |
↑ open up ↑ |
2881 2903 zone_addr_list_t *ptr, *new;
2882 2904
2883 2905 for (ptr = zalist; ptr != NULL; ) {
2884 2906 new = ptr;
2885 2907 ptr = ptr->za_next;
2886 2908 free(new);
2887 2909 }
2888 2910 }
2889 2911
2890 2912 /*
2913 + * For IP networking, we need to use the illumos-native device tree. For most
2914 + * zones, this is $ZONEROOT/dev. For LX ones, it's $ZONEROOT/native/dev.
2915 + * Return the appropriate post-$ZONEROOT path.
2916 + */
2917 +static char *
2918 +get_brand_dev(void)
2919 +{
2920 + static char *lxpath = "/native/dev";
2921 + /* Cheesy hard-coding of strlen("/native") */
2922 + char *default_path = lxpath + 7;
2923 +
2924 + /* LX zones are the exception... */
2925 + if (strcmp(brand_name, "lx") == 0)
2926 + return (lxpath);
2927 +
2928 + return (default_path);
2929 +}
2930 +
2931 +/*
2891 2932 * Add the kernel access control information for the interface names.
2892 2933 * If anything goes wrong, we log a general error message, attempt to tear down
2893 2934 * whatever we set up, and return an error.
2894 2935 */
2895 2936 static int
2896 2937 configure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
2897 2938 {
2898 2939 zone_dochandle_t handle;
2899 2940 struct zone_nwiftab nwiftab;
2900 2941 char rootpath[MAXPATHLEN];
2901 2942 char path[MAXPATHLEN];
2902 2943 datalink_id_t linkid;
2903 2944 di_prof_t prof = NULL;
2904 2945 boolean_t added = B_FALSE;
2905 2946 zone_addr_list_t *zalist = NULL, *new;
2906 2947
2907 2948 if ((handle = zonecfg_init_handle()) == NULL) {
2908 2949 zerror(zlogp, B_TRUE, "getting zone configuration handle");
2909 2950 return (-1);
2910 2951 }
2911 2952 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
2912 2953 zerror(zlogp, B_FALSE, "invalid configuration");
2913 2954 zonecfg_fini_handle(handle);
2914 2955 return (-1);
2915 2956 }
2916 2957
2917 2958 if (zonecfg_setnwifent(handle) != Z_OK) {
2918 2959 zonecfg_fini_handle(handle);
2919 2960 return (0);
2920 2961 }
2921 2962
2922 2963 for (;;) {
2923 2964 if (zonecfg_getnwifent(handle, &nwiftab) != Z_OK)
2924 2965 break;
2925 2966
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
2926 2967 if (prof == NULL) {
2927 2968 if (zone_get_devroot(zone_name, rootpath,
2928 2969 sizeof (rootpath)) != Z_OK) {
2929 2970 (void) zonecfg_endnwifent(handle);
2930 2971 zonecfg_fini_handle(handle);
2931 2972 zerror(zlogp, B_TRUE,
2932 2973 "unable to determine dev root");
2933 2974 return (-1);
2934 2975 }
2935 2976 (void) snprintf(path, sizeof (path), "%s%s", rootpath,
2936 - "/dev");
2977 + get_brand_dev());
2937 2978 if (di_prof_init(path, &prof) != 0) {
2938 2979 (void) zonecfg_endnwifent(handle);
2939 2980 zonecfg_fini_handle(handle);
2940 2981 zerror(zlogp, B_TRUE,
2941 2982 "failed to initialize profile");
2942 2983 return (-1);
2943 2984 }
2944 2985 }
2945 2986
2946 2987 /*
2947 2988 * Create the /dev entry for backward compatibility.
2948 2989 * Only create the /dev entry if it's not in use.
2949 2990 * Note that the zone still boots when the assigned
2950 2991 * interface is inaccessible, used by others, etc.
2951 2992 * Also, when vanity naming is used, some interface do
2952 2993 * do not have corresponding /dev node names (for example,
2953 2994 * vanity named aggregations). The /dev entry is not
2954 2995 * created in that case. The /dev/net entry is always
2955 2996 * accessible.
2956 2997 */
2957 2998 if (dladm_name2info(dld_handle, nwiftab.zone_nwif_physical,
2958 2999 &linkid, NULL, NULL, NULL) == DLADM_STATUS_OK &&
2959 3000 add_datalink(zlogp, zone_name, linkid,
2960 3001 nwiftab.zone_nwif_physical) == 0) {
2961 3002 added = B_TRUE;
2962 3003 } else {
2963 3004 (void) zonecfg_endnwifent(handle);
2964 3005 zonecfg_fini_handle(handle);
2965 3006 zerror(zlogp, B_TRUE, "failed to add network device");
2966 3007 return (-1);
2967 3008 }
2968 3009 /* set up the new IP interface, and add them all later */
2969 3010 new = malloc(sizeof (*new));
2970 3011 if (new == NULL) {
2971 3012 zerror(zlogp, B_TRUE, "no memory for %s",
2972 3013 nwiftab.zone_nwif_physical);
2973 3014 zonecfg_fini_handle(handle);
2974 3015 free_ip_interface(zalist);
2975 3016 }
2976 3017 bzero(new, sizeof (*new));
2977 3018 new->za_nwiftab = nwiftab;
2978 3019 new->za_linkid = linkid;
2979 3020 zalist = add_ip_interface(zalist, new);
2980 3021 }
2981 3022 if (zalist != NULL) {
2982 3023 if ((errno = add_net(zlogp, zoneid, zalist)) != 0) {
2983 3024 (void) zonecfg_endnwifent(handle);
2984 3025 zonecfg_fini_handle(handle);
2985 3026 zerror(zlogp, B_TRUE, "failed to add address");
2986 3027 free_ip_interface(zalist);
2987 3028 return (-1);
2988 3029 }
2989 3030 free_ip_interface(zalist);
2990 3031 }
2991 3032 (void) zonecfg_endnwifent(handle);
2992 3033 zonecfg_fini_handle(handle);
2993 3034
2994 3035 if (prof != NULL && added) {
2995 3036 if (di_prof_commit(prof) != 0) {
2996 3037 zerror(zlogp, B_TRUE, "failed to commit profile");
2997 3038 return (-1);
2998 3039 }
2999 3040 }
3000 3041 if (prof != NULL)
3001 3042 di_prof_fini(prof);
3002 3043
3003 3044 return (0);
3004 3045 }
3005 3046
3006 3047 static int
3007 3048 remove_datalink_pool(zlog_t *zlogp, zoneid_t zoneid)
3008 3049 {
3009 3050 ushort_t flags;
3010 3051 zone_iptype_t iptype;
3011 3052 int i, dlnum = 0;
3012 3053 datalink_id_t *dllink, *dllinks = NULL;
3013 3054 dladm_status_t err;
3014 3055
3015 3056 if (strlen(pool_name) == 0)
3016 3057 return (0);
3017 3058
3018 3059 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3019 3060 sizeof (flags)) < 0) {
3020 3061 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3021 3062 zerror(zlogp, B_FALSE, "unable to determine ip-type");
3022 3063 return (-1);
3023 3064 }
3024 3065 } else {
3025 3066 if (flags & ZF_NET_EXCL)
3026 3067 iptype = ZS_EXCLUSIVE;
3027 3068 else
3028 3069 iptype = ZS_SHARED;
3029 3070 }
3030 3071
3031 3072 if (iptype == ZS_EXCLUSIVE) {
3032 3073 /*
3033 3074 * Get the datalink count and for each datalink,
3034 3075 * attempt to clear the pool property and clear
3035 3076 * the pool_name.
3036 3077 */
3037 3078 if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
3038 3079 zerror(zlogp, B_TRUE, "unable to count network "
3039 3080 "interfaces");
3040 3081 return (-1);
3041 3082 }
3042 3083
3043 3084 if (dlnum == 0)
3044 3085 return (0);
3045 3086
3046 3087 if ((dllinks = malloc(dlnum * sizeof (datalink_id_t)))
3047 3088 == NULL) {
3048 3089 zerror(zlogp, B_TRUE, "memory allocation failed");
3049 3090 return (-1);
3050 3091 }
3051 3092 if (zone_list_datalink(zoneid, &dlnum, dllinks) != 0) {
3052 3093 zerror(zlogp, B_TRUE, "unable to list network "
3053 3094 "interfaces");
3054 3095 return (-1);
3055 3096 }
3056 3097
3057 3098 bzero(pool_name, sizeof (pool_name));
3058 3099 for (i = 0, dllink = dllinks; i < dlnum; i++, dllink++) {
3059 3100 err = dladm_set_linkprop(dld_handle, *dllink, "pool",
3060 3101 NULL, 0, DLADM_OPT_ACTIVE);
3061 3102 if (err != DLADM_STATUS_OK) {
3062 3103 zerror(zlogp, B_TRUE,
3063 3104 "WARNING: unable to clear pool");
3064 3105 }
3065 3106 }
3066 3107 free(dllinks);
3067 3108 }
3068 3109 return (0);
3069 3110 }
3070 3111
3071 3112 static int
3072 3113 remove_datalink_protect(zlog_t *zlogp, zoneid_t zoneid)
3073 3114 {
3074 3115 ushort_t flags;
3075 3116 zone_iptype_t iptype;
3076 3117 int i, dlnum = 0;
3077 3118 dladm_status_t dlstatus;
3078 3119 datalink_id_t *dllink, *dllinks = NULL;
3079 3120
3080 3121 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3081 3122 sizeof (flags)) < 0) {
3082 3123 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3083 3124 zerror(zlogp, B_FALSE, "unable to determine ip-type");
3084 3125 return (-1);
3085 3126 }
3086 3127 } else {
3087 3128 if (flags & ZF_NET_EXCL)
3088 3129 iptype = ZS_EXCLUSIVE;
3089 3130 else
3090 3131 iptype = ZS_SHARED;
3091 3132 }
3092 3133
3093 3134 if (iptype != ZS_EXCLUSIVE)
3094 3135 return (0);
3095 3136
3096 3137 /*
3097 3138 * Get the datalink count and for each datalink,
3098 3139 * attempt to clear the pool property and clear
3099 3140 * the pool_name.
3100 3141 */
3101 3142 if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
3102 3143 zerror(zlogp, B_TRUE, "unable to count network interfaces");
3103 3144 return (-1);
3104 3145 }
3105 3146
3106 3147 if (dlnum == 0)
3107 3148 return (0);
3108 3149
3109 3150 if ((dllinks = malloc(dlnum * sizeof (datalink_id_t))) == NULL) {
3110 3151 zerror(zlogp, B_TRUE, "memory allocation failed");
3111 3152 return (-1);
3112 3153 }
3113 3154 if (zone_list_datalink(zoneid, &dlnum, dllinks) != 0) {
3114 3155 zerror(zlogp, B_TRUE, "unable to list network interfaces");
3115 3156 free(dllinks);
3116 3157 return (-1);
3117 3158 }
3118 3159
3119 3160 for (i = 0, dllink = dllinks; i < dlnum; i++, dllink++) {
3120 3161 char dlerr[DLADM_STRSIZE];
3121 3162
3122 3163 dlstatus = dladm_set_linkprop(dld_handle, *dllink,
3123 3164 "protection", NULL, 0, DLADM_OPT_ACTIVE);
3124 3165 if (dlstatus == DLADM_STATUS_NOTFOUND) {
3125 3166 /* datalink does not belong to the GZ */
3126 3167 continue;
3127 3168 }
3128 3169 if (dlstatus != DLADM_STATUS_OK) {
3129 3170 zerror(zlogp, B_FALSE,
3130 3171 dladm_status2str(dlstatus, dlerr));
3131 3172 free(dllinks);
3132 3173 return (-1);
3133 3174 }
3134 3175 dlstatus = dladm_set_linkprop(dld_handle, *dllink,
3135 3176 "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
3136 3177 if (dlstatus != DLADM_STATUS_OK) {
3137 3178 zerror(zlogp, B_FALSE,
3138 3179 dladm_status2str(dlstatus, dlerr));
3139 3180 free(dllinks);
3140 3181 return (-1);
3141 3182 }
3142 3183 }
3143 3184 free(dllinks);
3144 3185 return (0);
3145 3186 }
3146 3187
3147 3188 static int
3148 3189 unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
3149 3190 {
3150 3191 int dlnum = 0;
3151 3192
3152 3193 /*
3153 3194 * The kernel shutdown callback for the dls module should have removed
3154 3195 * all datalinks from this zone. If any remain, then there's a
3155 3196 * problem.
3156 3197 */
3157 3198 if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
3158 3199 zerror(zlogp, B_TRUE, "unable to list network interfaces");
3159 3200 return (-1);
3160 3201 }
3161 3202 if (dlnum != 0) {
3162 3203 zerror(zlogp, B_FALSE,
3163 3204 "datalinks remain in zone after shutdown");
3164 3205 return (-1);
3165 3206 }
3166 3207 return (0);
3167 3208 }
3168 3209
3169 3210 static int
3170 3211 tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
3171 3212 const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
3172 3213 {
3173 3214 int fd;
3174 3215 struct strioctl ioc;
3175 3216 tcp_ioc_abort_conn_t conn;
3176 3217 int error;
3177 3218
3178 3219 conn.ac_local = *local;
3179 3220 conn.ac_remote = *remote;
3180 3221 conn.ac_start = TCPS_SYN_SENT;
3181 3222 conn.ac_end = TCPS_TIME_WAIT;
3182 3223 conn.ac_zoneid = zoneid;
3183 3224
3184 3225 ioc.ic_cmd = TCP_IOC_ABORT_CONN;
3185 3226 ioc.ic_timout = -1; /* infinite timeout */
3186 3227 ioc.ic_len = sizeof (conn);
3187 3228 ioc.ic_dp = (char *)&conn;
3188 3229
3189 3230 if ((fd = open("/dev/tcp", O_RDONLY)) < 0) {
3190 3231 zerror(zlogp, B_TRUE, "unable to open %s", "/dev/tcp");
3191 3232 return (-1);
3192 3233 }
3193 3234
3194 3235 error = ioctl(fd, I_STR, &ioc);
3195 3236 (void) close(fd);
3196 3237 if (error == 0 || errno == ENOENT) /* ENOENT is not an error */
3197 3238 return (0);
3198 3239 return (-1);
3199 3240 }
3200 3241
3201 3242 static int
3202 3243 tcp_abort_connections(zlog_t *zlogp, zoneid_t zoneid)
3203 3244 {
3204 3245 struct sockaddr_storage l, r;
3205 3246 struct sockaddr_in *local, *remote;
3206 3247 struct sockaddr_in6 *local6, *remote6;
3207 3248 int error;
3208 3249
3209 3250 /*
3210 3251 * Abort IPv4 connections.
3211 3252 */
3212 3253 bzero(&l, sizeof (*local));
3213 3254 local = (struct sockaddr_in *)&l;
3214 3255 local->sin_family = AF_INET;
3215 3256 local->sin_addr.s_addr = INADDR_ANY;
3216 3257 local->sin_port = 0;
3217 3258
3218 3259 bzero(&r, sizeof (*remote));
3219 3260 remote = (struct sockaddr_in *)&r;
3220 3261 remote->sin_family = AF_INET;
3221 3262 remote->sin_addr.s_addr = INADDR_ANY;
3222 3263 remote->sin_port = 0;
3223 3264
3224 3265 if ((error = tcp_abort_conn(zlogp, zoneid, &l, &r)) != 0)
3225 3266 return (error);
3226 3267
3227 3268 /*
3228 3269 * Abort IPv6 connections.
3229 3270 */
3230 3271 bzero(&l, sizeof (*local6));
3231 3272 local6 = (struct sockaddr_in6 *)&l;
3232 3273 local6->sin6_family = AF_INET6;
3233 3274 local6->sin6_port = 0;
3234 3275 local6->sin6_addr = in6addr_any;
3235 3276
3236 3277 bzero(&r, sizeof (*remote6));
3237 3278 remote6 = (struct sockaddr_in6 *)&r;
3238 3279 remote6->sin6_family = AF_INET6;
3239 3280 remote6->sin6_port = 0;
3240 3281 remote6->sin6_addr = in6addr_any;
3241 3282
3242 3283 if ((error = tcp_abort_conn(zlogp, zoneid, &l, &r)) != 0)
3243 3284 return (error);
3244 3285 return (0);
3245 3286 }
3246 3287
3247 3288 static int
3248 3289 get_privset(zlog_t *zlogp, priv_set_t *privs, zone_mnt_t mount_cmd)
3249 3290 {
3250 3291 int error = -1;
3251 3292 zone_dochandle_t handle;
3252 3293 char *privname = NULL;
3253 3294
3254 3295 if ((handle = zonecfg_init_handle()) == NULL) {
3255 3296 zerror(zlogp, B_TRUE, "getting zone configuration handle");
3256 3297 return (-1);
3257 3298 }
3258 3299 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
3259 3300 zerror(zlogp, B_FALSE, "invalid configuration");
3260 3301 zonecfg_fini_handle(handle);
3261 3302 return (-1);
3262 3303 }
3263 3304
3264 3305 if (ALT_MOUNT(mount_cmd)) {
3265 3306 zone_iptype_t iptype;
3266 3307 const char *curr_iptype;
3267 3308
3268 3309 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
3269 3310 zerror(zlogp, B_TRUE, "unable to determine ip-type");
3270 3311 zonecfg_fini_handle(handle);
3271 3312 return (-1);
3272 3313 }
3273 3314
3274 3315 switch (iptype) {
3275 3316 case ZS_SHARED:
3276 3317 curr_iptype = "shared";
3277 3318 break;
3278 3319 case ZS_EXCLUSIVE:
3279 3320 curr_iptype = "exclusive";
3280 3321 break;
3281 3322 }
3282 3323
3283 3324 if (zonecfg_default_privset(privs, curr_iptype) == Z_OK) {
3284 3325 zonecfg_fini_handle(handle);
3285 3326 return (0);
3286 3327 }
3287 3328 zerror(zlogp, B_FALSE,
3288 3329 "failed to determine the zone's default privilege set");
3289 3330 zonecfg_fini_handle(handle);
3290 3331 return (-1);
3291 3332 }
3292 3333
3293 3334 switch (zonecfg_get_privset(handle, privs, &privname)) {
3294 3335 case Z_OK:
3295 3336 error = 0;
3296 3337 break;
3297 3338 case Z_PRIV_PROHIBITED:
3298 3339 zerror(zlogp, B_FALSE, "privilege \"%s\" is not permitted "
3299 3340 "within the zone's privilege set", privname);
3300 3341 break;
3301 3342 case Z_PRIV_REQUIRED:
3302 3343 zerror(zlogp, B_FALSE, "required privilege \"%s\" is missing "
3303 3344 "from the zone's privilege set", privname);
3304 3345 break;
3305 3346 case Z_PRIV_UNKNOWN:
3306 3347 zerror(zlogp, B_FALSE, "unknown privilege \"%s\" specified "
3307 3348 "in the zone's privilege set", privname);
3308 3349 break;
3309 3350 default:
|
↓ open down ↓ |
363 lines elided |
↑ open up ↑ |
3310 3351 zerror(zlogp, B_FALSE, "failed to determine the zone's "
3311 3352 "privilege set");
3312 3353 break;
3313 3354 }
3314 3355
3315 3356 free(privname);
3316 3357 zonecfg_fini_handle(handle);
3317 3358 return (error);
3318 3359 }
3319 3360
3361 +static char *
3362 +zone_proj_rctl(const char *name)
3363 +{
3364 + int i;
3365 +
3366 + for (i = 0; zone_proj_rctl_map[i].zpr_zone_rctl != NULL; i++) {
3367 + if (strcmp(name, zone_proj_rctl_map[i].zpr_zone_rctl) == 0) {
3368 + return (zone_proj_rctl_map[i].zpr_project_rctl);
3369 + }
3370 + }
3371 + return (NULL);
3372 +}
3373 +
3320 3374 static int
3321 3375 get_rctls(zlog_t *zlogp, char **bufp, size_t *bufsizep)
3322 3376 {
3323 3377 nvlist_t *nvl = NULL;
3324 3378 char *nvl_packed = NULL;
3325 3379 size_t nvl_size = 0;
3326 3380 nvlist_t **nvlv = NULL;
3327 3381 int rctlcount = 0;
3328 3382 int error = -1;
3329 3383 zone_dochandle_t handle;
3330 3384 struct zone_rctltab rctltab;
3331 3385 rctlblk_t *rctlblk = NULL;
3332 3386 uint64_t maxlwps;
3333 3387 uint64_t maxprocs;
3388 + int rproc, rlwp;
3334 3389
3335 3390 *bufp = NULL;
3336 3391 *bufsizep = 0;
3337 3392
3338 3393 if ((handle = zonecfg_init_handle()) == NULL) {
3339 3394 zerror(zlogp, B_TRUE, "getting zone configuration handle");
3340 3395 return (-1);
3341 3396 }
3342 3397 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
3343 3398 zerror(zlogp, B_FALSE, "invalid configuration");
3344 3399 zonecfg_fini_handle(handle);
3345 3400 return (-1);
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3346 3401 }
3347 3402
3348 3403 rctltab.zone_rctl_valptr = NULL;
3349 3404 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
3350 3405 zerror(zlogp, B_TRUE, "%s failed", "nvlist_alloc");
3351 3406 goto out;
3352 3407 }
3353 3408
3354 3409 /*
3355 3410 * Allow the administrator to control both the maximum number of
3356 - * process table slots and the maximum number of lwps with just the
3357 - * max-processes property. If only the max-processes property is set,
3358 - * we add a max-lwps property with a limit derived from max-processes.
3411 + * process table slots, and the maximum number of lwps, with a single
3412 + * max-processes or max-lwps property. If only the max-processes
3413 + * property is set, we add a max-lwps property with a limit derived
3414 + * from max-processes. If only the max-lwps property is set, we add a
3415 + * max-processes property with the same limit as max-lwps.
3359 3416 */
3360 - if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPROCS, &maxprocs)
3361 - == Z_OK &&
3362 - zonecfg_get_aliased_rctl(handle, ALIAS_MAXLWPS, &maxlwps)
3363 - == Z_NO_ENTRY) {
3364 - if (zonecfg_set_aliased_rctl(handle, ALIAS_MAXLWPS,
3417 + rproc = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXPROCS, &maxprocs);
3418 + rlwp = zonecfg_get_aliased_rctl(snap_hndl, ALIAS_MAXLWPS, &maxlwps);
3419 + if (rproc == Z_OK && rlwp == Z_NO_ENTRY) {
3420 + if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXLWPS,
3365 3421 maxprocs * LWPS_PER_PROCESS) != Z_OK) {
3366 3422 zerror(zlogp, B_FALSE, "unable to set max-lwps alias");
3367 3423 goto out;
3368 3424 }
3425 + } else if (rlwp == Z_OK && rproc == Z_NO_ENTRY) {
3426 + /* no scaling for max-proc value */
3427 + if (zonecfg_set_aliased_rctl(snap_hndl, ALIAS_MAXPROCS,
3428 + maxlwps) != Z_OK) {
3429 + zerror(zlogp, B_FALSE,
3430 + "unable to set max-processes alias");
3431 + goto out;
3432 + }
3369 3433 }
3370 3434
3371 3435 if (zonecfg_setrctlent(handle) != Z_OK) {
3372 3436 zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setrctlent");
3373 3437 goto out;
3374 3438 }
3375 3439
3376 3440 if ((rctlblk = malloc(rctlblk_size())) == NULL) {
3377 3441 zerror(zlogp, B_TRUE, "memory allocation failed");
3378 3442 goto out;
3379 3443 }
3380 3444 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
3381 3445 struct zone_rctlvaltab *rctlval;
3382 3446 uint_t i, count;
3383 3447 const char *name = rctltab.zone_rctl_name;
3448 + char *proj_nm;
3384 3449
3385 3450 /* zoneadm should have already warned about unknown rctls. */
3386 3451 if (!zonecfg_is_rctl(name)) {
3387 3452 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3388 3453 rctltab.zone_rctl_valptr = NULL;
3389 3454 continue;
3390 3455 }
3391 3456 count = 0;
3392 3457 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
3393 3458 rctlval = rctlval->zone_rctlval_next) {
3394 3459 count++;
3395 3460 }
3396 3461 if (count == 0) { /* ignore */
3397 3462 continue; /* Nothing to free */
3398 3463 }
3399 3464 if ((nvlv = malloc(sizeof (*nvlv) * count)) == NULL)
3400 3465 goto out;
3401 3466 i = 0;
3402 3467 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
3403 3468 rctlval = rctlval->zone_rctlval_next, i++) {
3404 3469 if (nvlist_alloc(&nvlv[i], NV_UNIQUE_NAME, 0) != 0) {
3405 3470 zerror(zlogp, B_TRUE, "%s failed",
3406 3471 "nvlist_alloc");
3407 3472 goto out;
3408 3473 }
3409 3474 if (zonecfg_construct_rctlblk(rctlval, rctlblk)
3410 3475 != Z_OK) {
3411 3476 zerror(zlogp, B_FALSE, "invalid rctl value: "
3412 3477 "(priv=%s,limit=%s,action=%s)",
3413 3478 rctlval->zone_rctlval_priv,
3414 3479 rctlval->zone_rctlval_limit,
3415 3480 rctlval->zone_rctlval_action);
3416 3481 goto out;
3417 3482 }
3418 3483 if (!zonecfg_valid_rctl(name, rctlblk)) {
3419 3484 zerror(zlogp, B_FALSE,
3420 3485 "(priv=%s,limit=%s,action=%s) is not a "
3421 3486 "valid value for rctl '%s'",
3422 3487 rctlval->zone_rctlval_priv,
3423 3488 rctlval->zone_rctlval_limit,
3424 3489 rctlval->zone_rctlval_action,
3425 3490 name);
3426 3491 goto out;
3427 3492 }
3428 3493 if (nvlist_add_uint64(nvlv[i], "privilege",
3429 3494 rctlblk_get_privilege(rctlblk)) != 0) {
3430 3495 zerror(zlogp, B_FALSE, "%s failed",
3431 3496 "nvlist_add_uint64");
3432 3497 goto out;
3433 3498 }
3434 3499 if (nvlist_add_uint64(nvlv[i], "limit",
3435 3500 rctlblk_get_value(rctlblk)) != 0) {
3436 3501 zerror(zlogp, B_FALSE, "%s failed",
3437 3502 "nvlist_add_uint64");
3438 3503 goto out;
3439 3504 }
|
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
3440 3505 if (nvlist_add_uint64(nvlv[i], "action",
3441 3506 (uint_t)rctlblk_get_local_action(rctlblk, NULL))
3442 3507 != 0) {
3443 3508 zerror(zlogp, B_FALSE, "%s failed",
3444 3509 "nvlist_add_uint64");
3445 3510 goto out;
3446 3511 }
3447 3512 }
3448 3513 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3449 3514 rctltab.zone_rctl_valptr = NULL;
3515 +
3516 + /*
3517 + * With no action on our part we will start zsched with the
3518 + * project rctl values for our (zoneadmd) current project. For
3519 + * brands running a variant of Illumos, that's not a problem
3520 + * since they will setup their own projects, but for a
3521 + * non-native brand like lx, where there are no projects, we
3522 + * want to start things up with the same project rctls as the
3523 + * corresponding zone rctls, since nothing within the zone will
3524 + * ever change the project rctls.
3525 + */
3526 + if ((proj_nm = zone_proj_rctl(name)) != NULL) {
3527 + if (nvlist_add_nvlist_array(nvl, proj_nm, nvlv, count)
3528 + != 0) {
3529 + zerror(zlogp, B_FALSE,
3530 + "nvlist_add_nvlist_arrays failed");
3531 + goto out;
3532 + }
3533 + }
3534 +
3450 3535 if (nvlist_add_nvlist_array(nvl, (char *)name, nvlv, count)
3451 3536 != 0) {
3452 3537 zerror(zlogp, B_FALSE, "%s failed",
3453 3538 "nvlist_add_nvlist_array");
3454 3539 goto out;
3455 3540 }
3456 3541 for (i = 0; i < count; i++)
3457 3542 nvlist_free(nvlv[i]);
3458 3543 free(nvlv);
3459 3544 nvlv = NULL;
3460 3545 rctlcount++;
3461 3546 }
3462 3547 (void) zonecfg_endrctlent(handle);
3463 3548
3464 3549 if (rctlcount == 0) {
3465 3550 error = 0;
3466 3551 goto out;
3467 3552 }
3468 3553 if (nvlist_pack(nvl, &nvl_packed, &nvl_size, NV_ENCODE_NATIVE, 0)
3469 3554 != 0) {
3470 3555 zerror(zlogp, B_FALSE, "%s failed", "nvlist_pack");
3471 3556 goto out;
3472 3557 }
3473 3558
3474 3559 error = 0;
3475 3560 *bufp = nvl_packed;
3476 3561 *bufsizep = nvl_size;
3477 3562
3478 3563 out:
3479 3564 free(rctlblk);
3480 3565 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3481 3566 if (error && nvl_packed != NULL)
3482 3567 free(nvl_packed);
3483 3568 nvlist_free(nvl);
3484 3569 if (nvlv != NULL)
3485 3570 free(nvlv);
3486 3571 if (handle != NULL)
3487 3572 zonecfg_fini_handle(handle);
3488 3573 return (error);
3489 3574 }
3490 3575
3491 3576 static int
3492 3577 get_implicit_datasets(zlog_t *zlogp, char **retstr)
3493 3578 {
3494 3579 char cmdbuf[2 * MAXPATHLEN];
3495 3580
3496 3581 if (query_hook[0] == '\0')
3497 3582 return (0);
3498 3583
3499 3584 if (snprintf(cmdbuf, sizeof (cmdbuf), "%s datasets", query_hook)
3500 3585 > sizeof (cmdbuf))
3501 3586 return (-1);
3502 3587
3503 3588 if (do_subproc(zlogp, cmdbuf, retstr) != 0)
3504 3589 return (-1);
3505 3590
3506 3591 return (0);
3507 3592 }
3508 3593
3509 3594 static int
3510 3595 get_datasets(zlog_t *zlogp, char **bufp, size_t *bufsizep)
3511 3596 {
3512 3597 zone_dochandle_t handle;
3513 3598 struct zone_dstab dstab;
3514 3599 size_t total, offset, len;
3515 3600 int error = -1;
3516 3601 char *str = NULL;
3517 3602 char *implicit_datasets = NULL;
3518 3603 int implicit_len = 0;
3519 3604
3520 3605 *bufp = NULL;
3521 3606 *bufsizep = 0;
3522 3607
3523 3608 if ((handle = zonecfg_init_handle()) == NULL) {
3524 3609 zerror(zlogp, B_TRUE, "getting zone configuration handle");
3525 3610 return (-1);
3526 3611 }
3527 3612 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
3528 3613 zerror(zlogp, B_FALSE, "invalid configuration");
3529 3614 zonecfg_fini_handle(handle);
3530 3615 return (-1);
3531 3616 }
3532 3617
3533 3618 if (get_implicit_datasets(zlogp, &implicit_datasets) != 0) {
3534 3619 zerror(zlogp, B_FALSE, "getting implicit datasets failed");
3535 3620 goto out;
3536 3621 }
3537 3622
3538 3623 if (zonecfg_setdsent(handle) != Z_OK) {
3539 3624 zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
3540 3625 goto out;
3541 3626 }
3542 3627
3543 3628 total = 0;
3544 3629 while (zonecfg_getdsent(handle, &dstab) == Z_OK)
3545 3630 total += strlen(dstab.zone_dataset_name) + 1;
3546 3631 (void) zonecfg_enddsent(handle);
3547 3632
3548 3633 if (implicit_datasets != NULL)
3549 3634 implicit_len = strlen(implicit_datasets);
3550 3635 if (implicit_len > 0)
3551 3636 total += implicit_len + 1;
3552 3637
3553 3638 if (total == 0) {
3554 3639 error = 0;
3555 3640 goto out;
3556 3641 }
3557 3642
3558 3643 if ((str = malloc(total)) == NULL) {
3559 3644 zerror(zlogp, B_TRUE, "memory allocation failed");
3560 3645 goto out;
3561 3646 }
3562 3647
3563 3648 if (zonecfg_setdsent(handle) != Z_OK) {
3564 3649 zerror(zlogp, B_FALSE, "%s failed", "zonecfg_setdsent");
3565 3650 goto out;
3566 3651 }
3567 3652 offset = 0;
3568 3653 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
3569 3654 len = strlen(dstab.zone_dataset_name);
3570 3655 (void) strlcpy(str + offset, dstab.zone_dataset_name,
3571 3656 total - offset);
3572 3657 offset += len;
3573 3658 if (offset < total - 1)
3574 3659 str[offset++] = ',';
3575 3660 }
3576 3661 (void) zonecfg_enddsent(handle);
3577 3662
3578 3663 if (implicit_len > 0)
3579 3664 (void) strlcpy(str + offset, implicit_datasets, total - offset);
3580 3665
3581 3666 error = 0;
3582 3667 *bufp = str;
3583 3668 *bufsizep = total;
3584 3669
3585 3670 out:
3586 3671 if (error != 0 && str != NULL)
3587 3672 free(str);
3588 3673 if (handle != NULL)
3589 3674 zonecfg_fini_handle(handle);
3590 3675 if (implicit_datasets != NULL)
3591 3676 free(implicit_datasets);
3592 3677
3593 3678 return (error);
3594 3679 }
3595 3680
3596 3681 static int
3597 3682 validate_datasets(zlog_t *zlogp)
3598 3683 {
3599 3684 zone_dochandle_t handle;
3600 3685 struct zone_dstab dstab;
3601 3686 zfs_handle_t *zhp;
3602 3687 libzfs_handle_t *hdl;
3603 3688
3604 3689 if ((handle = zonecfg_init_handle()) == NULL) {
3605 3690 zerror(zlogp, B_TRUE, "getting zone configuration handle");
3606 3691 return (-1);
3607 3692 }
3608 3693 if (zonecfg_get_snapshot_handle(zone_name, handle) != Z_OK) {
3609 3694 zerror(zlogp, B_FALSE, "invalid configuration");
3610 3695 zonecfg_fini_handle(handle);
3611 3696 return (-1);
3612 3697 }
3613 3698
3614 3699 if (zonecfg_setdsent(handle) != Z_OK) {
3615 3700 zerror(zlogp, B_FALSE, "invalid configuration");
3616 3701 zonecfg_fini_handle(handle);
3617 3702 return (-1);
3618 3703 }
3619 3704
3620 3705 if ((hdl = libzfs_init()) == NULL) {
3621 3706 zerror(zlogp, B_FALSE, "opening ZFS library");
3622 3707 zonecfg_fini_handle(handle);
3623 3708 return (-1);
3624 3709 }
3625 3710
3626 3711 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
3627 3712
3628 3713 if ((zhp = zfs_open(hdl, dstab.zone_dataset_name,
3629 3714 ZFS_TYPE_FILESYSTEM)) == NULL) {
3630 3715 zerror(zlogp, B_FALSE, "cannot open ZFS dataset '%s'",
3631 3716 dstab.zone_dataset_name);
3632 3717 zonecfg_fini_handle(handle);
3633 3718 libzfs_fini(hdl);
3634 3719 return (-1);
3635 3720 }
3636 3721
3637 3722 /*
3638 3723 * Automatically set the 'zoned' property. We check the value
3639 3724 * first because we'll get EPERM if it is already set.
3640 3725 */
3641 3726 if (!zfs_prop_get_int(zhp, ZFS_PROP_ZONED) &&
3642 3727 zfs_prop_set(zhp, zfs_prop_to_name(ZFS_PROP_ZONED),
3643 3728 "on") != 0) {
3644 3729 zerror(zlogp, B_FALSE, "cannot set 'zoned' "
3645 3730 "property for ZFS dataset '%s'\n",
3646 3731 dstab.zone_dataset_name);
3647 3732 zonecfg_fini_handle(handle);
3648 3733 zfs_close(zhp);
3649 3734 libzfs_fini(hdl);
3650 3735 return (-1);
3651 3736 }
3652 3737
3653 3738 zfs_close(zhp);
3654 3739 }
3655 3740 (void) zonecfg_enddsent(handle);
3656 3741
3657 3742 zonecfg_fini_handle(handle);
3658 3743 libzfs_fini(hdl);
3659 3744
3660 3745 return (0);
3661 3746 }
3662 3747
3663 3748 /*
3664 3749 * Return true if the path is its own zfs file system. We determine this
3665 3750 * by stat-ing the path to see if it is zfs and stat-ing the parent to see
3666 3751 * if it is a different fs.
3667 3752 */
3668 3753 boolean_t
3669 3754 is_zonepath_zfs(char *zonepath)
3670 3755 {
3671 3756 int res;
3672 3757 char *path;
3673 3758 char *parent;
3674 3759 struct statvfs64 buf1, buf2;
3675 3760
3676 3761 if (statvfs64(zonepath, &buf1) != 0)
3677 3762 return (B_FALSE);
3678 3763
3679 3764 if (strcmp(buf1.f_basetype, "zfs") != 0)
3680 3765 return (B_FALSE);
3681 3766
3682 3767 if ((path = strdup(zonepath)) == NULL)
3683 3768 return (B_FALSE);
3684 3769
3685 3770 parent = dirname(path);
3686 3771 res = statvfs64(parent, &buf2);
3687 3772 free(path);
3688 3773
3689 3774 if (res != 0)
3690 3775 return (B_FALSE);
3691 3776
3692 3777 if (buf1.f_fsid == buf2.f_fsid)
3693 3778 return (B_FALSE);
3694 3779
3695 3780 return (B_TRUE);
3696 3781 }
3697 3782
3698 3783 /*
3699 3784 * Verify the MAC label in the root dataset for the zone.
3700 3785 * If the label exists, it must match the label configured for the zone.
|
↓ open down ↓ |
241 lines elided |
↑ open up ↑ |
3701 3786 * Otherwise if there's no label on the dataset, create one here.
3702 3787 */
3703 3788
3704 3789 static int
3705 3790 validate_rootds_label(zlog_t *zlogp, char *rootpath, m_label_t *zone_sl)
3706 3791 {
3707 3792 int error = -1;
3708 3793 zfs_handle_t *zhp;
3709 3794 libzfs_handle_t *hdl;
3710 3795 m_label_t ds_sl;
3711 - char zonepath[MAXPATHLEN];
3712 3796 char ds_hexsl[MAXNAMELEN];
3713 3797
3714 3798 if (!is_system_labeled())
3715 3799 return (0);
3716 3800
3717 - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
3718 - zerror(zlogp, B_TRUE, "unable to determine zone path");
3719 - return (-1);
3720 - }
3721 -
3722 3801 if (!is_zonepath_zfs(zonepath))
3723 3802 return (0);
3724 3803
3725 3804 if ((hdl = libzfs_init()) == NULL) {
3726 3805 zerror(zlogp, B_FALSE, "opening ZFS library");
3727 3806 return (-1);
3728 3807 }
3729 3808
3730 3809 if ((zhp = zfs_path_to_zhandle(hdl, rootpath,
3731 3810 ZFS_TYPE_FILESYSTEM)) == NULL) {
3732 3811 zerror(zlogp, B_FALSE, "cannot open ZFS dataset for path '%s'",
3733 3812 rootpath);
3734 3813 libzfs_fini(hdl);
3735 3814 return (-1);
3736 3815 }
3737 3816
3738 3817 /* Get the mlslabel property if it exists. */
3739 3818 if ((zfs_prop_get(zhp, ZFS_PROP_MLSLABEL, ds_hexsl, MAXNAMELEN,
3740 3819 NULL, NULL, 0, B_TRUE) != 0) ||
3741 3820 (strcmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)) {
3742 3821 char *str2 = NULL;
3743 3822
3744 3823 /*
3745 3824 * No label on the dataset (or default only); create one.
3746 3825 * (Only do this automatic labeling for the labeled brand.)
3747 3826 */
3748 3827 if (strcmp(brand_name, LABELED_BRAND_NAME) != 0) {
3749 3828 error = 0;
3750 3829 goto out;
3751 3830 }
3752 3831
3753 3832 error = l_to_str_internal(zone_sl, &str2);
3754 3833 if (error)
3755 3834 goto out;
3756 3835 if (str2 == NULL) {
3757 3836 error = -1;
3758 3837 goto out;
3759 3838 }
3760 3839 if ((error = zfs_prop_set(zhp,
3761 3840 zfs_prop_to_name(ZFS_PROP_MLSLABEL), str2)) != 0) {
3762 3841 zerror(zlogp, B_FALSE, "cannot set 'mlslabel' "
3763 3842 "property for root dataset at '%s'\n", rootpath);
3764 3843 }
3765 3844 free(str2);
3766 3845 goto out;
3767 3846 }
3768 3847
3769 3848 /* Convert the retrieved dataset label to binary form. */
3770 3849 error = hexstr_to_label(ds_hexsl, &ds_sl);
3771 3850 if (error) {
3772 3851 zerror(zlogp, B_FALSE, "invalid 'mlslabel' "
3773 3852 "property on root dataset at '%s'\n", rootpath);
3774 3853 goto out; /* exit with error */
3775 3854 }
3776 3855
3777 3856 /*
3778 3857 * Perform a MAC check by comparing the zone label with the
3779 3858 * dataset label.
3780 3859 */
3781 3860 error = (!blequal(zone_sl, &ds_sl));
3782 3861 if (error)
3783 3862 zerror(zlogp, B_FALSE, "Rootpath dataset has mismatched label");
3784 3863 out:
3785 3864 zfs_close(zhp);
3786 3865 libzfs_fini(hdl);
3787 3866
3788 3867 return (error);
3789 3868 }
3790 3869
3791 3870 /*
3792 3871 * Mount lower level home directories into/from current zone
3793 3872 * Share exported directories specified in dfstab for zone
3794 3873 */
3795 3874 static int
3796 3875 tsol_mounts(zlog_t *zlogp, char *zone_name, char *rootpath)
3797 3876 {
3798 3877 zoneid_t *zids = NULL;
3799 3878 priv_set_t *zid_privs;
3800 3879 const priv_impl_info_t *ip = NULL;
3801 3880 uint_t nzents_saved;
3802 3881 uint_t nzents;
3803 3882 int i;
3804 3883 char readonly[] = "ro";
3805 3884 struct zone_fstab lower_fstab;
3806 3885 char *argv[4];
3807 3886
3808 3887 if (!is_system_labeled())
3809 3888 return (0);
3810 3889
3811 3890 if (zid_label == NULL) {
3812 3891 zid_label = m_label_alloc(MAC_LABEL);
3813 3892 if (zid_label == NULL)
3814 3893 return (-1);
3815 3894 }
3816 3895
3817 3896 /* Make sure our zone has an /export/home dir */
3818 3897 (void) make_one_dir(zlogp, rootpath, "/export/home",
3819 3898 DEFAULT_DIR_MODE, DEFAULT_DIR_USER, DEFAULT_DIR_GROUP);
3820 3899
3821 3900 lower_fstab.zone_fs_raw[0] = '\0';
3822 3901 (void) strlcpy(lower_fstab.zone_fs_type, MNTTYPE_LOFS,
3823 3902 sizeof (lower_fstab.zone_fs_type));
3824 3903 lower_fstab.zone_fs_options = NULL;
3825 3904 (void) zonecfg_add_fs_option(&lower_fstab, readonly);
3826 3905
3827 3906 /*
3828 3907 * Get the list of zones from the kernel
3829 3908 */
3830 3909 if (zone_list(NULL, &nzents) != 0) {
3831 3910 zerror(zlogp, B_TRUE, "unable to list zones");
3832 3911 zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
3833 3912 return (-1);
3834 3913 }
3835 3914 again:
3836 3915 if (nzents == 0) {
3837 3916 zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
3838 3917 return (-1);
3839 3918 }
3840 3919
3841 3920 zids = malloc(nzents * sizeof (zoneid_t));
3842 3921 if (zids == NULL) {
3843 3922 zerror(zlogp, B_TRUE, "memory allocation failed");
3844 3923 return (-1);
3845 3924 }
3846 3925 nzents_saved = nzents;
3847 3926
3848 3927 if (zone_list(zids, &nzents) != 0) {
3849 3928 zerror(zlogp, B_TRUE, "unable to list zones");
3850 3929 zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
3851 3930 free(zids);
3852 3931 return (-1);
3853 3932 }
3854 3933 if (nzents != nzents_saved) {
3855 3934 /* list changed, try again */
3856 3935 free(zids);
3857 3936 goto again;
3858 3937 }
3859 3938
3860 3939 ip = getprivimplinfo();
3861 3940 if ((zid_privs = priv_allocset()) == NULL) {
3862 3941 zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
3863 3942 zonecfg_free_fs_option_list(
3864 3943 lower_fstab.zone_fs_options);
3865 3944 free(zids);
3866 3945 return (-1);
3867 3946 }
3868 3947
3869 3948 for (i = 0; i < nzents; i++) {
3870 3949 char zid_name[ZONENAME_MAX];
3871 3950 zone_state_t zid_state;
3872 3951 char zid_rpath[MAXPATHLEN];
3873 3952 struct stat stat_buf;
3874 3953
3875 3954 if (zids[i] == GLOBAL_ZONEID)
3876 3955 continue;
3877 3956
3878 3957 if (getzonenamebyid(zids[i], zid_name, ZONENAME_MAX) == -1)
3879 3958 continue;
3880 3959
3881 3960 /*
3882 3961 * Do special setup for the zone we are booting
3883 3962 */
3884 3963 if (strcmp(zid_name, zone_name) == 0) {
3885 3964 struct zone_fstab autofs_fstab;
3886 3965 char map_path[MAXPATHLEN];
3887 3966 int fd;
3888 3967
3889 3968 /*
3890 3969 * Create auto_home_<zone> map for this zone
3891 3970 * in the global zone. The non-global zone entry
3892 3971 * will be created by automount when the zone
3893 3972 * is booted.
3894 3973 */
3895 3974
3896 3975 (void) snprintf(autofs_fstab.zone_fs_special,
3897 3976 MAXPATHLEN, "auto_home_%s", zid_name);
3898 3977
3899 3978 (void) snprintf(autofs_fstab.zone_fs_dir, MAXPATHLEN,
3900 3979 "/zone/%s/home", zid_name);
3901 3980
3902 3981 (void) snprintf(map_path, sizeof (map_path),
3903 3982 "/etc/%s", autofs_fstab.zone_fs_special);
3904 3983 /*
3905 3984 * If the map file doesn't exist create a template
3906 3985 */
3907 3986 if ((fd = open(map_path, O_RDWR | O_CREAT | O_EXCL,
3908 3987 S_IRUSR | S_IWUSR | S_IRGRP| S_IROTH)) != -1) {
3909 3988 int len;
3910 3989 char map_rec[MAXPATHLEN];
3911 3990
3912 3991 len = snprintf(map_rec, sizeof (map_rec),
3913 3992 "+%s\n*\t-fstype=lofs\t:%s/export/home/&\n",
3914 3993 autofs_fstab.zone_fs_special, rootpath);
3915 3994 (void) write(fd, map_rec, len);
3916 3995 (void) close(fd);
3917 3996 }
3918 3997
3919 3998 /*
3920 3999 * Mount auto_home_<zone> in the global zone if absent.
3921 4000 * If it's already of type autofs, then
3922 4001 * don't mount it again.
3923 4002 */
3924 4003 if ((stat(autofs_fstab.zone_fs_dir, &stat_buf) == -1) ||
3925 4004 strcmp(stat_buf.st_fstype, MNTTYPE_AUTOFS) != 0) {
3926 4005 char optstr[] = "indirect,ignore,nobrowse";
3927 4006
3928 4007 (void) make_one_dir(zlogp, "",
3929 4008 autofs_fstab.zone_fs_dir, DEFAULT_DIR_MODE,
3930 4009 DEFAULT_DIR_USER, DEFAULT_DIR_GROUP);
3931 4010
3932 4011 /*
3933 4012 * Mount will fail if automounter has already
3934 4013 * processed the auto_home_<zonename> map
3935 4014 */
3936 4015 (void) domount(zlogp, MNTTYPE_AUTOFS, optstr,
3937 4016 autofs_fstab.zone_fs_special,
3938 4017 autofs_fstab.zone_fs_dir);
3939 4018 }
3940 4019 continue;
3941 4020 }
3942 4021
3943 4022
3944 4023 if (zone_get_state(zid_name, &zid_state) != Z_OK ||
3945 4024 (zid_state != ZONE_STATE_READY &&
3946 4025 zid_state != ZONE_STATE_RUNNING))
3947 4026 /* Skip over zones without mounted filesystems */
3948 4027 continue;
3949 4028
3950 4029 if (zone_getattr(zids[i], ZONE_ATTR_SLBL, zid_label,
3951 4030 sizeof (m_label_t)) < 0)
3952 4031 /* Skip over zones with unspecified label */
3953 4032 continue;
3954 4033
3955 4034 if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zid_rpath,
3956 4035 sizeof (zid_rpath)) == -1)
3957 4036 /* Skip over zones with bad path */
3958 4037 continue;
3959 4038
3960 4039 if (zone_getattr(zids[i], ZONE_ATTR_PRIVSET, zid_privs,
3961 4040 sizeof (priv_chunk_t) * ip->priv_setsize) == -1)
3962 4041 /* Skip over zones with bad privs */
3963 4042 continue;
3964 4043
3965 4044 /*
3966 4045 * Reading down is valid according to our label model
3967 4046 * but some customers want to disable it because it
3968 4047 * allows execute down and other possible attacks.
3969 4048 * Therefore, we restrict this feature to zones that
3970 4049 * have the NET_MAC_AWARE privilege which is required
3971 4050 * for NFS read-down semantics.
3972 4051 */
3973 4052 if ((bldominates(zlabel, zid_label)) &&
3974 4053 (priv_ismember(zprivs, PRIV_NET_MAC_AWARE))) {
3975 4054 /*
3976 4055 * Our zone dominates this one.
3977 4056 * Create a lofs mount from lower zone's /export/home
3978 4057 */
3979 4058 (void) snprintf(lower_fstab.zone_fs_dir, MAXPATHLEN,
3980 4059 "%s/zone/%s/export/home", rootpath, zid_name);
3981 4060
3982 4061 /*
3983 4062 * If the target is already an LOFS mount
3984 4063 * then don't do it again.
3985 4064 */
3986 4065 if ((stat(lower_fstab.zone_fs_dir, &stat_buf) == -1) ||
3987 4066 strcmp(stat_buf.st_fstype, MNTTYPE_LOFS) != 0) {
3988 4067
3989 4068 if (snprintf(lower_fstab.zone_fs_special,
3990 4069 MAXPATHLEN, "%s/export",
3991 4070 zid_rpath) > MAXPATHLEN)
3992 4071 continue;
3993 4072
3994 4073 /*
3995 4074 * Make sure the lower-level home exists
3996 4075 */
3997 4076 if (make_one_dir(zlogp,
3998 4077 lower_fstab.zone_fs_special, "/home",
3999 4078 DEFAULT_DIR_MODE, DEFAULT_DIR_USER,
4000 4079 DEFAULT_DIR_GROUP) != 0)
4001 4080 continue;
4002 4081
4003 4082 (void) strlcat(lower_fstab.zone_fs_special,
4004 4083 "/home", MAXPATHLEN);
4005 4084
4006 4085 /*
4007 4086 * Mount can fail because the lower-level
4008 4087 * zone may have already done a mount up.
4009 4088 */
4010 4089 (void) mount_one(zlogp, &lower_fstab, "",
4011 4090 Z_MNT_BOOT);
4012 4091 }
4013 4092 } else if ((bldominates(zid_label, zlabel)) &&
4014 4093 (priv_ismember(zid_privs, PRIV_NET_MAC_AWARE))) {
4015 4094 /*
4016 4095 * This zone dominates our zone.
4017 4096 * Create a lofs mount from our zone's /export/home
4018 4097 */
4019 4098 if (snprintf(lower_fstab.zone_fs_dir, MAXPATHLEN,
4020 4099 "%s/zone/%s/export/home", zid_rpath,
4021 4100 zone_name) > MAXPATHLEN)
4022 4101 continue;
4023 4102
4024 4103 /*
4025 4104 * If the target is already an LOFS mount
4026 4105 * then don't do it again.
4027 4106 */
4028 4107 if ((stat(lower_fstab.zone_fs_dir, &stat_buf) == -1) ||
4029 4108 strcmp(stat_buf.st_fstype, MNTTYPE_LOFS) != 0) {
4030 4109
4031 4110 (void) snprintf(lower_fstab.zone_fs_special,
4032 4111 MAXPATHLEN, "%s/export/home", rootpath);
4033 4112
4034 4113 /*
4035 4114 * Mount can fail because the higher-level
4036 4115 * zone may have already done a mount down.
4037 4116 */
4038 4117 (void) mount_one(zlogp, &lower_fstab, "",
4039 4118 Z_MNT_BOOT);
4040 4119 }
4041 4120 }
4042 4121 }
4043 4122 zonecfg_free_fs_option_list(lower_fstab.zone_fs_options);
4044 4123 priv_freeset(zid_privs);
4045 4124 free(zids);
4046 4125
4047 4126 /*
4048 4127 * Now share any exported directories from this zone.
4049 4128 * Each zone can have its own dfstab.
4050 4129 */
4051 4130
4052 4131 argv[0] = "zoneshare";
4053 4132 argv[1] = "-z";
4054 4133 argv[2] = zone_name;
4055 4134 argv[3] = NULL;
4056 4135
4057 4136 (void) forkexec(zlogp, "/usr/lib/zones/zoneshare", argv);
4058 4137 /* Don't check for errors since they don't affect the zone */
4059 4138
4060 4139 return (0);
4061 4140 }
4062 4141
4063 4142 /*
4064 4143 * Unmount lofs mounts from higher level zones
4065 4144 * Unshare nfs exported directories
4066 4145 */
4067 4146 static void
4068 4147 tsol_unmounts(zlog_t *zlogp, char *zone_name)
4069 4148 {
4070 4149 zoneid_t *zids = NULL;
4071 4150 uint_t nzents_saved;
4072 4151 uint_t nzents;
4073 4152 int i;
4074 4153 char *argv[4];
4075 4154 char path[MAXPATHLEN];
4076 4155
4077 4156 if (!is_system_labeled())
4078 4157 return;
4079 4158
4080 4159 /*
4081 4160 * Get the list of zones from the kernel
4082 4161 */
4083 4162 if (zone_list(NULL, &nzents) != 0) {
4084 4163 return;
4085 4164 }
4086 4165
4087 4166 if (zid_label == NULL) {
4088 4167 zid_label = m_label_alloc(MAC_LABEL);
4089 4168 if (zid_label == NULL)
4090 4169 return;
4091 4170 }
4092 4171
4093 4172 again:
4094 4173 if (nzents == 0)
4095 4174 return;
4096 4175
4097 4176 zids = malloc(nzents * sizeof (zoneid_t));
4098 4177 if (zids == NULL) {
4099 4178 zerror(zlogp, B_TRUE, "memory allocation failed");
4100 4179 return;
4101 4180 }
4102 4181 nzents_saved = nzents;
4103 4182
4104 4183 if (zone_list(zids, &nzents) != 0) {
4105 4184 free(zids);
4106 4185 return;
4107 4186 }
4108 4187 if (nzents != nzents_saved) {
4109 4188 /* list changed, try again */
4110 4189 free(zids);
4111 4190 goto again;
4112 4191 }
4113 4192
4114 4193 for (i = 0; i < nzents; i++) {
4115 4194 char zid_name[ZONENAME_MAX];
4116 4195 zone_state_t zid_state;
4117 4196 char zid_rpath[MAXPATHLEN];
4118 4197
4119 4198 if (zids[i] == GLOBAL_ZONEID)
4120 4199 continue;
4121 4200
4122 4201 if (getzonenamebyid(zids[i], zid_name, ZONENAME_MAX) == -1)
4123 4202 continue;
4124 4203
4125 4204 /*
4126 4205 * Skip the zone we are halting
4127 4206 */
4128 4207 if (strcmp(zid_name, zone_name) == 0)
4129 4208 continue;
4130 4209
4131 4210 if ((zone_getattr(zids[i], ZONE_ATTR_STATUS, &zid_state,
4132 4211 sizeof (zid_state)) < 0) ||
4133 4212 (zid_state < ZONE_IS_READY))
4134 4213 /* Skip over zones without mounted filesystems */
4135 4214 continue;
4136 4215
4137 4216 if (zone_getattr(zids[i], ZONE_ATTR_SLBL, zid_label,
4138 4217 sizeof (m_label_t)) < 0)
4139 4218 /* Skip over zones with unspecified label */
4140 4219 continue;
4141 4220
4142 4221 if (zone_getattr(zids[i], ZONE_ATTR_ROOT, zid_rpath,
4143 4222 sizeof (zid_rpath)) == -1)
4144 4223 /* Skip over zones with bad path */
4145 4224 continue;
4146 4225
4147 4226 if (zlabel != NULL && bldominates(zid_label, zlabel)) {
4148 4227 /*
4149 4228 * This zone dominates our zone.
4150 4229 * Unmount the lofs mount of our zone's /export/home
4151 4230 */
4152 4231
4153 4232 if (snprintf(path, MAXPATHLEN,
4154 4233 "%s/zone/%s/export/home", zid_rpath,
4155 4234 zone_name) > MAXPATHLEN)
4156 4235 continue;
4157 4236
4158 4237 /* Skip over mount failures */
4159 4238 (void) umount(path);
4160 4239 }
4161 4240 }
4162 4241 free(zids);
4163 4242
4164 4243 /*
4165 4244 * Unmount global zone autofs trigger for this zone
4166 4245 */
4167 4246 (void) snprintf(path, MAXPATHLEN, "/zone/%s/home", zone_name);
4168 4247 /* Skip over mount failures */
4169 4248 (void) umount(path);
4170 4249
4171 4250 /*
4172 4251 * Next unshare any exported directories from this zone.
4173 4252 */
4174 4253
4175 4254 argv[0] = "zoneunshare";
4176 4255 argv[1] = "-z";
4177 4256 argv[2] = zone_name;
4178 4257 argv[3] = NULL;
4179 4258
4180 4259 (void) forkexec(zlogp, "/usr/lib/zones/zoneunshare", argv);
4181 4260 /* Don't check for errors since they don't affect the zone */
4182 4261
4183 4262 /*
4184 4263 * Finally, deallocate any devices in the zone.
4185 4264 */
4186 4265
4187 4266 argv[0] = "deallocate";
4188 4267 argv[1] = "-Isz";
4189 4268 argv[2] = zone_name;
4190 4269 argv[3] = NULL;
4191 4270
4192 4271 (void) forkexec(zlogp, "/usr/sbin/deallocate", argv);
4193 4272 /* Don't check for errors since they don't affect the zone */
4194 4273 }
4195 4274
4196 4275 /*
4197 4276 * Fetch the Trusted Extensions label and multi-level ports (MLPs) for
4198 4277 * this zone.
4199 4278 */
4200 4279 static tsol_zcent_t *
4201 4280 get_zone_label(zlog_t *zlogp, priv_set_t *privs)
4202 4281 {
4203 4282 FILE *fp;
4204 4283 tsol_zcent_t *zcent = NULL;
4205 4284 char line[MAXTNZLEN];
4206 4285
4207 4286 if ((fp = fopen(TNZONECFG_PATH, "r")) == NULL) {
4208 4287 zerror(zlogp, B_TRUE, "%s", TNZONECFG_PATH);
4209 4288 return (NULL);
4210 4289 }
4211 4290
4212 4291 while (fgets(line, sizeof (line), fp) != NULL) {
4213 4292 /*
4214 4293 * Check for malformed database
4215 4294 */
4216 4295 if (strlen(line) == MAXTNZLEN - 1)
4217 4296 break;
4218 4297 if ((zcent = tsol_sgetzcent(line, NULL, NULL)) == NULL)
4219 4298 continue;
4220 4299 if (strcmp(zcent->zc_name, zone_name) == 0)
4221 4300 break;
4222 4301 tsol_freezcent(zcent);
4223 4302 zcent = NULL;
4224 4303 }
4225 4304 (void) fclose(fp);
4226 4305
4227 4306 if (zcent == NULL) {
4228 4307 zerror(zlogp, B_FALSE, "zone requires a label assignment. "
4229 4308 "See tnzonecfg(4)");
4230 4309 } else {
4231 4310 if (zlabel == NULL)
4232 4311 zlabel = m_label_alloc(MAC_LABEL);
4233 4312 /*
4234 4313 * Save this zone's privileges for later read-down processing
4235 4314 */
4236 4315 if ((zprivs = priv_allocset()) == NULL) {
4237 4316 zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
4238 4317 return (NULL);
4239 4318 } else {
4240 4319 priv_copyset(privs, zprivs);
4241 4320 }
4242 4321 }
4243 4322 return (zcent);
4244 4323 }
4245 4324
4246 4325 /*
4247 4326 * Add the Trusted Extensions multi-level ports for this zone.
4248 4327 */
4249 4328 static void
4250 4329 set_mlps(zlog_t *zlogp, zoneid_t zoneid, tsol_zcent_t *zcent)
4251 4330 {
4252 4331 tsol_mlp_t *mlp;
4253 4332 tsol_mlpent_t tsme;
4254 4333
4255 4334 if (!is_system_labeled())
4256 4335 return;
4257 4336
4258 4337 tsme.tsme_zoneid = zoneid;
4259 4338 tsme.tsme_flags = 0;
4260 4339 for (mlp = zcent->zc_private_mlp; !TSOL_MLP_END(mlp); mlp++) {
4261 4340 tsme.tsme_mlp = *mlp;
4262 4341 if (tnmlp(TNDB_LOAD, &tsme) != 0) {
4263 4342 zerror(zlogp, B_TRUE, "cannot set zone-specific MLP "
4264 4343 "on %d-%d/%d", mlp->mlp_port,
4265 4344 mlp->mlp_port_upper, mlp->mlp_ipp);
4266 4345 }
4267 4346 }
4268 4347
4269 4348 tsme.tsme_flags = TSOL_MEF_SHARED;
4270 4349 for (mlp = zcent->zc_shared_mlp; !TSOL_MLP_END(mlp); mlp++) {
4271 4350 tsme.tsme_mlp = *mlp;
4272 4351 if (tnmlp(TNDB_LOAD, &tsme) != 0) {
4273 4352 zerror(zlogp, B_TRUE, "cannot set shared MLP "
4274 4353 "on %d-%d/%d", mlp->mlp_port,
4275 4354 mlp->mlp_port_upper, mlp->mlp_ipp);
4276 4355 }
4277 4356 }
4278 4357 }
4279 4358
4280 4359 static void
4281 4360 remove_mlps(zlog_t *zlogp, zoneid_t zoneid)
4282 4361 {
4283 4362 tsol_mlpent_t tsme;
4284 4363
4285 4364 if (!is_system_labeled())
4286 4365 return;
4287 4366
4288 4367 (void) memset(&tsme, 0, sizeof (tsme));
4289 4368 tsme.tsme_zoneid = zoneid;
4290 4369 if (tnmlp(TNDB_FLUSH, &tsme) != 0)
4291 4370 zerror(zlogp, B_TRUE, "cannot flush MLPs");
4292 4371 }
4293 4372
4294 4373 int
4295 4374 prtmount(const struct mnttab *fs, void *x)
4296 4375 {
4297 4376 zerror((zlog_t *)x, B_FALSE, " %s", fs->mnt_mountp);
4298 4377 return (0);
4299 4378 }
4300 4379
4301 4380 /*
4302 4381 * Look for zones running on the main system that are using this root (or any
4303 4382 * subdirectory of it). Return B_TRUE and print an error if a conflicting zone
4304 4383 * is found or if we can't tell.
4305 4384 */
4306 4385 static boolean_t
4307 4386 duplicate_zone_root(zlog_t *zlogp, const char *rootpath)
4308 4387 {
4309 4388 zoneid_t *zids = NULL;
4310 4389 uint_t nzids = 0;
4311 4390 boolean_t retv;
4312 4391 int rlen, zlen;
4313 4392 char zroot[MAXPATHLEN];
4314 4393 char zonename[ZONENAME_MAX];
4315 4394
4316 4395 for (;;) {
4317 4396 nzids += 10;
4318 4397 zids = malloc(nzids * sizeof (*zids));
4319 4398 if (zids == NULL) {
4320 4399 zerror(zlogp, B_TRUE, "memory allocation failed");
4321 4400 return (B_TRUE);
4322 4401 }
4323 4402 if (zone_list(zids, &nzids) == 0)
4324 4403 break;
4325 4404 free(zids);
4326 4405 }
4327 4406 retv = B_FALSE;
4328 4407 rlen = strlen(rootpath);
4329 4408 while (nzids > 0) {
4330 4409 /*
4331 4410 * Ignore errors; they just mean that the zone has disappeared
4332 4411 * while we were busy.
4333 4412 */
4334 4413 if (zone_getattr(zids[--nzids], ZONE_ATTR_ROOT, zroot,
4335 4414 sizeof (zroot)) == -1)
4336 4415 continue;
4337 4416 zlen = strlen(zroot);
4338 4417 if (zlen > rlen)
4339 4418 zlen = rlen;
4340 4419 if (strncmp(rootpath, zroot, zlen) == 0 &&
4341 4420 (zroot[zlen] == '\0' || zroot[zlen] == '/') &&
4342 4421 (rootpath[zlen] == '\0' || rootpath[zlen] == '/')) {
4343 4422 if (getzonenamebyid(zids[nzids], zonename,
4344 4423 sizeof (zonename)) == -1)
4345 4424 (void) snprintf(zonename, sizeof (zonename),
4346 4425 "id %d", (int)zids[nzids]);
4347 4426 zerror(zlogp, B_FALSE,
4348 4427 "zone root %s already in use by zone %s",
4349 4428 rootpath, zonename);
4350 4429 retv = B_TRUE;
4351 4430 break;
4352 4431 }
4353 4432 }
4354 4433 free(zids);
4355 4434 return (retv);
4356 4435 }
4357 4436
4358 4437 /*
4359 4438 * Search for loopback mounts that use this same source node (same device and
4360 4439 * inode). Return B_TRUE if there is one or if we can't tell.
4361 4440 */
4362 4441 static boolean_t
4363 4442 duplicate_reachable_path(zlog_t *zlogp, const char *rootpath)
4364 4443 {
4365 4444 struct stat64 rst, zst;
4366 4445 struct mnttab *mnp;
4367 4446
4368 4447 if (stat64(rootpath, &rst) == -1) {
4369 4448 zerror(zlogp, B_TRUE, "can't stat %s", rootpath);
4370 4449 return (B_TRUE);
4371 4450 }
4372 4451 if (resolve_lofs_mnts == NULL && lofs_read_mnttab(zlogp) == -1)
4373 4452 return (B_TRUE);
4374 4453 for (mnp = resolve_lofs_mnts; mnp < resolve_lofs_mnt_max; mnp++) {
4375 4454 if (mnp->mnt_fstype == NULL ||
4376 4455 strcmp(MNTTYPE_LOFS, mnp->mnt_fstype) != 0)
4377 4456 continue;
4378 4457 /* We're looking at a loopback mount. Stat it. */
4379 4458 if (mnp->mnt_special != NULL &&
4380 4459 stat64(mnp->mnt_special, &zst) != -1 &&
4381 4460 rst.st_dev == zst.st_dev && rst.st_ino == zst.st_ino) {
|
↓ open down ↓ |
650 lines elided |
↑ open up ↑ |
4382 4461 zerror(zlogp, B_FALSE,
4383 4462 "zone root %s is reachable through %s",
4384 4463 rootpath, mnp->mnt_mountp);
4385 4464 return (B_TRUE);
4386 4465 }
4387 4466 }
4388 4467 return (B_FALSE);
4389 4468 }
4390 4469
4391 4470 /*
4392 - * Set memory cap and pool info for the zone's resource management
4393 - * configuration.
4471 + * Set pool info for the zone's resource management configuration.
4394 4472 */
4395 4473 static int
4396 4474 setup_zone_rm(zlog_t *zlogp, char *zone_name, zoneid_t zoneid)
4397 4475 {
4398 4476 int res;
4399 4477 uint64_t tmp;
4400 - struct zone_mcaptab mcap;
4401 4478 char sched[MAXNAMELEN];
4402 4479 zone_dochandle_t handle = NULL;
4403 4480 char pool_err[128];
4404 4481
4405 4482 if ((handle = zonecfg_init_handle()) == NULL) {
4406 4483 zerror(zlogp, B_TRUE, "getting zone configuration handle");
4407 4484 return (Z_BAD_HANDLE);
4408 4485 }
4409 4486
4410 4487 if ((res = zonecfg_get_snapshot_handle(zone_name, handle)) != Z_OK) {
4411 4488 zerror(zlogp, B_FALSE, "invalid configuration");
4412 4489 zonecfg_fini_handle(handle);
4413 4490 return (res);
4414 4491 }
4415 4492
4416 - /*
4417 - * If a memory cap is configured, set the cap in the kernel using
4418 - * zone_setattr() and make sure the rcapd SMF service is enabled.
4419 - */
4420 - if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
4421 - uint64_t num;
4422 - char smf_err[128];
4423 -
4424 - num = (uint64_t)strtoull(mcap.zone_physmem_cap, NULL, 10);
4425 - if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
4426 - zerror(zlogp, B_TRUE, "could not set zone memory cap");
4427 - zonecfg_fini_handle(handle);
4428 - return (Z_INVAL);
4429 - }
4430 -
4431 - if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
4432 - zerror(zlogp, B_FALSE, "enabling system/rcap service "
4433 - "failed: %s", smf_err);
4434 - zonecfg_fini_handle(handle);
4435 - return (Z_INVAL);
4436 - }
4437 - }
4438 -
4439 4493 /* Get the scheduling class set in the zone configuration. */
4440 4494 if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
4441 4495 strlen(sched) > 0) {
4442 4496 if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, sched,
4443 4497 strlen(sched)) == -1)
4444 4498 zerror(zlogp, B_TRUE, "WARNING: unable to set the "
4445 4499 "default scheduling class");
4446 4500
4447 - } else if (zonecfg_get_aliased_rctl(handle, ALIAS_SHARES, &tmp)
4501 + if (strcmp(sched, "FX") == 0) {
4502 + /*
4503 + * When FX is specified then by default all processes
4504 + * will start at the lowest priority level (0) and
4505 + * stay there. We support an optional attr which
4506 + * indicates that all the processes should be "high
4507 + * priority". We set this on the zone so that starting
4508 + * init will set the priority high.
4509 + */
4510 + struct zone_attrtab a;
4511 +
4512 + bzero(&a, sizeof (a));
4513 + (void) strlcpy(a.zone_attr_name, "fixed-hi-prio",
4514 + sizeof (a.zone_attr_name));
4515 +
4516 + if (zonecfg_lookup_attr(snap_hndl, &a) == Z_OK &&
4517 + strcmp(a.zone_attr_value, "true") == 0) {
4518 + boolean_t hi = B_TRUE;
4519 +
4520 + if (zone_setattr(zoneid,
4521 + ZONE_ATTR_SCHED_FIXEDHI, (void *)hi,
4522 + sizeof (hi)) == -1)
4523 + zerror(zlogp, B_TRUE, "WARNING: unable "
4524 + "to set high priority");
4525 + }
4526 + }
4527 +
4528 + } else if (zonecfg_get_aliased_rctl(snap_hndl, ALIAS_SHARES, &tmp)
4448 4529 == Z_OK) {
4449 4530 /*
4450 4531 * If the zone has the zone.cpu-shares rctl set then we want to
4451 4532 * use the Fair Share Scheduler (FSS) for processes in the
4452 4533 * zone. Check what scheduling class the zone would be running
4453 4534 * in by default so we can print a warning and modify the class
4454 4535 * if we wouldn't be using FSS.
4455 4536 */
4456 4537 char class_name[PC_CLNMSZ];
4457 4538
4458 4539 if (zonecfg_get_dflt_sched_class(handle, class_name,
4459 4540 sizeof (class_name)) != Z_OK) {
4460 4541 zerror(zlogp, B_FALSE, "WARNING: unable to determine "
4461 4542 "the zone's scheduling class");
4462 4543
4463 4544 } else if (strcmp("FSS", class_name) != 0) {
4464 4545 zerror(zlogp, B_FALSE, "WARNING: The zone.cpu-shares "
4465 4546 "rctl is set but\nFSS is not the default "
4466 4547 "scheduling class for\nthis zone. FSS will be "
4467 4548 "used for processes\nin the zone but to get the "
4468 4549 "full benefit of FSS,\nit should be the default "
4469 4550 "scheduling class.\nSee dispadmin(1M) for more "
4470 4551 "details.");
4471 4552
4472 4553 if (zone_setattr(zoneid, ZONE_ATTR_SCHED_CLASS, "FSS",
4473 4554 strlen("FSS")) == -1)
4474 4555 zerror(zlogp, B_TRUE, "WARNING: unable to set "
4475 4556 "zone scheduling class to FSS");
4476 4557 }
4477 4558 }
4478 4559
4479 4560 /*
4480 4561 * The next few blocks of code attempt to set up temporary pools as
4481 4562 * well as persistent pools. In all cases we call the functions
4482 4563 * unconditionally. Within each funtion the code will check if the
4483 4564 * zone is actually configured for a temporary pool or persistent pool
4484 4565 * and just return if there is nothing to do.
4485 4566 *
4486 4567 * If we are rebooting we want to attempt to reuse any temporary pool
4487 4568 * that was previously set up. zonecfg_bind_tmp_pool() will do the
4488 4569 * right thing in all cases (reuse or create) based on the current
4489 4570 * zonecfg.
4490 4571 */
4491 4572 if ((res = zonecfg_bind_tmp_pool(handle, zoneid, pool_err,
4492 4573 sizeof (pool_err))) != Z_OK) {
4493 4574 if (res == Z_POOL || res == Z_POOL_CREATE || res == Z_POOL_BIND)
4494 4575 zerror(zlogp, B_FALSE, "%s: %s\ndedicated-cpu setting "
4495 4576 "cannot be instantiated", zonecfg_strerror(res),
4496 4577 pool_err);
4497 4578 else
4498 4579 zerror(zlogp, B_FALSE, "could not bind zone to "
4499 4580 "temporary pool: %s", zonecfg_strerror(res));
4500 4581 zonecfg_fini_handle(handle);
4501 4582 return (Z_POOL_BIND);
4502 4583 }
4503 4584
4504 4585 /*
4505 4586 * Check if we need to warn about poold not being enabled.
4506 4587 */
4507 4588 if (zonecfg_warn_poold(handle)) {
4508 4589 zerror(zlogp, B_FALSE, "WARNING: A range of dedicated-cpus has "
4509 4590 "been specified\nbut the dynamic pool service is not "
4510 4591 "enabled.\nThe system will not dynamically adjust the\n"
4511 4592 "processor allocation within the specified range\n"
4512 4593 "until svc:/system/pools/dynamic is enabled.\n"
4513 4594 "See poold(1M).");
4514 4595 }
4515 4596
4516 4597 /* The following is a warning, not an error. */
4517 4598 if ((res = zonecfg_bind_pool(handle, zoneid, pool_err,
4518 4599 sizeof (pool_err))) != Z_OK) {
4519 4600 if (res == Z_POOL_BIND)
4520 4601 zerror(zlogp, B_FALSE, "WARNING: unable to bind to "
4521 4602 "pool '%s'; using default pool.", pool_err);
4522 4603 else if (res == Z_POOL)
4523 4604 zerror(zlogp, B_FALSE, "WARNING: %s: %s",
4524 4605 zonecfg_strerror(res), pool_err);
4525 4606 else
4526 4607 zerror(zlogp, B_FALSE, "WARNING: %s",
4527 4608 zonecfg_strerror(res));
4528 4609 }
4529 4610
4530 4611 /* Update saved pool name in case it has changed */
4531 4612 (void) zonecfg_get_poolname(handle, zone_name, pool_name,
4532 4613 sizeof (pool_name));
4533 4614
4534 4615 zonecfg_fini_handle(handle);
4535 4616 return (Z_OK);
4536 4617 }
4537 4618
4538 4619 static void
4539 4620 report_prop_err(zlog_t *zlogp, const char *name, const char *value, int res)
4540 4621 {
4541 4622 switch (res) {
4542 4623 case Z_TOO_BIG:
4543 4624 zerror(zlogp, B_FALSE, "%s property value is too large.", name);
4544 4625 break;
4545 4626
4546 4627 case Z_INVALID_PROPERTY:
4547 4628 zerror(zlogp, B_FALSE, "%s property value \"%s\" is not valid",
4548 4629 name, value);
4549 4630 break;
4550 4631
4551 4632 default:
4552 4633 zerror(zlogp, B_TRUE, "fetching property %s: %d", name, res);
4553 4634 break;
4554 4635 }
4555 4636 }
4556 4637
4557 4638 /*
4558 4639 * Sets the hostid of the new zone based on its configured value. The zone's
4559 4640 * zone_t structure must already exist in kernel memory. 'zlogp' refers to the
4560 4641 * log used to report errors and warnings and must be non-NULL. 'zone_namep'
4561 4642 * is the name of the new zone and must be non-NULL. 'zoneid' is the numeric
4562 4643 * ID of the new zone.
4563 4644 *
4564 4645 * This function returns zero on success and a nonzero error code on failure.
4565 4646 */
4566 4647 static int
4567 4648 setup_zone_hostid(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
4568 4649 {
4569 4650 int res;
4570 4651 char hostidp[HW_HOSTID_LEN];
4571 4652 unsigned int hostid;
4572 4653
4573 4654 res = zonecfg_get_hostid(handle, hostidp, sizeof (hostidp));
4574 4655
4575 4656 if (res == Z_BAD_PROPERTY) {
4576 4657 return (Z_OK);
4577 4658 } else if (res != Z_OK) {
4578 4659 report_prop_err(zlogp, "hostid", hostidp, res);
4579 4660 return (res);
4580 4661 }
4581 4662
4582 4663 hostid = (unsigned int)strtoul(hostidp, NULL, 16);
4583 4664 if ((res = zone_setattr(zoneid, ZONE_ATTR_HOSTID, &hostid,
4584 4665 sizeof (hostid))) != 0) {
4585 4666 zerror(zlogp, B_TRUE,
4586 4667 "zone hostid is not valid: %s: %d", hostidp, res);
4587 4668 return (Z_SYSTEM);
4588 4669 }
4589 4670
4590 4671 return (res);
4591 4672 }
4592 4673
4593 4674 static int
4594 4675 setup_zone_fs_allowed(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
4595 4676 {
4596 4677 char fsallowed[ZONE_FS_ALLOWED_MAX];
4597 4678 char *fsallowedp = fsallowed;
4598 4679 int len = sizeof (fsallowed);
4599 4680 int res;
4600 4681
4601 4682 res = zonecfg_get_fs_allowed(handle, fsallowed, len);
4602 4683
4603 4684 if (res == Z_BAD_PROPERTY) {
4604 4685 /* No value, set the defaults */
4605 4686 (void) strlcpy(fsallowed, DFLT_FS_ALLOWED, len);
4606 4687 } else if (res != Z_OK) {
4607 4688 report_prop_err(zlogp, "fs-allowed", fsallowed, res);
4608 4689 return (res);
4609 4690 } else if (fsallowed[0] == '-') {
4610 4691 /* dropping default privs - use remaining list */
4611 4692 if (fsallowed[1] != ',')
4612 4693 return (Z_OK);
4613 4694 fsallowedp += 2;
4614 4695 len -= 2;
4615 4696 } else {
4616 4697 /* Has a value, append the defaults */
4617 4698 if (strlcat(fsallowed, ",", len) >= len ||
4618 4699 strlcat(fsallowed, DFLT_FS_ALLOWED, len) >= len) {
4619 4700 report_prop_err(zlogp, "fs-allowed", fsallowed,
4620 4701 Z_TOO_BIG);
4621 4702 return (Z_TOO_BIG);
4622 4703 }
4623 4704 }
4624 4705
4625 4706 if (zone_setattr(zoneid, ZONE_ATTR_FS_ALLOWED, fsallowedp, len) != 0) {
4626 4707 zerror(zlogp, B_TRUE,
4627 4708 "fs-allowed couldn't be set: %s: %d", fsallowedp, res);
4628 4709 return (Z_SYSTEM);
4629 4710 }
4630 4711
4631 4712 return (Z_OK);
4632 4713 }
4633 4714
4634 4715 static int
4635 4716 setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid)
4636 4717 {
4637 4718 zone_dochandle_t handle;
4638 4719 int res = Z_OK;
4639 4720
4640 4721 if ((handle = zonecfg_init_handle()) == NULL) {
4641 4722 zerror(zlogp, B_TRUE, "getting zone configuration handle");
4642 4723 return (Z_BAD_HANDLE);
4643 4724 }
4644 4725 if ((res = zonecfg_get_snapshot_handle(zone_namep, handle)) != Z_OK) {
4645 4726 zerror(zlogp, B_FALSE, "invalid configuration");
4646 4727 goto out;
4647 4728 }
4648 4729
4649 4730 if ((res = setup_zone_hostid(handle, zlogp, zoneid)) != Z_OK)
4650 4731 goto out;
4651 4732
4652 4733 if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK)
4653 4734 goto out;
4654 4735
4655 4736 out:
4656 4737 zonecfg_fini_handle(handle);
4657 4738 return (res);
4658 4739 }
4659 4740
4660 4741 zoneid_t
4661 4742 vplat_create(zlog_t *zlogp, zone_mnt_t mount_cmd)
4662 4743 {
4663 4744 zoneid_t rval = -1;
4664 4745 priv_set_t *privs;
4665 4746 char rootpath[MAXPATHLEN];
4666 4747 char *rctlbuf = NULL;
4667 4748 size_t rctlbufsz = 0;
4668 4749 char *zfsbuf = NULL;
4669 4750 size_t zfsbufsz = 0;
4670 4751 zoneid_t zoneid = -1;
4671 4752 int xerr;
4672 4753 char *kzone;
4673 4754 FILE *fp = NULL;
4674 4755 tsol_zcent_t *zcent = NULL;
4675 4756 int match = 0;
4676 4757 int doi = 0;
4677 4758 int flags;
4678 4759 zone_iptype_t iptype;
4679 4760
4680 4761 if (zone_get_rootpath(zone_name, rootpath, sizeof (rootpath)) != Z_OK) {
4681 4762 zerror(zlogp, B_TRUE, "unable to determine zone root");
4682 4763 return (-1);
4683 4764 }
4684 4765 if (zonecfg_in_alt_root())
4685 4766 resolve_lofs(zlogp, rootpath, sizeof (rootpath));
4686 4767
4687 4768 if (vplat_get_iptype(zlogp, &iptype) < 0) {
4688 4769 zerror(zlogp, B_TRUE, "unable to determine ip-type");
4689 4770 return (-1);
4690 4771 }
4691 4772 switch (iptype) {
4692 4773 case ZS_SHARED:
4693 4774 flags = 0;
4694 4775 break;
4695 4776 case ZS_EXCLUSIVE:
4696 4777 flags = ZCF_NET_EXCL;
4697 4778 break;
4698 4779 }
4699 4780
4700 4781 if ((privs = priv_allocset()) == NULL) {
4701 4782 zerror(zlogp, B_TRUE, "%s failed", "priv_allocset");
4702 4783 return (-1);
4703 4784 }
4704 4785 priv_emptyset(privs);
4705 4786 if (get_privset(zlogp, privs, mount_cmd) != 0)
4706 4787 goto error;
4707 4788
4708 4789 if (mount_cmd == Z_MNT_BOOT &&
4709 4790 get_rctls(zlogp, &rctlbuf, &rctlbufsz) != 0) {
4710 4791 zerror(zlogp, B_FALSE, "Unable to get list of rctls");
4711 4792 goto error;
4712 4793 }
4713 4794
4714 4795 if (get_datasets(zlogp, &zfsbuf, &zfsbufsz) != 0) {
4715 4796 zerror(zlogp, B_FALSE, "Unable to get list of ZFS datasets");
4716 4797 goto error;
4717 4798 }
4718 4799
4719 4800 if (mount_cmd == Z_MNT_BOOT && is_system_labeled()) {
4720 4801 zcent = get_zone_label(zlogp, privs);
4721 4802 if (zcent != NULL) {
4722 4803 match = zcent->zc_match;
4723 4804 doi = zcent->zc_doi;
4724 4805 *zlabel = zcent->zc_label;
4725 4806 } else {
4726 4807 goto error;
4727 4808 }
4728 4809 if (validate_rootds_label(zlogp, rootpath, zlabel) != 0)
4729 4810 goto error;
4730 4811 }
4731 4812
4732 4813 kzone = zone_name;
4733 4814
4734 4815 /*
4735 4816 * We must do this scan twice. First, we look for zones running on the
4736 4817 * main system that are using this root (or any subdirectory of it).
4737 4818 * Next, we reduce to the shortest path and search for loopback mounts
4738 4819 * that use this same source node (same device and inode).
4739 4820 */
4740 4821 if (duplicate_zone_root(zlogp, rootpath))
4741 4822 goto error;
4742 4823 if (duplicate_reachable_path(zlogp, rootpath))
4743 4824 goto error;
4744 4825
4745 4826 if (ALT_MOUNT(mount_cmd)) {
4746 4827 root_to_lu(zlogp, rootpath, sizeof (rootpath), B_TRUE);
4747 4828
4748 4829 /*
4749 4830 * Forge up a special root for this zone. When a zone is
4750 4831 * mounted, we can't let the zone have its own root because the
4751 4832 * tools that will be used in this "scratch zone" need access
4752 4833 * to both the zone's resources and the running machine's
4753 4834 * executables.
4754 4835 *
4755 4836 * Note that the mkdir here also catches read-only filesystems.
4756 4837 */
4757 4838 if (mkdir(rootpath, 0755) != 0 && errno != EEXIST) {
4758 4839 zerror(zlogp, B_TRUE, "cannot create %s", rootpath);
4759 4840 goto error;
4760 4841 }
4761 4842 if (domount(zlogp, "tmpfs", "", "swap", rootpath) != 0)
4762 4843 goto error;
4763 4844 }
4764 4845
4765 4846 if (zonecfg_in_alt_root()) {
4766 4847 /*
4767 4848 * If we are mounting up a zone in an alternate root partition,
4768 4849 * then we have some additional work to do before starting the
4769 4850 * zone. First, resolve the root path down so that we're not
4770 4851 * fooled by duplicates. Then forge up an internal name for
4771 4852 * the zone.
4772 4853 */
4773 4854 if ((fp = zonecfg_open_scratch("", B_TRUE)) == NULL) {
4774 4855 zerror(zlogp, B_TRUE, "cannot open mapfile");
4775 4856 goto error;
4776 4857 }
4777 4858 if (zonecfg_lock_scratch(fp) != 0) {
4778 4859 zerror(zlogp, B_TRUE, "cannot lock mapfile");
4779 4860 goto error;
4780 4861 }
4781 4862 if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(),
4782 4863 NULL, 0) == 0) {
4783 4864 zerror(zlogp, B_FALSE, "scratch zone already running");
4784 4865 goto error;
4785 4866 }
4786 4867 /* This is the preferred name */
4787 4868 (void) snprintf(kernzone, sizeof (kernzone), "SUNWlu-%s",
4788 4869 zone_name);
4789 4870 srandom(getpid());
4790 4871 while (zonecfg_reverse_scratch(fp, kernzone, NULL, 0, NULL,
4791 4872 0) == 0) {
4792 4873 /* This is just an arbitrary name; note "." usage */
4793 4874 (void) snprintf(kernzone, sizeof (kernzone),
4794 4875 "SUNWlu.%08lX%08lX", random(), random());
4795 4876 }
4796 4877 kzone = kernzone;
4797 4878 }
4798 4879
4799 4880 xerr = 0;
4800 4881 if ((zoneid = zone_create(kzone, rootpath, privs, rctlbuf,
4801 4882 rctlbufsz, zfsbuf, zfsbufsz, &xerr, match, doi, zlabel,
4802 4883 flags)) == -1) {
4803 4884 if (xerr == ZE_AREMOUNTS) {
4804 4885 if (zonecfg_find_mounts(rootpath, NULL, NULL) < 1) {
4805 4886 zerror(zlogp, B_FALSE,
4806 4887 "An unknown file-system is mounted on "
4807 4888 "a subdirectory of %s", rootpath);
4808 4889 } else {
4809 4890
4810 4891 zerror(zlogp, B_FALSE,
4811 4892 "These file-systems are mounted on "
4812 4893 "subdirectories of %s:", rootpath);
4813 4894 (void) zonecfg_find_mounts(rootpath,
4814 4895 prtmount, zlogp);
4815 4896 }
4816 4897 } else if (xerr == ZE_CHROOTED) {
4817 4898 zerror(zlogp, B_FALSE, "%s: "
4818 4899 "cannot create a zone from a chrooted "
4819 4900 "environment", "zone_create");
4820 4901 } else if (xerr == ZE_LABELINUSE) {
4821 4902 char zonename[ZONENAME_MAX];
4822 4903 (void) getzonenamebyid(getzoneidbylabel(zlabel),
4823 4904 zonename, ZONENAME_MAX);
4824 4905 zerror(zlogp, B_FALSE, "The zone label is already "
4825 4906 "used by the zone '%s'.", zonename);
4826 4907 } else {
4827 4908 zerror(zlogp, B_TRUE, "%s failed", "zone_create");
4828 4909 }
4829 4910 goto error;
4830 4911 }
4831 4912
4832 4913 if (zonecfg_in_alt_root() &&
4833 4914 zonecfg_add_scratch(fp, zone_name, kernzone,
4834 4915 zonecfg_get_root()) == -1) {
4835 4916 zerror(zlogp, B_TRUE, "cannot add mapfile entry");
4836 4917 goto error;
4837 4918 }
4838 4919
4839 4920 /*
4840 4921 * The following actions are not performed when merely mounting a zone
4841 4922 * for administrative use.
4842 4923 */
4843 4924 if (mount_cmd == Z_MNT_BOOT) {
4844 4925 brand_handle_t bh;
4845 4926 struct brand_attr attr;
4846 4927 char modname[MAXPATHLEN];
4847 4928
4848 4929 if (setup_zone_attrs(zlogp, zone_name, zoneid) != Z_OK)
4849 4930 goto error;
4850 4931
4851 4932 if ((bh = brand_open(brand_name)) == NULL) {
4852 4933 zerror(zlogp, B_FALSE,
4853 4934 "unable to determine brand name");
4854 4935 goto error;
4855 4936 }
4856 4937
4857 4938 if (!is_system_labeled() &&
4858 4939 (strcmp(brand_name, LABELED_BRAND_NAME) == 0)) {
4859 4940 brand_close(bh);
4860 4941 zerror(zlogp, B_FALSE,
4861 4942 "cannot boot labeled zone on unlabeled system");
4862 4943 goto error;
4863 4944 }
4864 4945
4865 4946 /*
4866 4947 * If this brand requires any kernel support, now is the time to
4867 4948 * get it loaded and initialized.
4868 4949 */
4869 4950 if (brand_get_modname(bh, modname, MAXPATHLEN) < 0) {
4870 4951 brand_close(bh);
4871 4952 zerror(zlogp, B_FALSE,
4872 4953 "unable to determine brand kernel module");
4873 4954 goto error;
4874 4955 }
4875 4956 brand_close(bh);
4876 4957
4877 4958 if (strlen(modname) > 0) {
4878 4959 (void) strlcpy(attr.ba_brandname, brand_name,
4879 4960 sizeof (attr.ba_brandname));
4880 4961 (void) strlcpy(attr.ba_modname, modname,
4881 4962 sizeof (attr.ba_modname));
4882 4963 if (zone_setattr(zoneid, ZONE_ATTR_BRAND, &attr,
4883 4964 sizeof (attr) != 0)) {
4884 4965 zerror(zlogp, B_TRUE,
4885 4966 "could not set zone brand attribute.");
4886 4967 goto error;
4887 4968 }
4888 4969 }
4889 4970
4890 4971 if (setup_zone_rm(zlogp, zone_name, zoneid) != Z_OK)
4891 4972 goto error;
4892 4973
4893 4974 set_mlps(zlogp, zoneid, zcent);
4894 4975 }
4895 4976
4896 4977 rval = zoneid;
4897 4978 zoneid = -1;
4898 4979
4899 4980 error:
4900 4981 if (zoneid != -1) {
4901 4982 (void) zone_shutdown(zoneid);
4902 4983 (void) zone_destroy(zoneid);
4903 4984 }
4904 4985 if (rctlbuf != NULL)
4905 4986 free(rctlbuf);
4906 4987 priv_freeset(privs);
4907 4988 if (fp != NULL)
4908 4989 zonecfg_close_scratch(fp);
4909 4990 lofs_discard_mnttab();
4910 4991 if (zcent != NULL)
4911 4992 tsol_freezcent(zcent);
4912 4993 return (rval);
4913 4994 }
4914 4995
4915 4996 /*
4916 4997 * Enter the zone and write a /etc/zones/index file there. This allows
4917 4998 * libzonecfg (and thus zoneadm) to report the UUID and potentially other zone
4918 4999 * details from inside the zone.
4919 5000 */
4920 5001 static void
4921 5002 write_index_file(zoneid_t zoneid)
4922 5003 {
4923 5004 FILE *zef;
4924 5005 FILE *zet;
4925 5006 struct zoneent *zep;
4926 5007 pid_t child;
4927 5008 int tmpl_fd;
4928 5009 ctid_t ct;
4929 5010 int fd;
4930 5011 char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
4931 5012
4932 5013 /* Locate the zone entry in the global zone's index file */
4933 5014 if ((zef = setzoneent()) == NULL)
4934 5015 return;
4935 5016 while ((zep = getzoneent_private(zef)) != NULL) {
4936 5017 if (strcmp(zep->zone_name, zone_name) == 0)
4937 5018 break;
4938 5019 free(zep);
4939 5020 }
4940 5021 endzoneent(zef);
4941 5022 if (zep == NULL)
4942 5023 return;
4943 5024
4944 5025 if ((tmpl_fd = init_template()) == -1) {
4945 5026 free(zep);
4946 5027 return;
4947 5028 }
4948 5029
4949 5030 if ((child = fork()) == -1) {
4950 5031 (void) ct_tmpl_clear(tmpl_fd);
4951 5032 (void) close(tmpl_fd);
4952 5033 free(zep);
4953 5034 return;
4954 5035 }
4955 5036
4956 5037 /* parent waits for child to finish */
4957 5038 if (child != 0) {
4958 5039 free(zep);
4959 5040 if (contract_latest(&ct) == -1)
4960 5041 ct = -1;
4961 5042 (void) ct_tmpl_clear(tmpl_fd);
4962 5043 (void) close(tmpl_fd);
4963 5044 (void) waitpid(child, NULL, 0);
4964 5045 (void) contract_abandon_id(ct);
4965 5046 return;
4966 5047 }
4967 5048
4968 5049 /* child enters zone and sets up index file */
4969 5050 (void) ct_tmpl_clear(tmpl_fd);
4970 5051 if (zone_enter(zoneid) != -1) {
4971 5052 (void) mkdir(ZONE_CONFIG_ROOT, ZONE_CONFIG_MODE);
4972 5053 (void) chown(ZONE_CONFIG_ROOT, ZONE_CONFIG_UID,
4973 5054 ZONE_CONFIG_GID);
4974 5055 fd = open(ZONE_INDEX_FILE, O_WRONLY|O_CREAT|O_TRUNC,
4975 5056 ZONE_INDEX_MODE);
4976 5057 if (fd != -1 && (zet = fdopen(fd, "w")) != NULL) {
4977 5058 (void) fchown(fd, ZONE_INDEX_UID, ZONE_INDEX_GID);
4978 5059 if (uuid_is_null(zep->zone_uuid))
4979 5060 uuidstr[0] = '\0';
4980 5061 else
4981 5062 uuid_unparse(zep->zone_uuid, uuidstr);
4982 5063 (void) fprintf(zet, "%s:%s:/:%s\n", zep->zone_name,
4983 5064 zone_state_str(zep->zone_state),
|
↓ open down ↓ |
526 lines elided |
↑ open up ↑ |
4984 5065 uuidstr);
4985 5066 (void) fclose(zet);
4986 5067 }
4987 5068 }
4988 5069 _exit(0);
4989 5070 }
4990 5071
4991 5072 int
4992 5073 vplat_bringup(zlog_t *zlogp, zone_mnt_t mount_cmd, zoneid_t zoneid)
4993 5074 {
4994 - char zonepath[MAXPATHLEN];
5075 + char zpath[MAXPATHLEN];
4995 5076
4996 5077 if (mount_cmd == Z_MNT_BOOT && validate_datasets(zlogp) != 0) {
4997 5078 lofs_discard_mnttab();
4998 5079 return (-1);
4999 5080 }
5000 5081
5001 5082 /*
5002 5083 * Before we try to mount filesystems we need to create the
5003 5084 * attribute backing store for /dev
5004 5085 */
5005 - if (zone_get_zonepath(zone_name, zonepath, sizeof (zonepath)) != Z_OK) {
5006 - lofs_discard_mnttab();
5007 - return (-1);
5008 - }
5009 - resolve_lofs(zlogp, zonepath, sizeof (zonepath));
5086 + (void) strlcpy(zpath, zonepath, sizeof (zpath));
5087 + resolve_lofs(zlogp, zpath, sizeof (zpath));
5010 5088
5011 5089 /* Make /dev directory owned by root, grouped sys */
5012 - if (make_one_dir(zlogp, zonepath, "/dev", DEFAULT_DIR_MODE,
5013 - 0, 3) != 0) {
5090 + if (make_one_dir(zlogp, zpath, "/dev", DEFAULT_DIR_MODE, 0, 3) != 0) {
5014 5091 lofs_discard_mnttab();
5015 5092 return (-1);
5016 5093 }
5017 5094
5018 5095 if (mount_filesystems(zlogp, mount_cmd) != 0) {
5019 5096 lofs_discard_mnttab();
5020 5097 return (-1);
5021 5098 }
5022 5099
5023 5100 if (mount_cmd == Z_MNT_BOOT) {
5024 5101 zone_iptype_t iptype;
5025 5102
5026 5103 if (vplat_get_iptype(zlogp, &iptype) < 0) {
5027 5104 zerror(zlogp, B_TRUE, "unable to determine ip-type");
5028 5105 lofs_discard_mnttab();
5029 5106 return (-1);
5030 5107 }
5031 5108
5032 5109 switch (iptype) {
5033 5110 case ZS_SHARED:
5034 5111 /* Always do this to make lo0 get configured */
5035 5112 if (configure_shared_network_interfaces(zlogp) != 0) {
5036 5113 lofs_discard_mnttab();
5037 5114 return (-1);
5038 5115 }
5039 5116 break;
5040 5117 case ZS_EXCLUSIVE:
5041 5118 if (configure_exclusive_network_interfaces(zlogp,
5042 5119 zoneid) !=
5043 5120 0) {
5044 5121 lofs_discard_mnttab();
5045 5122 return (-1);
5046 5123 }
5047 5124 break;
5048 5125 }
5049 5126 }
5050 5127
5051 5128 write_index_file(zoneid);
5052 5129
5053 5130 lofs_discard_mnttab();
5054 5131 return (0);
5055 5132 }
5056 5133
5057 5134 static int
5058 5135 lu_root_teardown(zlog_t *zlogp)
5059 5136 {
5060 5137 char zroot[MAXPATHLEN];
5061 5138
5062 5139 if (zone_get_rootpath(zone_name, zroot, sizeof (zroot)) != Z_OK) {
5063 5140 zerror(zlogp, B_FALSE, "unable to determine zone root");
5064 5141 return (-1);
5065 5142 }
5066 5143 root_to_lu(zlogp, zroot, sizeof (zroot), B_FALSE);
5067 5144
5068 5145 /*
5069 5146 * At this point, the processes are gone, the filesystems (save the
5070 5147 * root) are unmounted, and the zone is on death row. But there may
5071 5148 * still be creds floating about in the system that reference the
5072 5149 * zone_t, and which pin down zone_rootvp causing this call to fail
5073 5150 * with EBUSY. Thus, we try for a little while before just giving up.
5074 5151 * (How I wish this were not true, and umount2 just did the right
5075 5152 * thing, or tmpfs supported MS_FORCE This is a gross hack.)
5076 5153 */
5077 5154 if (umount2(zroot, MS_FORCE) != 0) {
5078 5155 if (errno == ENOTSUP && umount2(zroot, 0) == 0)
5079 5156 goto unmounted;
5080 5157 if (errno == EBUSY) {
5081 5158 int tries = 10;
5082 5159
5083 5160 while (--tries >= 0) {
5084 5161 (void) sleep(1);
5085 5162 if (umount2(zroot, 0) == 0)
5086 5163 goto unmounted;
5087 5164 if (errno != EBUSY)
5088 5165 break;
5089 5166 }
5090 5167 }
5091 5168 zerror(zlogp, B_TRUE, "unable to unmount '%s'", zroot);
5092 5169 return (-1);
5093 5170 }
5094 5171 unmounted:
5095 5172
5096 5173 /*
5097 5174 * Only zones in an alternate root environment have scratch zone
5098 5175 * entries.
5099 5176 */
5100 5177 if (zonecfg_in_alt_root()) {
5101 5178 FILE *fp;
5102 5179 int retv;
5103 5180
5104 5181 if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
5105 5182 zerror(zlogp, B_TRUE, "cannot open mapfile");
5106 5183 return (-1);
5107 5184 }
5108 5185 retv = -1;
5109 5186 if (zonecfg_lock_scratch(fp) != 0)
5110 5187 zerror(zlogp, B_TRUE, "cannot lock mapfile");
5111 5188 else if (zonecfg_delete_scratch(fp, kernzone) != 0)
5112 5189 zerror(zlogp, B_TRUE, "cannot delete map entry");
5113 5190 else
5114 5191 retv = 0;
5115 5192 zonecfg_close_scratch(fp);
5116 5193 return (retv);
5117 5194 } else {
5118 5195 return (0);
|
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
5119 5196 }
5120 5197 }
5121 5198
5122 5199 int
5123 5200 vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting)
5124 5201 {
5125 5202 char *kzone;
5126 5203 zoneid_t zoneid;
5127 5204 int res;
5128 5205 char pool_err[128];
5129 - char zpath[MAXPATHLEN];
5130 5206 char cmdbuf[MAXPATHLEN];
5131 5207 brand_handle_t bh = NULL;
5132 5208 dladm_status_t status;
5133 5209 char errmsg[DLADM_STRSIZE];
5134 5210 ushort_t flags;
5135 5211
5136 5212 kzone = zone_name;
5137 5213 if (zonecfg_in_alt_root()) {
5138 5214 FILE *fp;
5139 5215
5140 5216 if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
5141 5217 zerror(zlogp, B_TRUE, "unable to open map file");
5142 5218 goto error;
5143 5219 }
5144 5220 if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(),
5145 5221 kernzone, sizeof (kernzone)) != 0) {
5146 5222 zerror(zlogp, B_FALSE, "unable to find scratch zone");
5147 5223 zonecfg_close_scratch(fp);
5148 5224 goto error;
5149 5225 }
5150 5226 zonecfg_close_scratch(fp);
5151 5227 kzone = kernzone;
5152 5228 }
5153 5229
5154 5230 if ((zoneid = getzoneidbyname(kzone)) == ZONE_ID_UNDEFINED) {
5155 5231 if (!bringup_failure_recovery)
5156 5232 zerror(zlogp, B_TRUE, "unable to get zoneid");
5157 5233 if (unmount_cmd)
5158 5234 (void) lu_root_teardown(zlogp);
5159 5235 goto error;
5160 5236 }
5161 5237
5162 5238 if (remove_datalink_pool(zlogp, zoneid) != 0) {
5163 5239 zerror(zlogp, B_FALSE, "unable clear datalink pool property");
5164 5240 goto error;
5165 5241 }
5166 5242
5167 5243 if (remove_datalink_protect(zlogp, zoneid) != 0) {
5168 5244 zerror(zlogp, B_FALSE,
5169 5245 "unable clear datalink protect property");
5170 5246 goto error;
5171 5247 }
5172 5248
5173 5249 /*
5174 5250 * The datalinks assigned to the zone will be removed from the NGZ as
|
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
5175 5251 * part of zone_shutdown() so that we need to remove protect/pool etc.
5176 5252 * before zone_shutdown(). Even if the shutdown itself fails, the zone
5177 5253 * will not be able to violate any constraints applied because the
5178 5254 * datalinks are no longer available to the zone.
5179 5255 */
5180 5256 if (zone_shutdown(zoneid) != 0) {
5181 5257 zerror(zlogp, B_TRUE, "unable to shutdown zone");
5182 5258 goto error;
5183 5259 }
5184 5260
5185 - /* Get the zonepath of this zone */
5186 - if (zone_get_zonepath(zone_name, zpath, sizeof (zpath)) != Z_OK) {
5187 - zerror(zlogp, B_FALSE, "unable to determine zone path");
5188 - goto error;
5189 - }
5190 -
5191 5261 /* Get a handle to the brand info for this zone */
5192 5262 if ((bh = brand_open(brand_name)) == NULL) {
5193 5263 zerror(zlogp, B_FALSE, "unable to determine zone brand");
5194 5264 return (-1);
5195 5265 }
5196 5266 /*
5197 5267 * If there is a brand 'halt' callback, execute it now to give the
5198 5268 * brand a chance to cleanup any custom configuration.
5199 5269 */
5200 5270 (void) strcpy(cmdbuf, EXEC_PREFIX);
5201 - if (brand_get_halt(bh, zone_name, zpath, cmdbuf + EXEC_LEN,
5271 + if (brand_get_halt(bh, zone_name, zonepath, cmdbuf + EXEC_LEN,
5202 5272 sizeof (cmdbuf) - EXEC_LEN) < 0) {
5203 5273 brand_close(bh);
5204 5274 zerror(zlogp, B_FALSE, "unable to determine branded zone's "
5205 5275 "halt callback.");
5206 5276 goto error;
5207 5277 }
5208 5278 brand_close(bh);
5209 5279
5210 5280 if ((strlen(cmdbuf) > EXEC_LEN) &&
5211 5281 (do_subproc(zlogp, cmdbuf, NULL) != Z_OK)) {
5212 5282 zerror(zlogp, B_FALSE, "%s failed", cmdbuf);
5213 5283 goto error;
5214 5284 }
5215 5285
5216 5286 if (!unmount_cmd) {
5217 5287 zone_iptype_t iptype;
5218 5288
5219 5289 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
5220 5290 sizeof (flags)) < 0) {
5221 5291 if (vplat_get_iptype(zlogp, &iptype) < 0) {
5222 5292 zerror(zlogp, B_TRUE, "unable to determine "
5223 5293 "ip-type");
5224 5294 goto error;
5225 5295 }
5226 5296 } else {
5227 5297 if (flags & ZF_NET_EXCL)
5228 5298 iptype = ZS_EXCLUSIVE;
5229 5299 else
5230 5300 iptype = ZS_SHARED;
5231 5301 }
5232 5302
5233 5303 switch (iptype) {
5234 5304 case ZS_SHARED:
5235 5305 if (unconfigure_shared_network_interfaces(zlogp,
5236 5306 zoneid) != 0) {
5237 5307 zerror(zlogp, B_FALSE, "unable to unconfigure "
5238 5308 "network interfaces in zone");
5239 5309 goto error;
5240 5310 }
5241 5311 break;
5242 5312 case ZS_EXCLUSIVE:
5243 5313 if (unconfigure_exclusive_network_interfaces(zlogp,
5244 5314 zoneid) != 0) {
5245 5315 zerror(zlogp, B_FALSE, "unable to unconfigure "
5246 5316 "network interfaces in zone");
5247 5317 goto error;
5248 5318 }
5249 5319 status = dladm_zone_halt(dld_handle, zoneid);
5250 5320 if (status != DLADM_STATUS_OK) {
5251 5321 zerror(zlogp, B_FALSE, "unable to notify "
5252 5322 "dlmgmtd of zone halt: %s",
5253 5323 dladm_status2str(status, errmsg));
5254 5324 }
5255 5325 break;
5256 5326 }
5257 5327 }
5258 5328
5259 5329 if (!unmount_cmd && tcp_abort_connections(zlogp, zoneid) != 0) {
5260 5330 zerror(zlogp, B_TRUE, "unable to abort TCP connections");
5261 5331 goto error;
5262 5332 }
5263 5333
5264 5334 if (unmount_filesystems(zlogp, zoneid, unmount_cmd) != 0) {
5265 5335 zerror(zlogp, B_FALSE,
5266 5336 "unable to unmount file systems in zone");
5267 5337 goto error;
5268 5338 }
5269 5339
5270 5340 /*
5271 5341 * If we are rebooting then we normally don't want to destroy an
5272 5342 * existing temporary pool at this point so that we can just reuse it
5273 5343 * when the zone boots back up. However, it is also possible we were
5274 5344 * running with a temporary pool and the zone configuration has been
5275 5345 * modified to no longer use a temporary pool. In that case we need
5276 5346 * to destroy the temporary pool now. This case looks like the case
5277 5347 * where we never had a temporary pool configured but
5278 5348 * zonecfg_destroy_tmp_pool will do the right thing either way.
5279 5349 */
5280 5350 if (!unmount_cmd) {
5281 5351 boolean_t destroy_tmp_pool = B_TRUE;
5282 5352
5283 5353 if (rebooting) {
5284 5354 struct zone_psettab pset_tab;
5285 5355 zone_dochandle_t handle;
5286 5356
5287 5357 if ((handle = zonecfg_init_handle()) != NULL &&
5288 5358 zonecfg_get_handle(zone_name, handle) == Z_OK &&
5289 5359 zonecfg_lookup_pset(handle, &pset_tab) == Z_OK)
5290 5360 destroy_tmp_pool = B_FALSE;
5291 5361
5292 5362 zonecfg_fini_handle(handle);
5293 5363 }
5294 5364
5295 5365 if (destroy_tmp_pool) {
5296 5366 if ((res = zonecfg_destroy_tmp_pool(zone_name, pool_err,
5297 5367 sizeof (pool_err))) != Z_OK) {
5298 5368 if (res == Z_POOL)
5299 5369 zerror(zlogp, B_FALSE, pool_err);
5300 5370 }
5301 5371 }
5302 5372 }
5303 5373
5304 5374 remove_mlps(zlogp, zoneid);
5305 5375
5306 5376 if (zone_destroy(zoneid) != 0) {
5307 5377 zerror(zlogp, B_TRUE, "unable to destroy zone");
5308 5378 goto error;
5309 5379 }
5310 5380
5311 5381 /*
5312 5382 * Special teardown for alternate boot environments: remove the tmpfs
5313 5383 * root for the zone and then remove it from the map file.
5314 5384 */
5315 5385 if (unmount_cmd && lu_root_teardown(zlogp) != 0)
5316 5386 goto error;
5317 5387
5318 5388 lofs_discard_mnttab();
5319 5389 return (0);
5320 5390
5321 5391 error:
5322 5392 lofs_discard_mnttab();
5323 5393 return (-1);
5324 5394 }
|
↓ open down ↓ |
113 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX