svn commit: r196393 - in stable/8: etc share/man/man5 usr.sbin/freebsd-update

Simon L. Nielsen simon at FreeBSD.org
Wed Aug 19 21:01:33 UTC 2009


Author: simon
Date: Wed Aug 19 21:01:32 2009
New Revision: 196393
URL: http://svn.freebsd.org/changeset/base/196393

Log:
  MFC 196392:
  
    Add support for backing up the old kernel when installing a new kernel
    using freebsd-update.  This applies to using freebsd-update in "upgrade
    mode" and normal freebsd-update on a security branch.
  
    The backup kernel will be written to /boot/kernel.old, if the directory
    does not exist, or the directory was created by freebsd-update in a
    previous backup.  Otherwise freebsd-update will generate a new directory
    name for use by the backup.  By default symbol files are not backed up
    to save diskspace and avoid filling up the root partition.
  
    This feature is fully configurable in the freebsd-update config file,
    but defaults to enabled.
  
    Reviewed by:	cperciva
  
  Approved by:	re (kib)

Modified:
  stable/8/etc/   (props changed)
  stable/8/etc/freebsd-update.conf
  stable/8/share/man/man5/   (props changed)
  stable/8/share/man/man5/freebsd-update.conf.5
  stable/8/usr.sbin/freebsd-update/   (props changed)
  stable/8/usr.sbin/freebsd-update/freebsd-update.sh

Modified: stable/8/etc/freebsd-update.conf
==============================================================================
--- stable/8/etc/freebsd-update.conf	Wed Aug 19 20:47:31 2009	(r196392)
+++ stable/8/etc/freebsd-update.conf	Wed Aug 19 21:01:32 2009	(r196393)
@@ -63,3 +63,14 @@ MergeChanges /etc/ /var/named/etc/ /boot
 # which *might* be installed of which FreeBSD Update should figure out
 # which actually are installed and upgrade those (StrictComponents no)?
 # StrictComponents no
+
+# When installing a new kernel perform a backup of the old one first
+# so it is possible to boot the old kernel in case of problems.
+# BackupKernel yes
+
+# If BackupKernel is enabled, the backup kernel is saved to this
+# directory.
+# BackupKernelDir /boot/kernel.old
+
+# When backing up a kernel also back up debug symbol files?
+# BackupKernelSymbolFiles no

Modified: stable/8/share/man/man5/freebsd-update.conf.5
==============================================================================
--- stable/8/share/man/man5/freebsd-update.conf.5	Wed Aug 19 20:47:31 2009	(r196392)
+++ stable/8/share/man/man5/freebsd-update.conf.5	Wed Aug 19 21:01:32 2009	(r196393)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 30, 2006
+.Dd August 19, 2009
 .Dt FREEBSD-UPDATE.CONF 5
 .Os FreeBSD
 .Sh NAME
@@ -48,7 +48,7 @@ error.
 .Pp
 The possible options and their meanings are as follows:
 .Pp
-.Bl -tag -width "KeepModifiedMetadata"
+.Bl -tag -width ".Cm BackupKernelSymbolFiles"
 .It Cm KeyPrint
 The single parameter following this keyword is the SHA256 hash
 of the RSA key which will be trusted to sign updates.
@@ -171,6 +171,54 @@ command is used ("yes"), or merely as a 
 which might be installed, of which
 .Cm freebsd-update
 should identify which in fact are present ("no").
