From a7491e13497b24d20517535ae7c767c7f32c40a1 Mon Sep 17 00:00:00 2001
From: Jesse Hathaway <jesse@mbuki-mvuki.org>
Date: Tue, 23 Oct 2007 16:56:43 -0400
Subject: add exposedroot option which exposes the root fs as ro

This option allows you to expose the root read only.  Using
this option a person could upgrade the root filesystem or
add packages without requiring the user to reboot. The root
filesystem could be kept on an nfs volume or some other
persistent medium. Multiple clients could then be booted off
the same root fs. I used LTSP as a template to determine which
directories to make rw.
---
 functions/defaults.sh      |  3 +++
 helpers/lh_binary_grub     |  5 +++++
 helpers/lh_binary_syslinux |  5 +++++
 helpers/lh_binary_yaboot   |  5 +++++
 helpers/lh_chroot_hacks    | 39 +++++++++++++++++++++++++++++++++++++++
 helpers/lh_chroot_hosts    |  5 +++--
 helpers/lh_config          | 12 +++++++++++-
 7 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/functions/defaults.sh b/functions/defaults.sh
index 715e568..8a876f0 100755
--- a/functions/defaults.sh
+++ b/functions/defaults.sh
@@ -298,6 +298,9 @@ Set_defaults ()
 	# Setting chroot filesystem
 	LH_CHROOT_FILESYSTEM="${LH_CHROOT_FILESYSTEM:-squashfs}"
 
+	# Setting whether to expose root filesystem as read only
+	LH_EXPOSED_ROOT="${LH_EXPOSED_ROOT:-disabled}"
+
 	# Setting union filesystem
 	if [ -z "${LH_UNION_FILESYSTEM}" ]
 	then
diff --git a/helpers/lh_binary_grub b/helpers/lh_binary_grub
index 9ba3286..1c05962 100755
--- a/helpers/lh_binary_grub
+++ b/helpers/lh_binary_grub
@@ -178,6 +178,11 @@ then
 	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} union=${LH_UNION_FILESYSTEM}"
 fi
 
+if [ "${LH_EXPOSED_ROOT}" != "disabled" ]
+then
+	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} exposedroot"
+fi
+
 LH_BOOTAPPEND_LIVE="$(echo ${LH_BOOTAPPEND_LIVE} | sed -e 's/  //')"
 
 # Parameters are listed at: linux/Documentation/kernel-parameters.txt
diff --git a/helpers/lh_binary_syslinux b/helpers/lh_binary_syslinux
index 68fa0f3..a6eb400 100755
--- a/helpers/lh_binary_syslinux
+++ b/helpers/lh_binary_syslinux
@@ -403,6 +403,11 @@ then
 	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} union=${LH_UNION_FILESYSTEM}"
 fi
 
+if [ "${LH_EXPOSED_ROOT}" != "disabled" ]
+then
+	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} exposedroot"
+fi
+
 if [ "${LH_BINARY_IMAGES}" = "net" ]
 then
 	case "${LH_NET_FILESYSTEM}" in
diff --git a/helpers/lh_binary_yaboot b/helpers/lh_binary_yaboot
index 8cffb3f..93fc0bb 100755
--- a/helpers/lh_binary_yaboot
+++ b/helpers/lh_binary_yaboot
@@ -186,6 +186,11 @@ then
 	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} union=${LH_UNION_FILESYSTEM}"
 fi
 
+if [ "${LH_EXPOSED_ROOT}" != "disabled" ]
+then
+	LH_BOOTAPPEND_LIVE="${LH_BOOTAPPEND_LIVE} exposedroot"
+fi
+
 LH_BOOTAPPEND_LIVE="$(echo ${LH_BOOTAPPEND_LIVE} | sed -e 's/  //')"
 
 # Parameters are listed at: linux/Documentation/kernel-parameters.txt
diff --git a/helpers/lh_chroot_hacks b/helpers/lh_chroot_hacks
index da2be17..6eaef4f 100755
--- a/helpers/lh_chroot_hacks
+++ b/helpers/lh_chroot_hacks
@@ -111,5 +111,44 @@ then
 	chown -R --quiet 999:999 chroot/home/${LH_USERNAME}
 fi
 
+if [ "${LH_EXPOSED_ROOT}" = "enabled" ]
+then
+	# Make sure RW dirs exist so that the initramfs script has
+	# a directory in which to bind the tmpfs filesystems
+	COW_DIRS='/tmp /var/tmp /var/lock /var/run /var/lib/live /var/log
+		/var/spool /home /live'
+	for DIR in ${COW_DIRS}; do
+		mkdir -p chroot${DIR}
+	done
+
+	# Config files which need to be RW
+	CONFIG_FILES='/etc/hostname /etc/hosts /etc/resolv.conf /etc/fstab
+		/etc/live.conf /etc/network/interfaces /etc/X11/xorg.conf
+		/etc/udev/rules.d/z25_persistent-net.rules
+		/etc/udev/rules.d/z25_persistent-cd.rules'
+
+	# Where we will store RW config files
+	RW_DIR='/var/lib/live'
+
+	for FILE_PATH in ${CONFIG_FILES}
+	do
+		# Touch files in case they don't yet exist
+		FILE_DIR=$(dirname ${FILE_PATH})
+		mkdir -p chroot${FILE_DIR}
+		touch chroot${FILE_PATH}
+		FILE_NAME=$(basename ${FILE_PATH})
+		mkdir -p chroot${RW_DIR}${FILE_DIR}
+		mv chroot${FILE_PATH} chroot${RW_DIR}${FILE_DIR}
+		# Create a symbolic link to RW config file
+		RELATIVE_PATH=$(echo ${FILE_DIR}|sed 's/[^\/]\+/../g; s/^\///g')
+		ln -s ${RELATIVE_PATH}${RW_DIR}${FILE_PATH} chroot${FILE_PATH}
+	done
+
+	# Mount doesn't write to a symlink so use /proc/mounts instead,
+	# see debian bug #154438 for more info
+	rm chroot/etc/mtab
+	ln -s /proc/mounts chroot/etc/mtab
+fi
+
 # Creating stage file
 Create_stagefile .stage/chroot_hacks
