[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#683261: live-build: please re-add losetup-lukshome hook



Package: live-build
Version: 3.0_a53-1
Severity: wishlist
Tags: patch

Dear Maintainer,

the losetup-lukshome hook was removed from live-build recently because 
it was broken since the recent live-boot changes.

I have corrected this and now the hook works in squeeze/wheezy/sid and 
should work with either old versions of live-boot and live-build, as with 
the more recent ones.

I've tested with a squeeze build and a sid build, with live-build 3.0_a54-1.

This new version has some other minor changes and improvements.

Attached is the complete script.

Thank you.

-- Package-specific info:

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=pt_PT.UTF-8, LC_CTYPE=pt_PT.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages live-build depends on:
ii  debootstrap  1.0.39

Versions of packages live-build recommends:
pn  cpio                            2.11-7
pn  gnu-fdisk                       <none>
pn  live-boot-doc                   3.0~a25-1
pn  live-config-doc                 3.0~a35-1
pn  live-manual-html | live-manual  <none>

Versions of packages live-build suggests:
pn  dosfstools                  <none>
pn  fakeroot                    1.18.2-1
pn  genisoimage                 <none>
pn  grub                        0.97-66
pn  memtest86+ | memtest86      <none>
pn  mtools                      <none>
pn  parted                      2.3-10
pn  squashfs-tools | mtd-tools  <none>
pn  sudo                        1.8.3p2-1
pn  syslinux                    2:4.05+dfsg-2
pn  uuid-runtime                <none>
pn  win32-loader                <none>

-- debconf-show failed
#!/bin/sh

## lukshome - a live-build(7) hook to have an encrypted /home
## Copyright (C) 2009-2012 Rui Bernardo <rui.bernardo.pt@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.

# This hook was based and adapted from:
# http://lists.debian.org/debian-live/2009/04/msg00186.html
# ---------------------------------------------------------
#
#
# NOTE 1: this was not tested with persistent boot option,
# but it seems logic that persistent and lukshome can't
# coexist as boot options (because of snapshots and others), so lukshome
# won't be executed if any persistent option is given on boot.
#
# NOTE 2: if using an USB key, it will eventualy end up failing someday.
# You should backup the encrypted disk image file itself (luks-home.img) to
# prevent loosing your data.
#
# This hook will create 3 files:
#
# /usr/local/sbin/create-lukshome-file.sh
#	script to create an disk file image (luks-home.img) with a
#	LUKS encrypted ext2 filesystem inside to be placed in a
#	partition labeled lukshome.
#
# /usr/local/sbin/lukshome.sh
#	detects a partition with lukshome label, updates fstab and crypttab so
#	the encrypted file is mounted later in a loopback device (/dev/loopX).
#	It also changes /etc/init.d/umountfs so the encrypted home is correctly
#	umounted.
#
# (old live-boot) /usr/share/initramfs-tools/scripts/live-bottom/13live_luks_home
# (new live-boot) /lib/live/boot/9999-live_luks_home
#	a live-initramfs hook to execute lukshome.sh script
#	in initrd.
#
#
# HOWTO lukshome
# --------------
#
# First build your live system with this hook inside config/chroot_local-hooks/.
# If you have an existing live-build build directory with a previous live
# build, you might have to run
#
#	lb clean
#
# to make sure this hook is included in the live system. Then (re)build your
# live system.
#
#	lb build
#
# After booting your (re)built live system, setup the encrypted losetup
# filesystem to be used as /home using the instructions present in the
# create-lukshome-file.sh script.
#
# Reboot and now use the "lukshome" boot option to mount the encrypted /home,
# like when using "persistent" boot option with a home-rw file in some partition.
#


# install needed packages (in case apt recommends are off)
# make sure that cryptsetup is installed
echo "I: checking for cryptsetup."
if [ ! -x /sbin/cryptsetup ]
then
	echo "I: installing cryptsetup."
	DEBIAN_FRONTEND="dialog" apt-get install --yes --force-yes -y cryptsetup
fi


echo "I: to see how to use lukshome hook run create-lukshome-file.sh as root."
echo "I: creating script /usr/local/sbin/create-lukshome-file.sh"
cat > /usr/local/sbin/create-lukshome-file.sh << 'EOF'
#!/bin/sh

# This script will create an encrypted filesystem in a file to
# be used as /home in a live system built with Debian Live with
# this hook in config/hooks/.
#
# The lukshome boot option will do the following:
#	- search for a partition with label 'lukshome'
#	  (btw, you can't use the live system partition itself)
#	- mount the partition as /luks-home in the live system
#	- open /luks-home/luks-home.img file as a loopback device (/dev/loop)
#	- open the loopback device with cryptsetup
#	- mount the encrypted filesystem as /home
#
# This script will only create the luks-home.img file. Next are details of how
# to use this script.
#
# CAUTION! THIS CAN WIPE YOUR DATA, backup first!
# Be sure to understand what you will do, or you can end up
# wiping disks or partitions you don't want to!
#
# Login as root:
#	$ sudo -i
#
# Create a mountpoint of the partition where the file will be:
#	# mkdir /media/target
#
# !!! ***  Skip the next line if you don't want to wipe a partition  *** !!!
# !!! * Just change the partition label to 'lukshome' (without quotes) * !!!
# Create an ext2 filesystem in a partition with 'lukshome' label:
#	# mkfs.ext2 -L lukshome /dev/the_partition_to_be_used
#
# Mount the partition and cd into it:
#	# mount /dev/the_partition_to_be_used /media/target
#	# cd /media/target
#
# Create the encrypted file:
#	# create-lukshome-file.sh [filename]
#
# The script is located in /usr/local/sbin/, so it's in root $PATH.
# It will copy the directories in /home/* into the file.
# Now return to $HOME to be able to umount the target partition:
#	# cd
#
# Umount the target partition:
#	# umount /media/target
#
# Reboot and use the "lukshome" boot option to mount the encrypted /home,
# like in using "persistent" boot option with a home-rw file in some partition.
#
# To use another partition label use the following boot options:
#	lukshome lukspart=partition_label
#
# If you want to use another filename instead of luks-home.img or the filename
# you chose, rename (mv) the file and use the following boot options:
#	lukshome luksfile=filename
#
# Both boot options can be used at the same time, but always with lukshome:
#	lukshome lukspart=partition_label luksfile=filename
#
# By default, if just the lukshome boot option is used, the script will
# search for a partition labeled 'lukshome' and a file named 'luks-home.img'.
#
# Press Shift-PgUp/Shift-PgDn to scrool the instructions on the screen.


# check if root/sudo
if [ "${USER}" != "root" ]
then
	echo " ** Please run this script as root or with sudo."
	exit 1
fi

LOSETUP_FILE="$1"
[ -z "$LOSETUP_FILE" ] && LOSETUP_FILE="luks-home.img"
echo " * going to create $LOSETUP_FILE"

# where the losetup file will be mounted
LOSETUP_MOUNT_POINT="/losetup-mount"
mkdir -p "$LOSETUP_MOUNT_POINT"

# check if $LOSETUP_MOUNT_POINT is available and empty
mount | grep "$LOSETUP_MOUNT_POINT" > /dev/null
TARGET_IS_MOUNTED=${?}
if [ "${TARGET_IS_MOUNTED}" = 0 ]
then
	echo "** ERROR: $LOSETUP_MOUNT_POINT is mounted at the moment. Please umount it to use this script."
	exit 1
fi
if [ -n "$(ls -A $LOSETUP_MOUNT_POINT)" ]
then
	echo "** ERROR: $LOSETUP_MOUNT_POINT is not empty. An empty $LOSETUP_MOUNT_POINT is needed to use this script."
	exit 1
fi
if [ -n "$(pwd|grep '^/home/')" ]
then
	echo "** ERROR: inside /home/ (recursivity)."
	echo "   Please move out of /home/. The encrypted file cannot be inside /home/."
	exit 1
fi

# check if /dev/mapper/luks-home is available
if [ -f /dev/mapper/luks-home ]
then
	echo "** ERROR: /dev/mapper/luks-home is being used at the moment. Please run «cryptsetup remove luks-home» to use this script."
	exit 1
fi


# show instructions
echo ""
echo "** Usage: create-lukshome-file.sh [filename]"
sed -n '2,64p' /usr/local/sbin/create-lukshome-file.sh | sed 's/^.//'
echo ""


# proceed?
echo "** Do you want to proceed with this script? (y/N)"
read CONFIRM

case "${CONFIRM}" in
	y*|Y*)
		echo ""
	;;
	*)
		exit 0
	;;
