6909222 reboot of system upgraded from 128 to build 129 generated error from an s10 zone due to boot-archive
6927878 removing patches that affect solaris10 emulation hoses solaris10-branded zones
6947847 Solaris 10 Containers need s10_replacefile to support S10 patch tools
--- a/usr/src/lib/brand/solaris10/Makefile Tue May 18 12:28:45 2010 -0600
+++ b/usr/src/lib/brand/solaris10/Makefile Tue May 18 12:28:09 2010 -0700
@@ -19,8 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
default: all
@@ -30,7 +29,8 @@
# Build everything in parallel; use .WAIT for dependencies
.PARALLEL:
-SUBDIRS = librtld_db s10_npreload s10_brand s10_support zone cmd
+SUBDIRS = librtld_db s10_npreload s10_brand s10_support s10_replacefile \
+ zone cmd
MSGSUBDIRS = s10_support zone
all := TARGET= all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/solaris10/s10_replacefile/Makefile Tue May 18 12:28:09 2010 -0700
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+#
+
+PROG = s10_replacefile
+PROGS = $(PROG)
+OBJS = s10_replacefile
+
+all: $(PROG)
+
+include ../Makefile.s10
+include $(SRC)/cmd/Makefile.cmd
+
+# override the install directory
+ROOTBIN = $(ROOTBRANDDIR)
+CLOBBERFILES = $(OBJS) $(ROOTPROGS)
+
+UTSBASE = $(SRC)/uts
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -D_REENTRANT
+
+.KEEP_STATE:
+
+install: all $(ROOTPROGS)
+
+clean:
+ $(RM) $(PROG) $(OBJS)
+
+lint: lint_PROG
+
+include $(SRC)/cmd/Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/brand/solaris10/s10_replacefile/s10_replacefile.c Tue May 18 12:28:09 2010 -0700
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/mntent.h>
+#include <unistd.h>
+
+/*
+ * This program aids the Solaris 10 patch tools (specifically
+ * /usr/lib/patch/patch_common_lib) in DAP patching.
+ *
+ * Whenever the patch tools replace a critical system component (e.g.,
+ * /lib/libc.so.1), they move the old component to a temporary location,
+ * move the new component to where the old component was, and establish
+ * an overlay mount of the old component on top of the new component.
+ * The patch tools do this with a shell script; consequently, the three
+ * operations occur in three processes.
+ *
+ * This doesn't work inside Solaris 10 Containers (S10Cs). Suppose the
+ * patch tools need to replace /lib/libc.so.1. The tools will move the old
+ * libc.so.1 to a temporary location. But when they try to move the new
+ * libc.so.1, they fork a mv(1) process, which loads the solaris10 brand's
+ * emulation library. The emulation library will try to load the zone's
+ * libc.so.1, but the library no longer exists; consequently, the emulation
+ * library aborts and the zone's users won't be able to start any processes.
+ *
+ * This program solves the problem by combining the move and mount operations
+ * into a single process. The emulation library will already have loaded
+ * libc.so.1 for the process by the time the process starts to replace
+ * libc.so.1.
+ *
+ * This program takes six parameters that correspond to six variables within
+ * /usr/lib/patch/patch_common_lib:InstallSafemodeObject():
+ *
+ * argv[1] - dstActual (the path to the file that will be replaced)
+ * argv[2] - tmp_file (the temporary location to which the file will be
+ * moved)
+ * argv[3] - tmpDst (the path to the replacement file)
+ * argv[4] - tmpFile (the path to a temporary copy of the running system's
+ * version of the file being replaced; the source [special] of
+ * the overlay mount)
+ * argv[5] - cksumTmpDst (checksum of the file represented by tmpDst)
+ * argv[6] - cksumTmpFile (checksum of the file represented by tmpFile)
+ *
+ * NOTE: This program will only establish an overlay mount if argv[4] or argv[5]
+ * is emtpy or if argv[4] and argv[5] differ.
+ *
+ * This program returns zero when it succeeds. Non-negative values indicate
+ * failure.
+ */
+int
+main(int argc, char **argv)
+{
+ struct stat statbuf;
+ char mntoptions[MAX_MNTOPT_STR];
+
+ /*
+ * Check the number of arguments that were passed to s10_replacefile.
+ */
+ if (argc != 7) {
+ (void) fprintf(stderr, "Usage: %s dstActual tmp_file tmpDst "
+ "tmpFile cksumTmpDst cksumTmpFile\n", argv[0]);
+ return (1);
+ }
+
+ /*
+ * Move the destination file (dstActual) out of the way and move the
+ * new file (tmpDst) into its place.
+ *
+ * NOTE: s10_replacefile won't print error messages here because
+ * the Solaris 10 patch tools will.
+ */
+ if (rename(argv[1], argv[2]) != 0)
+ return (2);
+ if (rename(argv[3], argv[1]) != 0)
+ return (3);
+
+ /*
+ * If there was a lofs mount on dstActual (which we just moved), then
+ * s10_replacefile should reestablish the lofs mount. A lofs mount
+ * existed if tmpFile exists.
+ */
+ if (stat(argv[4], &statbuf) == 0 && (statbuf.st_mode & S_IFREG)) {
+ /*
+ * Create a lofs overlay mount only if the checksums of the
+ * old file at dstActual and the new file at dstActual differ.
+ */
+ if (argv[5][0] == '\0' || argv[6][0] == '\0' ||
+ strcmp(argv[5], argv[6]) != 0) {
+ mntoptions[0] = '\0';
+ if (mount(argv[4], argv[1], MS_OVERLAY | MS_OPTIONSTR,
+ MNTTYPE_LOFS, NULL, 0, mntoptions,
+ sizeof (mntoptions)) != 0) {
+ /*
+ * Although the patch tools will print error
+ * messages, the tools won't know that
+ * s10_replacefile failed to establish an
+ * overlay mount. Printing an error message
+ * here clarifies the problem for the user.
+ */
+ (void) fprintf(stderr, "ERROR: Failed to "
+ "overlay mount %s onto %s\n", argv[4],
+ argv[1]);
+ return (4);
+ }
+ } else {
+ /*
+ * dstActual does not need an overlay mount. Delete
+ * tmpFile.
+ */
+ (void) unlink(argv[4]);
+ }
+ }
+ return (0);
+}
--- a/usr/src/lib/brand/solaris10/s10_support/s10_support.c Tue May 18 12:28:45 2010 -0600
+++ b/usr/src/lib/brand/solaris10/s10_support/s10_support.c Tue May 18 12:28:09 2010 -0700
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -64,6 +63,13 @@
static char *bname = NULL;
+/*
+ * DELETE_LIST_PATH represents the path to a solaris10-branded zone's "delete
+ * list", which is generated by patchrm when it needs to remove files after
+ * the zone reboots. See set_zone_emul_bitmap() below for additional details.
+ */
+#define DELETE_LIST_PATH "/var/sadm/patch/.delete_list"
+
#define PKGINFO_RD_LEN 128
#define PATCHLIST "PATCHLIST="
@@ -338,6 +344,26 @@
}
/*
+ * Convert the specified file basename into an unsigned integer. If the
+ * basename contains characters that cannot be converted into digits or the
+ * basename isn't NULL or newline-terminated, then this function returns
+ * the unsigned equivalent of -1.
+ */
+static unsigned int
+basename_to_uint(const char *basenamep)
+{
+ char *filename_endptr;
+ unsigned int bit_index;
+
+ errno = 0;
+ bit_index = (unsigned int)strtoul(basenamep, &filename_endptr, 10);
+ if (errno != 0 || (*filename_endptr != '\n' &&
+ *filename_endptr != '\0') || filename_endptr == basenamep)
+ return ((unsigned int)-1);
+ return (bit_index);
+}
+
+/*
* Determine which features/behaviors should be emulated and construct a bitmap
* representing the results. Associate the bitmap with the zone so that
* the brand's emulation library will be able to retrieve the bitmap and
@@ -348,26 +374,27 @@
static void
set_zone_emul_bitmap(char *zonename)
{
- char req_emulation_dir_path[MAXPATHLEN];
+ char zoneroot[MAXPATHLEN];
+ char path[MAXPATHLEN];
DIR *req_emulation_dirp;
struct dirent *emul_feature_filep;
- char *filename_endptr;
s10_emul_bitmap_t bitmap;
unsigned int bit_index;
zoneid_t zoneid;
+ FILE *delete_listp;
/*
* If the Solaris 10 directory containing emulation feature files
* doesn't exist in the zone, then assume that it only needs the
* most basic emulation and, therefore, doesn't need a bitmap.
*/
- if (zone_get_rootpath(zonename, req_emulation_dir_path,
- sizeof (req_emulation_dir_path)) != Z_OK)
+ if (zone_get_rootpath(zonename, zoneroot, sizeof (zoneroot)) != Z_OK)
s10_err(gettext("error getting zone's path"));
- if (strlcat(req_emulation_dir_path, S10_REQ_EMULATION_DIR,
- sizeof (req_emulation_dir_path)) >= sizeof (req_emulation_dir_path))
- s10_err(gettext("error formatting version path"));
- if ((req_emulation_dirp = opendir(req_emulation_dir_path)) == NULL)
+ if (snprintf(path, sizeof (path), "%s" S10_REQ_EMULATION_DIR,
+ zoneroot) >= sizeof (path))
+ s10_err(gettext("zone's emulation versioning directory's path "
+ "%s" S10_REQ_EMULATION_DIR " is too long"), zoneroot);
+ if ((req_emulation_dirp = opendir(path)) == NULL)
return;
bzero(bitmap, sizeof (bitmap));
@@ -384,11 +411,8 @@
* Convert the file's name to an unsigned integer. Ignore
* files whose names aren't unsigned integers.
*/
- errno = 0;
- bit_index = (unsigned int)strtoul(emul_feature_filep->d_name,
- &filename_endptr, 10);
- if (errno != 0 || *filename_endptr != '\0' ||
- filename_endptr == emul_feature_filep->d_name)
+ bit_index = basename_to_uint(emul_feature_filep->d_name);
+ if (bit_index == (unsigned int)-1)
continue;
/*
@@ -412,11 +436,84 @@
bitmap[(bit_index >> 3)] |= (1 << (bit_index & 0x7));
}
}
+ (void) closedir(req_emulation_dirp);
+
+ /*
+ * The zone's administrator might have removed a patch that delivered
+ * an emulation feature file the last time the zone ran. If so, then
+ * the zone's patch utilities won't delete the file until the zone's
+ * svc:/system/patch-finish:delete SMF service runs. This is
+ * problematic because the zone will be using system libraries whose
+ * ioctl structures and syscall invocations will differ from those
+ * expected by the emulation library. For example, if an administrator
+ * removes a patch that affects the formats of MNTFS ioctls, then the
+ * administrator's zone will use a version of libc.so.1 that issues
+ * MNTFS ioctls that use older structure versions than the zone's
+ * emulation library will expect.
+ *
+ * Fortunately, the patchrm utility creates a hidden file,
+ * /var/sadm/patch/.delete_list, which lists all files that
+ * svc:/system/patch-finish:delete will delete. We'll determine whether
+ * this file exists in the zone and disable the emulation bits
+ * associated with the emulation feature files that will be deleted.
+ *
+ * NOTE: The patch tools lofs mount backup copies of critical system
+ * libraries, such as /lib/libc.so.1, over their replacements whenever
+ * administrators add or remove DAP patches. Consequently, there isn't
+ * a window of vulnerability between patch addition or removal and
+ * zone reboot. The aforementioned problem only occurs after a zone
+ * reboots.
+ */
+ if (snprintf(path, sizeof (path), "%s" DELETE_LIST_PATH, zoneroot) >=
+ sizeof (path))
+ s10_err(gettext("zone's delete list's path %s" DELETE_LIST_PATH
+ " is too long"), zoneroot);
+ if ((delete_listp = fopen(path, "r")) != NULL) {
+ while (fgets(path, sizeof (path), delete_listp) != NULL) {
+ char *const basenamep = path +
+ sizeof (S10_REQ_EMULATION_DIR);
+
+ /*
+ * Make sure that the file is in the directory
+ * containing emulation feature files. If it is,
+ * then basenamep should refer to the basename of
+ * the file.
+ */
+ if (strncmp(path, S10_REQ_EMULATION_DIR,
+ sizeof (S10_REQ_EMULATION_DIR) - 1) != 0)
+ continue;
+ if (*(basenamep - 1) != '/')
+ continue;
+
+ /*
+ * Convert the file's basename into a bit index in
+ * the emulation bitmap. If the file's basename isn't
+ * integral, then skip the file. Otherwise, clear the
+ * corresponding bit in the bitmap.
+ */
+ bit_index = basename_to_uint(basenamep);
+ if (bit_index == (unsigned int)-1)
+ continue;
+ if (bit_index < S10_NUM_EMUL_FEATURES)
+ bitmap[(bit_index >> 3)] &=
+ ~(1 << (bit_index & 0x7));
+ }
+ if (ferror(delete_listp) != 0 || feof(delete_listp) == 0)
+ s10_err(gettext("The program encountered an error while"
+ " reading from %s" DELETE_LIST_PATH "."), zoneroot);
+ (void) fclose(delete_listp);
+ } else if (errno != ENOENT) {
+ /*
+ * The delete list exists but couldn't be opened. Warn the
+ * administrator.
+ */
+ s10_err(gettext("Unable to open %s" DELETE_LIST_PATH ": %s"),
+ zoneroot, strerror(errno));
+ }
/*
* We're done scanning files. Set the zone's emulation bitmap.
*/
- (void) closedir(req_emulation_dirp);
if ((zoneid = getzoneidbyname(zonename)) < 0)
s10_err(gettext("unable to get zoneid"));
if (zone_setattr(zoneid, S10_EMUL_BITMAP, bitmap, sizeof (bitmap)) != 0)
--- a/usr/src/lib/brand/solaris10/zone/p2v.ksh Tue May 18 12:28:45 2010 -0600
+++ b/usr/src/lib/brand/solaris10/zone/p2v.ksh Tue May 18 12:28:09 2010 -0700
@@ -19,8 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
# NOTE: this script runs in the global zone and touches the non-global
@@ -50,6 +49,12 @@
/usr/sbin/zoneadm -z $ZONENAME halt
fi
+ #
+ # Delete temporary files created during the hollow package removal
+ # process.
+ #
+ rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
+
exit $EXIT_CODE
}
@@ -539,6 +544,9 @@
#
safe_dir /etc
safe_dir /var
+safe_dir /var/sadm
+safe_dir /var/sadm/install
+safe_dir /var/sadm/pkg
safe_opt_dir /etc/dfs
safe_opt_dir /etc/lu
safe_opt_dir /etc/zones
@@ -587,6 +595,88 @@
fatal "$e_exitfail"
fi
+#
+# Remove all files and directories installed by hollow packages. Such files
+# and directories shouldn't exist inside zones.
+#
+hollow_pkgs=$(mktemp -t .hollow.pkgs.XXXXXX)
+hollow_file_list=$(mktemp $ZONEROOT/.hollow.pkgs.files.XXXXXX)
+hollow_dir_list=$(mktemp $ZONEROOT/.hollow.pkgs.dirs.XXXXXX)
+[ -f "$hollow_pkgs" -a -f "$hollow_file_list" -a -f "$hollow_dir_list" ] || {
+ error "$e_tmpfile"
+ rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
+ fatal "$e_exitfail"
+}
+for pkg_name in $ZONEROOT/var/sadm/pkg/*; do
+ grep 'SUNW_PKG_HOLLOW=true' $pkg_name/pkginfo >/dev/null 2>&1 && \
+ basename $pkg_name >>$hollow_pkgs
+done
+/usr/bin/nawk -v hollowpkgs=$hollow_pkgs -v filelist=$hollow_file_list \
+ -v dirlist=$hollow_dir_list '
+ BEGIN {
+ while (getline p <hollowpkgs > 0)
+ pkgs[p] = 1;
+ close(hollowpkgs);
+ }
+ {
+ # fld is the field where the pkg names begin.
+ # nm is the file/dir entry name.
+ if ($2 == "f") {
+ fld=10;
+ nm=$1;
+ } else if ($2 == "d") {
+ fld=7;
+ nm=$1;
+ } else if ($2 == "s" || $2 == "l") {
+ fld=4;
+ split($1, a, "=");
+ nm=a[1];
+ } else {
+ next;
+ }
+
+ # Determine whether the file or directory is delivered by any
+ # non-hollow packages. Files and directories can be
+ # delivered by multiple pkgs. The file or directory should only
+ # be removed if it is only delivered by hollow packages.
+ for (i = fld; i <= NF; i++) {
+ if (pkgs[get_pkg_name($i)] != 1) {
+ # We encountered a non-hollow package. Skip
+ # this entry.
+ next;
+ }
+ }
+
+ # The file or directory is only delivered by hollow packages.
+ # Mark it for removal.
+ if (fld != 7)
+ print nm >>filelist
+ else
+ print nm >>dirlist
+ }
+
+ # Get the clean pkg name from the fld entry.
+ function get_pkg_name(fld) {
+ # Remove any pkg control prefix (e.g. *, !)
+ first = substr(fld, 1, 1)
+ if (match(first, /[A-Za-z]/)) {
+ pname = fld
+ } else {
+ pname = substr(fld, 2)
+ }
+
+ # Then remove any class action script name
+ pos = index(pname, ":")
+ if (pos != 0)
+ pname = substr(pname, 1, pos - 1)
+ return (pname)
+ }
+' $ZONEROOT/var/sadm/install/contents
+/usr/sbin/zlogin -S $ZONENAME "cat /$(basename $hollow_file_list) | xargs rm -f"
+/usr/sbin/zlogin -S $ZONENAME "sort -r /$(basename $hollow_dir_list) | \
+ xargs rmdir >/dev/null 2>&1"
+rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
+
# cleanup SMF services
fix_smf
--- a/usr/src/pkg/manifests/system-zones-brand-s10.mf Tue May 18 12:28:45 2010 -0600
+++ b/usr/src/pkg/manifests/system-zones-brand-s10.mf Tue May 18 12:28:09 2010 -0700
@@ -20,8 +20,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
set name=pkg.fmri value=pkg:/system/zones/brand/s10@$(PKGVERS)
@@ -86,6 +85,7 @@
file path=usr/lib/brand/solaris10/s10_boot mode=0755
file path=usr/lib/brand/solaris10/s10_isaexec_wrapper mode=0755
file path=usr/lib/brand/solaris10/s10_native mode=0755
+file path=usr/lib/brand/solaris10/s10_replacefile mode=0755
file path=usr/lib/brand/solaris10/s10_support mode=0755
file path=usr/lib/brand/solaris10/smf_disable.lst mode=0444
file path=usr/lib/brand/solaris10/solaris10_librtld_db.so.1