diff --git a/helpers/lh_chroot_hosts b/helpers/lh_chroot_hosts
index c4d633e..8480383 100755
--- a/helpers/lh_chroot_hosts
+++ b/helpers/lh_chroot_hosts
@@ -87,8 +87,9 @@ EOF
 			# Restore hosts file
 			mv chroot/etc/hosts.orig chroot/etc/hosts
 		else
-			# Remove hosts file
-			rm -f chroot/etc/hosts
+			# Blank out hosts file, don't remove in case
+			# its a symlink, as in the case of exposedroot mode
+			cat /dev/null > chroot/etc/hosts
 		fi
 
 		# Removing stage file
diff --git a/helpers/lh_config b/helpers/lh_config
index 5fc2f7c..c702b7d 100755
--- a/helpers/lh_config
+++ b/helpers/lh_config
@@ -96,12 +96,13 @@ USAGE="${PROGRAM} [--apt apt|aptitude]\n\
 \t    [--tasks TASK]\n\
 \t    [--templates PATH]\n\
 \t    [--union-filesystem aufs|unionfs]\n\
+\t    [--exposed-root enabled|disabled]\n\
 \t    [--username NAME]\n\
 \t    [--verbose]"
 
 Local_arguments ()
 {
-	ARGUMENTS="$(getopt --longoptions apt:,apt-ftp-proxy:,apt-http-proxy:,apt-pdiffs:,apt-pipeline:,apt-recommends:,apt-secure:,bootstrap:,cache:,cache-indices:,cache-packages:,cache-stages:,debconf-frontend:,debconf-nowarnings:,debconf-priority:,genisoimage:,initramfs:,losetup:,mode:,root-command:,tasksel:,includes:,templates:,architecture:,bootstrap-config:,bootstrap-flavour:,bootstrap-keyring:,distribution:,mirror-bootstrap:,mirror-bootstrap-security:,mirror-binary:,mirror-binary-security:,sections:,chroot-filesystem:,union-filesystem:,hooks:,interactive:,keyring-packages:,language:,linux-flavours:,linux-packages:,packages:,packages-lists:,tasks:,security:,symlinks:,sysvinit:,binary-images:,binary-indices:,bootappend-install:,bootappend-live:,bootloader:,chroot-build:,debian-installer:,debian-installer-daily:,encryption:,grub-splash:,hostname:,iso-application:,iso-preparer:,iso-publisher:,iso-volume:,memtest:,net-filesystem:,net-mountoptions:,net-path:,net-server:,syslinux-splash:,syslinux-timeout:,username:,source:,source-images:,breakpoints,conffile:,debug,force,help,quiet,usage,verbose,version --name=${PROGRAM} --options a:f:d:m:l:k:p:b:e:s:c:huv --shell sh -- "${@}")"
+	ARGUMENTS="$(getopt --longoptions apt:,apt-ftp-proxy:,apt-http-proxy:,apt-pdiffs:,apt-pipeline:,apt-recommends:,apt-secure:,bootstrap:,cache:,cache-indices:,cache-packages:,cache-stages:,debconf-frontend:,debconf-nowarnings:,debconf-priority:,genisoimage:,initramfs:,losetup:,mode:,root-command:,tasksel:,includes:,templates:,architecture:,bootstrap-config:,bootstrap-flavour:,bootstrap-keyring:,distribution:,mirror-bootstrap:,mirror-bootstrap-security:,mirror-binary:,mirror-binary-security:,sections:,chroot-filesystem:,union-filesystem:,exposed-root:,hooks:,interactive:,keyring-packages:,language:,linux-flavours:,linux-packages:,packages:,packages-lists:,tasks:,security:,symlinks:,sysvinit:,binary-images:,binary-indices:,bootappend-install:,bootappend-live:,bootloader:,chroot-build:,debian-installer:,debian-installer-daily:,encryption:,grub-splash:,hostname:,iso-application:,iso-preparer:,iso-publisher:,iso-volume:,memtest:,net-filesystem:,net-mountoptions:,net-path:,net-server:,syslinux-splash:,syslinux-timeout:,username:,source:,source-images:,breakpoints,conffile:,debug,force,help,quiet,usage,verbose,version --name=${PROGRAM} --options a:f:d:m:l:k:p:b:e:s:c:huv --shell sh -- "${@}")"
 
 	if [ "${?}" != "0" ]
 	then
@@ -317,6 +318,11 @@ Local_arguments ()
 				shift 2
 				;;
 
+			--exposed-root)
+				LH_EXPOSED_ROOT="${2}"
+				shift 2
+				;;
+
 			--hooks)
 				LH_HOOKS="${2}"
 				shift 2
@@ -773,6 +779,10 @@ LH_CHROOT_FILESYSTEM="${LH_CHROOT_FILESYSTEM}"
 # (Default: ${LH_UNION_FILESYSTEM}
 LH_UNION_FILESYSTEM="${LH_UNION_FILESYSTEM}"
 
+# \$LH_EXPOSED_ROOT: expose root as read only
+# (Default: ${LH_EXPOSED_ROOT})
+LH_EXPOSED_ROOT="${LH_EXPOSED_ROOT}"
+
 # \$LH_HOOKS: set hook commands
 # (Default: empty)
 LH_HOOKS="${LH_HOOKS}"
-- 
cgit v1.0