+.It Cm BackupKernel
+The single parameter following this keyword must be
+.Dq yes
+or
+.Dq no
+and specifies whether
+.Cm freebsd-update
+will create a backup of the old kernel before installing a new kernel.
+This backup kernel can be used to recover a system where the newly
+installed kernel somehow did not work.
+Note that the backup kernel is not reverted to its original state by
+the
+.Cm freebsd-update
+rollback command.
+.It Cm BackupKernelDir
+This keyword sets the directory which is used to store a backup
+kernel, if the BackupKernel feature is enabled.
+If the directory already exist, and it was not created by
+.Cm freebsd-update ,
+the directory is skipped.
+In the case of the primary directory name not being usable, a number
+starting with
+.Sq 1
+is appended to the directory name.
+Like with the primary directory name, the constructed directory name is
+only used if the path name does not exist, or if the directory was
+previously created by
+.Cm freebsd-update .
+If the constructed directory still exist the appended number is
+incremented with 1 and the directory search process restarted.
+Should the number increment go above 9,
+.Cm freebsd-update
+will abort.
+.It Cm BackupKernelSymbolFiles
+The single parameter following this keyword must be
+.Dq yes
+or
+.Dq no
+and specifies whether
+.Cm freebsd-update
+will also backup kernel symbol files, if they exist.
+The kernel symbol files takes up a lot of disk space and are not
+needed for recovery purposes.
+If the symbol files are needed, after recovering a system using the
+backup kernel, the
+.Cm freebsd-update
+rollback command will recreate the symbol files along with the old
+kernel.
 .El
 .Sh FILES
 .Bl -tag -width "/etc/freebsd-update.conf"

Modified: stable/8/usr.sbin/freebsd-update/freebsd-update.sh
==============================================================================
--- stable/8/usr.sbin/freebsd-update/freebsd-update.sh	Wed Aug 19 20:47:31 2009	(r196392)
+++ stable/8/usr.sbin/freebsd-update/freebsd-update.sh	Wed Aug 19 21:01:32 2009	(r196393)
@@ -88,7 +88,7 @@ EOF
 CONFIGOPTIONS="KEYPRINT WORKDIR SERVERNAME MAILTO ALLOWADD ALLOWDELETE
     KEEPMODIFIEDMETADATA COMPONENTS IGNOREPATHS UPDATEIFUNMODIFIED
     BASEDIR VERBOSELEVEL TARGETRELEASE STRICTCOMPONENTS MERGECHANGES