esac


# create file
echo ""
echo "** Please type the size of the file disk image."
echo "Size of the file in MB: "
read FILE_SIZE

echo ""
echo "** Creating file $LOSETUP_FILE."
echo "** Filling file image with /dev/urandom output. It will take some time."
echo "(Edit this script to use /dev/random. It's known to be more secure but "
echo "it will take a *very* long time to complete."
dd if=/dev/urandom of=$LOSETUP_FILE bs=1M count=${FILE_SIZE}
# To use /dev/random comment the line above and uncomment the next line
#dd if=/dev/random of=$LOSETUP_FILE ibs=128 obs=128 count=$((8192*${FILE_SIZE}))
# You might have to increase kernel entropy by moving the mouse, typing keyboard,
# make the computer read the disk or use network connections.
echo "** Done."
echo ""

# losetup
FREE_LOSETUP=$(losetup -f)
echo "** Using ${FREE_LOSETUP} to open $LOSETUP_FILE"
losetup ${FREE_LOSETUP} $LOSETUP_FILE
echo "** Done."
echo ""

# cryptsetup
echo "** Running cryptsetup."
echo ""
echo "** luksFormat"
cryptsetup luksFormat ${FREE_LOSETUP}
EXIT_CODE=${?}
if [ "${EXIT_CODE}" != 0 ]
then
	echo "** ERROR: Error while trying to format disk file image."
	losetup -d ${FREE_LOSETUP}
	exit 1
