62 */ |
61 */ |
63 static boolean_t override = B_FALSE; |
62 static boolean_t override = B_FALSE; |
64 |
63 |
65 static char *bname = NULL; |
64 static char *bname = NULL; |
66 |
65 |
|
66 /* |
|
67 * DELETE_LIST_PATH represents the path to a solaris10-branded zone's "delete |
|
68 * list", which is generated by patchrm when it needs to remove files after |
|
69 * the zone reboots. See set_zone_emul_bitmap() below for additional details. |
|
70 */ |
|
71 #define DELETE_LIST_PATH "/var/sadm/patch/.delete_list" |
|
72 |
67 #define PKGINFO_RD_LEN 128 |
73 #define PKGINFO_RD_LEN 128 |
68 #define PATCHLIST "PATCHLIST=" |
74 #define PATCHLIST "PATCHLIST=" |
69 |
75 |
70 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ |
76 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ |
71 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ |
77 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ |
336 |
342 |
337 return (B_FALSE); |
343 return (B_FALSE); |
338 } |
344 } |
339 |
345 |
340 /* |
346 /* |
|
347 * Convert the specified file basename into an unsigned integer. If the |
|
348 * basename contains characters that cannot be converted into digits or the |
|
349 * basename isn't NULL or newline-terminated, then this function returns |
|
350 * the unsigned equivalent of -1. |
|
351 */ |
|
352 static unsigned int |
|
353 basename_to_uint(const char *basenamep) |
|
354 { |
|
355 char *filename_endptr; |
|
356 unsigned int bit_index; |
|
357 |
|
358 errno = 0; |
|
359 bit_index = (unsigned int)strtoul(basenamep, &filename_endptr, 10); |
|
360 if (errno != 0 || (*filename_endptr != '\n' && |
|
361 *filename_endptr != '\0') || filename_endptr == basenamep) |
|
362 return ((unsigned int)-1); |
|
363 return (bit_index); |
|
364 } |
|
365 |
|
366 /* |
341 * Determine which features/behaviors should be emulated and construct a bitmap |
367 * Determine which features/behaviors should be emulated and construct a bitmap |
342 * representing the results. Associate the bitmap with the zone so that |
368 * representing the results. Associate the bitmap with the zone so that |
343 * the brand's emulation library will be able to retrieve the bitmap and |
369 * the brand's emulation library will be able to retrieve the bitmap and |
344 * determine how the zone's process' behaviors should be emulated. |
370 * determine how the zone's process' behaviors should be emulated. |
345 * |
371 * |
346 * This function does not return if an error occurs. |
372 * This function does not return if an error occurs. |
347 */ |
373 */ |
348 static void |
374 static void |
349 set_zone_emul_bitmap(char *zonename) |
375 set_zone_emul_bitmap(char *zonename) |
350 { |
376 { |
351 char req_emulation_dir_path[MAXPATHLEN]; |
377 char zoneroot[MAXPATHLEN]; |
|
378 char path[MAXPATHLEN]; |
352 DIR *req_emulation_dirp; |
379 DIR *req_emulation_dirp; |
353 struct dirent *emul_feature_filep; |
380 struct dirent *emul_feature_filep; |
354 char *filename_endptr; |
|
355 s10_emul_bitmap_t bitmap; |
381 s10_emul_bitmap_t bitmap; |
356 unsigned int bit_index; |
382 unsigned int bit_index; |
357 zoneid_t zoneid; |
383 zoneid_t zoneid; |
|
384 FILE *delete_listp; |
358 |
385 |
359 /* |
386 /* |
360 * If the Solaris 10 directory containing emulation feature files |
387 * If the Solaris 10 directory containing emulation feature files |
361 * doesn't exist in the zone, then assume that it only needs the |
388 * doesn't exist in the zone, then assume that it only needs the |
362 * most basic emulation and, therefore, doesn't need a bitmap. |
389 * most basic emulation and, therefore, doesn't need a bitmap. |
363 */ |
390 */ |
364 if (zone_get_rootpath(zonename, req_emulation_dir_path, |
391 if (zone_get_rootpath(zonename, zoneroot, sizeof (zoneroot)) != Z_OK) |
365 sizeof (req_emulation_dir_path)) != Z_OK) |
|
366 s10_err(gettext("error getting zone's path")); |
392 s10_err(gettext("error getting zone's path")); |
367 if (strlcat(req_emulation_dir_path, S10_REQ_EMULATION_DIR, |
393 if (snprintf(path, sizeof (path), "%s" S10_REQ_EMULATION_DIR, |
368 sizeof (req_emulation_dir_path)) >= sizeof (req_emulation_dir_path)) |
394 zoneroot) >= sizeof (path)) |
369 s10_err(gettext("error formatting version path")); |
395 s10_err(gettext("zone's emulation versioning directory's path " |
370 if ((req_emulation_dirp = opendir(req_emulation_dir_path)) == NULL) |
396 "%s" S10_REQ_EMULATION_DIR " is too long"), zoneroot); |
|
397 if ((req_emulation_dirp = opendir(path)) == NULL) |
371 return; |
398 return; |
372 bzero(bitmap, sizeof (bitmap)); |
399 bzero(bitmap, sizeof (bitmap)); |
373 |
400 |
374 /* |
401 /* |
375 * Iterate over the contents of the directory and determine which |
402 * Iterate over the contents of the directory and determine which |
410 * Set the feature's flag in the bitmap. |
434 * Set the feature's flag in the bitmap. |
411 */ |
435 */ |
412 bitmap[(bit_index >> 3)] |= (1 << (bit_index & 0x7)); |
436 bitmap[(bit_index >> 3)] |= (1 << (bit_index & 0x7)); |
413 } |
437 } |
414 } |
438 } |
|
439 (void) closedir(req_emulation_dirp); |
|
440 |
|
441 /* |
|
442 * The zone's administrator might have removed a patch that delivered |
|
443 * an emulation feature file the last time the zone ran. If so, then |
|
444 * the zone's patch utilities won't delete the file until the zone's |
|
445 * svc:/system/patch-finish:delete SMF service runs. This is |
|
446 * problematic because the zone will be using system libraries whose |
|
447 * ioctl structures and syscall invocations will differ from those |
|
448 * expected by the emulation library. For example, if an administrator |
|
449 * removes a patch that affects the formats of MNTFS ioctls, then the |
|
450 * administrator's zone will use a version of libc.so.1 that issues |
|
451 * MNTFS ioctls that use older structure versions than the zone's |
|
452 * emulation library will expect. |
|
453 * |
|
454 * Fortunately, the patchrm utility creates a hidden file, |
|
455 * /var/sadm/patch/.delete_list, which lists all files that |
|
456 * svc:/system/patch-finish:delete will delete. We'll determine whether |
|
457 * this file exists in the zone and disable the emulation bits |
|
458 * associated with the emulation feature files that will be deleted. |
|
459 * |
|
460 * NOTE: The patch tools lofs mount backup copies of critical system |
|
461 * libraries, such as /lib/libc.so.1, over their replacements whenever |
|
462 * administrators add or remove DAP patches. Consequently, there isn't |
|
463 * a window of vulnerability between patch addition or removal and |
|
464 * zone reboot. The aforementioned problem only occurs after a zone |
|
465 * reboots. |
|
466 */ |
|
467 if (snprintf(path, sizeof (path), "%s" DELETE_LIST_PATH, zoneroot) >= |
|
468 sizeof (path)) |
|
469 s10_err(gettext("zone's delete list's path %s" DELETE_LIST_PATH |
|
470 " is too long"), zoneroot); |
|
471 if ((delete_listp = fopen(path, "r")) != NULL) { |
|
472 while (fgets(path, sizeof (path), delete_listp) != NULL) { |
|
473 char *const basenamep = path + |
|
474 sizeof (S10_REQ_EMULATION_DIR); |
|
475 |
|
476 /* |
|
477 * Make sure that the file is in the directory |
|
478 * containing emulation feature files. If it is, |
|
479 * then basenamep should refer to the basename of |
|
480 * the file. |
|
481 */ |
|
482 if (strncmp(path, S10_REQ_EMULATION_DIR, |
|
483 sizeof (S10_REQ_EMULATION_DIR) - 1) != 0) |
|
484 continue; |
|
485 if (*(basenamep - 1) != '/') |
|
486 continue; |
|
487 |
|
488 /* |
|
489 * Convert the file's basename into a bit index in |
|
490 * the emulation bitmap. If the file's basename isn't |
|
491 * integral, then skip the file. Otherwise, clear the |
|
492 * corresponding bit in the bitmap. |
|
493 */ |
|
494 bit_index = basename_to_uint(basenamep); |
|
495 if (bit_index == (unsigned int)-1) |
|
496 continue; |
|
497 if (bit_index < S10_NUM_EMUL_FEATURES) |
|
498 bitmap[(bit_index >> 3)] &= |
|
499 ~(1 << (bit_index & 0x7)); |
|
500 } |
|
501 if (ferror(delete_listp) != 0 || feof(delete_listp) == 0) |
|
502 s10_err(gettext("The program encountered an error while" |
|
503 " reading from %s" DELETE_LIST_PATH "."), zoneroot); |
|
504 (void) fclose(delete_listp); |
|
505 } else if (errno != ENOENT) { |
|
506 /* |
|
507 * The delete list exists but couldn't be opened. Warn the |
|
508 * administrator. |
|
509 */ |
|
510 s10_err(gettext("Unable to open %s" DELETE_LIST_PATH ": %s"), |
|
511 zoneroot, strerror(errno)); |
|
512 } |
415 |
513 |
416 /* |
514 /* |
417 * We're done scanning files. Set the zone's emulation bitmap. |
515 * We're done scanning files. Set the zone's emulation bitmap. |
418 */ |
516 */ |
419 (void) closedir(req_emulation_dirp); |
|
420 if ((zoneid = getzoneidbyname(zonename)) < 0) |
517 if ((zoneid = getzoneidbyname(zonename)) < 0) |
421 s10_err(gettext("unable to get zoneid")); |
518 s10_err(gettext("unable to get zoneid")); |
422 if (zone_setattr(zoneid, S10_EMUL_BITMAP, bitmap, sizeof (bitmap)) != 0) |
519 if (zone_setattr(zoneid, S10_EMUL_BITMAP, bitmap, sizeof (bitmap)) != 0) |
423 s10_err(gettext("error setting zone's emulation bitmap")); |
520 s10_err(gettext("error setting zone's emulation bitmap")); |
424 } |
521 } |