-    IDSIGNOREPATHS"
+    IDSIGNOREPATHS BACKUPKERNEL BACKUPKERNELDIR BACKUPKERNELSYMBOLFILES"
 
 # Set all the configuration options to "".
 nullconfig () {
@@ -308,6 +308,70 @@ config_VerboseLevel () {
 	fi
 }
 
+config_BackupKernel () {
+	if [ -z ${BACKUPKERNEL} ]; then
+		case $1 in
+		[Yy][Ee][Ss])
+			BACKUPKERNEL=yes
+			;;
+		[Nn][Oo])
+			BACKUPKERNEL=no
+			;;
+		*)
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
+config_BackupKernelDir () {
+	if [ -z ${BACKUPKERNELDIR} ]; then
+		if [ -z "$1" ]; then
+			echo "BackupKernelDir set to empty dir"
+			return 1
+		fi
+
+		# We check for some paths which would be extremely odd
+		# to use, but which could cause a lot of problems if
+		# used.
+		case $1 in
+		/|/bin|/boot|/etc|/lib|/libexec|/sbin|/usr|/var)
+			echo "BackupKernelDir set to invalid path $1"
+			return 1
+			;;
+		/*)
+			BACKUPKERNELDIR=$1
+			;;
+		*)
+			echo "BackupKernelDir ($1) is not an absolute path"
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
+config_BackupKernelSymbolFiles () {
+	if [ -z ${BACKUPKERNELSYMBOLFILES} ]; then
+		case $1 in
+		[Yy][Ee][Ss])
+			BACKUPKERNELSYMBOLFILES=yes
+			;;
+		[Nn][Oo])
+			BACKUPKERNELSYMBOLFILES=no
+			;;
+		*)
+			return 1
+			;;
+		esac
+	else
+		return 1
+	fi
+}
+
 # Handle one line of configuration
 configline () {
 	if [ $# -eq 0 ]; then
@@ -461,6 +525,9 @@ default_params () {
 	config_BaseDir /
 	config_VerboseLevel stats
 	config_StrictComponents no
+	config_BackupKernel yes
+	config_BackupKernelDir /boot/kernel.old
+	config_BackupKernelSymbolFiles no
 
 	# Merge these defaults into the earlier-configured settings
 	mergeconfig
@@ -665,6 +732,14 @@ install_check_params () {
 		echo "Re-run '$0 fetch'."
 		exit 1
 	fi
+
+	# Figure out what directory contains the running kernel
+	BOOTFILE=`sysctl -n kern.bootfile`
+	KERNELDIR=${BOOTFILE%/kernel}
+	if ! [ -d ${KERNELDIR} ]; then
+		echo "Cannot identify running kernel"
+		exit 1
+	fi
 }
 
 # Perform sanity checks and set some final parameters in
@@ -2494,6 +2569,88 @@ install_unschg () {
 	rm filelist
 }
 
+# Decide which directory name to use for kernel backups.
+backup_kernel_finddir () {
+	CNT=0
+	while true ; do
+		# Pathname does not exist, so it is OK use that name
+		# for backup directory.
+		if [ ! -e $BACKUPKERNELDIR ]; then
+			return 0
+		fi
+
+		# If directory do exist, we only use if it has our
+		# marker file.
+		if [ -d $BACKUPKERNELDIR -a \
+			-e $BACKUPKERNELDIR/.freebsd-update ]; then
+			return 0
+		fi
+
+		# We could not use current directory name, so add counter to
+		# the end and try again.
+		CNT=$((CNT + 1))
+		if [ $CNT -gt 9 ]; then
+			echo "Could not find valid backup dir ($BACKUPKERNELDIR)"
+			exit 1
+		fi
+		BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`"
+		BACKUPKERNELDIR="${BACKUPKERNELDIR}${CNT}"
+	done
+}
+
+# Backup the current kernel using hardlinks, if not disabled by user.
+# Since we delete all files in the directory used for previous backups
+# we create a marker file called ".freebsd-update" in the directory so
+# we can determine on the next run that the directory was created by
+# freebsd-update and we then do not accidentally remove user files in
+# the unlikely case that the user has created a directory with a
+# conflicting name.
+backup_kernel () {
+	# Only make kernel backup is so configured.
+	if [ $BACKUPKERNEL != yes ]; then
+		return 0
+	fi
+
+	# Decide which directory name to use for kernel backups.
+	backup_kernel_finddir
+
+	# Remove old kernel backup files.  If $BACKUPKERNELDIR was
+	# "not ours", backup_kernel_finddir would have exited, so
+	# deleting the directory content is as safe as we can make it.
+	if [ -d $BACKUPKERNELDIR ]; then
+		rm -f $BACKUPKERNELDIR/*
+	fi
+
+	# Create directory for backup if it doesn't exist.
+	mkdir -p $BACKUPKERNELDIR
+
+	# Mark the directory as having been created by freebsd-update.
+	touch $BACKUPKERNELDIR/.freebsd-update
+	if [ $? -ne 0 ]; then
+		echo "Could not create kernel backup directory"
+		exit 1
+	fi
+
+	# Disable pathname expansion to be sure *.symbols is not
+	# expanded.
+	set -f
+
+	# Use find to ignore symbol files, unless disabled by user.
+	if [ $BACKUPKERNELSYMBOLFILES = yes ]; then
+		FINDFILTER=""
+	else
+		FINDFILTER=-"a ! -name *.symbols"
+	fi
+
+	# Backup all the kernel files using hardlinks.
+	find $KERNELDIR -type f $FINDFILTER | \
+		sed -Ee "s,($KERNELDIR)/?(.*),\1/\2 ${BACKUPKERNELDIR}/\2," | \
+		xargs -n 2 cp -pl
+
+	# Re-enable patchname expansion.
+	set +f
+}
+
 # Install new files
 install_from_index () {
 	# First pass: Do everything apart from setting file flags.  We
@@ -2575,6 +2732,9 @@ install_files () {
 		grep -E '^/boot/' $1/INDEX-OLD > INDEX-OLD
 		grep -E '^/boot/' $1/INDEX-NEW > INDEX-NEW
 
+		# Backup current kernel before installing a new one
+		backup_kernel || return 1
+
 		# Install new files
 		install_from_index INDEX-NEW || return 1
 


More information about the svn-src-all mailing list