fi
echo ""

echo "** luksOpen"
cryptsetup luksOpen ${FREE_LOSETUP} luks-home
EXIT_CODE=${?}
if [ "${EXIT_CODE}" != 0 ]
then
	echo "** ERROR: Error while trying to open LUKS file image."
	losetup -d ${FREE_LOSETUP}
	exit 1
fi
echo ""

# format encrypted filesystem
echo "** Now formating /dev/mapper/luks-home"
mkfs.ext2 /dev/mapper/luks-home
EXIT_CODE=${?}
if [ "${EXIT_CODE}" != 0 ]
then
	echo "** ERROR: Error while trying to format LUKS file."
	cryptsetup remove luks-home
	losetup -d ${FREE_LOSETUP}
	exit 1
fi
echo ""

# mount in $LOSETUP_MOUNT_POINT
echo "** Now mounting $LOSETUP_FILE in $LOSETUP_MOUNT_POINT"
mount /dev/mapper/luks-home "$LOSETUP_MOUNT_POINT"
EXIT_CODE=${?}
if [ "${EXIT_CODE}" != 0 ]
then
	echo "** ERROR: Error while trying to mount LUKS file in $LOSETUP_MOUNT_POINT."
	umount $LOSETUP_MOUNT_POINT
	cryptsetup remove luks-home
	losetup -d ${FREE_LOSETUP}
	exit 1
fi
echo ""

# copy files
HOME_DIR="/home/*"

echo "** Copying ${HOME_DIR}."
cp -rav ${HOME_DIR} "${LOSETUP_MOUNT_POINT}"
EXIT_CODE=${?}
if [ "${EXIT_CODE}" != 0 ]
then
	echo "** ERROR: Error while trying to copy files to $LOSETUP_MOUNT_POINT."
	umount $LOSETUP_MOUNT_POINT
	cryptsetup remove luks-home
	losetup -d ${FREE_LOSETUP}
	exit 1
fi
echo "** Done."
echo ""

echo "** All done."
echo "** Closing losetup, cryptsetup and mounted $LOSETUP_MOUNT_POINT."
# umount and close
umount $LOSETUP_MOUNT_POINT
cryptsetup remove luks-home
losetup -d ${FREE_LOSETUP}
rmdir $LOSETUP_MOUNT_POINT 2>/dev/null
echo "** The disk file image $LOSETUP_FILE is done and ready. Move it into a partition"
echo "** with 'lukshome' as label and reboot with lukshome boot option to use it."
echo ""

EOF

chmod 0755 /usr/local/sbin/create-lukshome-file.sh



echo "I: creating script /usr/local/sbin/lukshome.sh"
cat > /usr/local/sbin/lukshome.sh << 'EOF'
#!/bin/sh

# this script is to be executed by a hook in live-initramfs. It searches
# for a partition with 'lukshome' label, mounts it as /luks-home, then opens an
# encrypted disk image file called luks-home.img as a loopback device, opens it
# with cryptsetup and finally mounts the present filesystem as /home.
# It also changes /etc/init.d/umountfs to umount the lukshome partition
#  (/luks-home) and clear the loopback device on shutdown.

