usr/src/lib/brand/solaris10/s10_support/s10_support.c
changeset 12433 a15cace5f27d
parent 11771 5d55cb57dff3
child 12463 5259ac7d9677
equal deleted inserted replaced
12432:222dd376dd6c 12433:a15cace5f27d
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
    18  *
    18  *
    19  * CDDL HEADER END
    19  * CDDL HEADER END
    20  */
    20  */
    21 /*
    21 /*
    22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
    22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
    23  * Use is subject to license terms.
       
    24  */
    23  */
    25 
    24 
    26 /*
    25 /*
    27  * s10_support is a small cli utility used to perform some brand-specific
    26  * s10_support is a small cli utility used to perform some brand-specific
    28  * tasks when verifying a zone.  This utility is not intended to be called
    27  * tasks when verifying a zone.  This utility is not intended to be called
    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
   382 
   409 
   383 		/*
   410 		/*
   384 		 * Convert the file's name to an unsigned integer.  Ignore
   411 		 * Convert the file's name to an unsigned integer.  Ignore
   385 		 * files whose names aren't unsigned integers.
   412 		 * files whose names aren't unsigned integers.
   386 		 */
   413 		 */
   387 		errno = 0;
   414 		bit_index = basename_to_uint(emul_feature_filep->d_name);
   388 		bit_index = (unsigned int)strtoul(emul_feature_filep->d_name,
   415 		if (bit_index == (unsigned int)-1)
   389 		    &filename_endptr, 10);
       
   390 		if (errno != 0 || *filename_endptr != '\0' ||
       
   391 		    filename_endptr == emul_feature_filep->d_name)
       
   392 			continue;
   416 			continue;
   393 
   417 
   394 		/*
   418 		/*
   395 		 * Determine if the brand can emulate the feature specified
   419 		 * Determine if the brand can emulate the feature specified
   396 		 * by bit_index.
   420 		 * by bit_index.
   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 }