# functions taken from live-helpers
if [ -e /usr/share/initramfs-tools/scripts/live-helpers ]
then
	# squeeze
	. /usr/share/initramfs-tools/scripts/live-helpers
else
	# post-squeeze
	. /usr/share/initramfs-tools/scripts/live
fi

# set default values
LUKSPART="lukshome"
LUKSFILE="luks-home.img"

# get boot option lukshome - adapted from live-helpers
for ARGUMENT in $(cat /proc/cmdline)
do
	case "${ARGUMENT}" in
		lukshome)
			LUKSHOME=1
			;;
		luksfile=*)
			LUKSFILE="${ARGUMENT#luksfile=}"
			LUKSHOME=1
			;;
		lukspart=*)
			LUKSPART="${ARGUMENT#lukspart=}"
			LUKSHOME=1
			;;

	esac
done

if [ -x /sbin/blkid ]
then
	CRYPTHOME=$(/sbin/blkid -L ${LUKSPART})
else
	# search for a partition labeled "lukshome" or $LUKSPART
	for sysblock in $(echo /sys/block/* | tr ' ' '\n' | grep -v loop | grep -v ram | grep -v fd)
	do
		for dev in $(subdevices "${sysblock}")
		do
			devname=$(sys2dev "${dev}")
			# find partition name and filesystem type
			if [ "$(/lib/udev/vol_id -l ${devname} 2>/dev/null)" = "${LUKSPART}" ]
			then
				# found one partition with correct label
				CRYPTHOME="${devname}"
				# don't search further
				break
			fi
		done
		# if already found, don't search further
		if [ -n "${CRYPTHOME}" ]
		then
			break
		fi
	done
fi

# if no partition found, exit
if [ -z "${CRYPTHOME}" ]
then
	echo "Could not find any partition with ${LUKSPART} label. "
	echo "Proceeding with no encrypted /home."
	exit 0
fi

# mount partition where file container is
echo "Mounting /luks-home with ${CRYPTHOME}."
mkdir -p /luks-home
mount -t $(get_fstype "${CRYPTHOME}") "${CRYPTHOME}" /luks-home

# mount losetup encrypted file
FREE_LOOP="$(/sbin/losetup -f)"
echo "Opening file /luks-home/${LUKSFILE} in ${FREE_LOOP}."

if [ -f /luks-home/"${LUKSFILE}" ]
then
	/sbin/losetup ${FREE_LOOP} /luks-home/"${LUKSFILE}"

	echo "Adding ${FREE_LOOP} home to /etc/crypttab and setting it as /home in /etc/fstab."

	# update crypttab
	echo "home	${FREE_LOOP}	none	luks,check,timeout" >> /etc/crypttab

	# update fstab
	echo "/dev/mapper/home	/home	ext2	defaults,noatime	0	0" >> /etc/fstab
else
	echo "Did not found any file named ${LUKSFILE} in ${CRYPTHOME}!"
	echo "Proceeding with no encrypted /home."
	sleep 2
	umount -r /luks-home
	exit 0
fi

# changes to /etc/init.d/umountfs to make /luks-home being umounted on shutdown
sed -i 's/[\t]do_stop/CHANGE_HERE/' /etc/init.d/umountfs
sed -i 's|CHANGE_HERE|	\
	# added by lukshome hook -  umount \/luks-home to prevent busy device on shutdown \
	LOOP_LUKSHOME=$(losetup -a \| grep luks-home \|cut -c 1-10) \
	if [ -n ${LOOP_LUKSHOME} ] \
	then \
		umount -r -d \/home \
		cryptsetup remove home \
		losetup -d ${LOOP_LUKSHOME} \
		umount -r \/luks-home \
	fi \
\
	do_stop \
|' /etc/init.d/umountfs

EOF

chmod 0755 /usr/local/sbin/lukshome.sh



# scripts/live-bottom/13live_luks_home, right after 12fstab
# or /lib/live/boot/9999-live_luks_home in new live-boot

set -x
LIVE_BOOT_DIR="/usr/share/initramfs-tools/scripts/live-bottom/"
[ ! -e "$LIVE_BOOT_DIR" ] && LIVE_BOOT_DIR="/lib/live/boot/"

if [ -e "$LIVE_BOOT_DIR" ]
then
	# since live-boot 3.0~a29 root is mounted in a different way.
	# the script can be mountroot or main. check if any of them exist.
	MOUNT_ROOT_SCRIPT="$(ls $LIVE_BOOT_DIR | grep main.sh)"
	[ -z "$MOUNT_ROOT_SCRIPT" ] && MOUNT_ROOT_SCRIPT="$(ls $LIVE_BOOT_DIR | grep mountroot.sh)"

	# add script right after fstab in initramfs-tools (old)
	[ -z "$MOUNT_ROOT_SCRIPT" ] && LUKSHOME_INIT_SCRIPT="13live_luks_home"
	# add script to be sources by live-boot in /lib/live/boot (new)
	[ -n "$MOUNT_ROOT_SCRIPT" ] && LUKSHOME_INIT_SCRIPT="9999-live_luks_home"
	# add path to whichever filename
	LUKSHOME_INIT_SCRIPT="$LIVE_BOOT_DIR""$LUKSHOME_INIT_SCRIPT"

	# patch main.sh to run lukshome after Fstab in main.sh (new only)
	if [ -n "$MOUNT_ROOT_SCRIPT" ]
	then
		sed -i '/^[\t]Fstab/ a \
	# added by lukshome script \
	luks_home
' "$LIVE_BOOT_DIR""$MOUNT_ROOT_SCRIPT"
	fi

	# check
	[ -z "$LUKSHOME_INIT_SCRIPT" ] && echo " * lukshome hook error: could not find fstab script" && exit 0

	echo "I: creating $LUKSHOME_INIT_SCRIPT"

set +x
# create boot script in the right place with right filename
cat > $LUKSHOME_INIT_SCRIPT << 'EOF'
#!/bin/sh

#set -e

luks_home()
{

# initramfs-tools header

PREREQ=""

prereqs()
{
	echo "${PREREQ}"
}

case "${1}" in
	prereqs)
		prereqs
		exit 0
		;;
esac

if [ -e /scripts/live-functions ]
then
	# squeeze
	. /scripts/live-functions
else
	# post-squeeze
	. /scripts/functions
fi

# live-initramfs hook to use an disk image file with encrypted filesystem as /home.

log_begin_msg "Executing losetup-lukshome"

# get boot option lukshome - adapted from live-helpers
for ARGUMENT in $(cat /proc/cmdline)
do
	case "${ARGUMENT}" in
		lukshome)
			LUKSHOME=1
			;;
		luksfile=*)
			LUKSFILE="${ARGUMENT#luksfile=}"
			LUKSHOME=1
			;;
		lukspart=*)
			LUKSPART="${ARGUMENT#lukspart=}"
			LUKSHOME=1
			;;

	esac
done

# don't use persistent* and lukshome
if ([ -n "${PERSISTENT}" ] || [ -n "${PERSISTENCE}" ]) && [  -n "${LUKSHOME}" ]
then
	echo "You should not use persistent and lukshome at the same time."
	echo "Skipping lukshome. Persistent medium, if any, will be used instead."
	log_end_msg
	exit 0
fi

# if no lukshome boot option, exit
if [ -z "${LUKSHOME}" ]
then
	log_end_msg
	exit 0
fi

log_begin_msg "Executing lukshome.sh script."

mount -o bind /sys /root/sys
mount -o bind /proc /root/proc
mount -o bind /dev /root/dev

# lukshome.sh detects lukshome partition and file location, mounts it
# and opens the file and then updates fstab and crypttab to use it as /home.
chroot /root /usr/local/sbin/lukshome.sh

umount /root/sys
umount /root/proc
umount /root/dev

# delete the lukshome.sh script, not needed anymore
# rm -f /root/usr/local/sbin/lukshome.sh

log_end_msg

}

# execute it immediatly in old live-boot;
# sourced in new live-boot and executed inside mountroot
[ -e /scripts/live-functions ] && luks_home

EOF

	chmod 0755 $LUKSHOME_INIT_SCRIPT	

fi



echo "I: update-initramfs to include $LUKSHOME_INIT_SCRIPT."

for KERNEL in /boot/vmlinuz-*
do
	VERSION="$(basename ${KERNEL} | sed -e 's|vmlinuz-||')"

	update-initramfs -k ${VERSION} -t -u
done

Reply to: