Skip to content

Instantly share code, notes, and snippets.

@Andrei-Pozolotin
Last active November 7, 2021 07:33
Show Gist options
  • Save Andrei-Pozolotin/2ab50d4f160c2ed8bd1a to your computer and use it in GitHub Desktop.
Save Andrei-Pozolotin/2ab50d4f160c2ed8bd1a to your computer and use it in GitHub Desktop.
ubuntu 14.04 cryptsetup luks suspend/resume root partition
#!/bin/bash
#
# ubuntu 14.04 cryptsetup luks suspend/resume root partition sleep activation
#
source=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # install script folder
target=/run/pm-crypto # chroot environment folder
bind_list="/dev /proc /sys /run" # special system mounts
target_create() {
echo "create chroot environment"
[[ $target == /run/* ]] && mount -o remount,exec /run # permit execution in chroot
rm -r -f $target
mkdir -p $target
setup_progs
setup_utils
setup_tools
cp -f $source/cryptsetup.sh $target/etc/pm/sleep.d/80-cryptsetup.sh # keep before 90-video
}
target_delete() {
echo "delete chroot environment"
[[ $target == /run/* ]] && mount -o remount,noexec /run
#rm -r -f $target
}
setup_progs() {
echo "copy programs into chroot environment"
local list
list="busybox cryptsetup dmsetup bash openvt" # crypto tools
#list="$list udevadm /lib/systemd/systemd-udevd" # crypto extra
list="$list pm-suspend bash wpa_cli flock fgconsole start stop" # pm-utils dependency
. /usr/share/initramfs-tools/hook-functions # load copy_exec
DESTDIR=$target ; verbose="n" # copy_exec params
for name in $list; do
exec=$(which $name)
copy_exec $exec
done
}
setup_utils() {
echo "copy scripts into chroot environment"
local list
list="/etc/pm /usr/lib/pm-utils" # pm-utils core
list="$list /lib/hdparm" # pm-utils dependency
for path in $list; do
folder=$target/$path
mkdir -p $folder
cp -r -f $path/* $folder
done
# patch pm-utils
cmd_suspend=$target/usr/sbin/pm-suspend
sed -i 's/^[[:space:]]*sync[[:space:]]*/#&### managed by cryptsetup ###/' $cmd_suspend
mkdir -p $target/var/log
}
setup_tools() {
echo "configure shell tools in chroot environment"
for tool in $(busybox --list-full); do
ln -s -f /bin/busybox $target/$tool
done
}
do_mount() {
echo "special system mount"
for path in $bind_list; do
folder=${target}${path}
echo "mount $folder"
mkdir -p $folder
mount -o bind $path $folder
done
}
do_umount() {
echo "special system un-mount"
for path in $(echo " $bind_list " | tac -s ' ' ); do
folder=${target}${path}
echo "umount $folder"
umount $folder
done
}
do_chroot() {
echo "invoke suspend in chroot environment"
chroot $target /usr/sbin/pm-suspend
}
do_process() {
do_mount
do_chroot
do_umount
}
target_create
do_process
target_delete
#! /bin/bash
#
# ubuntu 14.04 cryptsetup luks suspend/resume root partition sleep cryptsetup
#
# target location: /etc/pm/sleep.d/80-cryptsetup.sh
# hook must be run at order 80, at least before 90-video
# http://manpages.ubuntu.com/manpages/trusty/man8/pm-action.8.html
SLEEP=3 # convinience delay for debugging
# list of crypto mapper device names
luks_list() {
local list=$(dmsetup ls --target crypt | awk '{print $1}')
if [ "$list" == "No" ] ; then # match "No devices found"
echo ""
else
echo $list
fi
}
# flat line list of crypto mapper device names
luks_line() {
luks_list | tr '\\n' ','
}
# read password from current console
read_pass() { # note: need bash
local char=""
local star=""
local pass=""
local size=0
while IFS='' read -p "$star" -r -s -n 1 char ; do
if [[ $char == $'\0' ]] ; then
break
fi
if [[ $char == $'\177' ]] ; then
if [ $size -gt 0 ] ; then
size=$((size-1))
star=$'\b \b'
pass="${pass%?}"
else
star=""
fi
else
size=$((size+1))
star='*'
pass+="$char"
fi
done
echo "$pass"
}
# suspend all present crypto devices
do_suspend() {
local list=$(luks_list)
if [ "$list" == "" ]; then
echo "Suspend: no crypto devices"
else
echo "Suspend: [$(luks_line)]"
sync # note: ensure pm-utils are not using sync
for name in $list; do
echo "Suspend: $name"
cryptsetup luksSuspend $name
done
echo "Suspend complete."
fi
local word=""
read -t $SLEEP -p ">" word
if [ "$word" == "bash" ] ; then
bash -i # manual error handling
fi
}
# resume all present crypto devices
do_resume() {
local list=$(luks_list)
if [ "$list" == "" ]; then
echo "Resume: no crypto devices"
else
echo "Resume: [$(luks_line)]"
echo -n ">"
local pass=$(read_pass) # assume shared pass for all devices
echo ""
for name in $list; do
echo "Resume: $name"
printf "$pass" | cryptsetup luksResume $name || {
echo "Resume failure: cryptsetup luksResume $name"
bash -i # manual error handling
}
done
echo "Resume complete."
fi
sleep $SLEEP
}
# recurse script again in a terminal
do_terminal() {
self="$0"
mode="$1"
openvt -s -w -- "$self" "$mode"
exit 0
}
# pm-utils entry point
case $1 in
suspend)
echo "Crypto device list: [$(luks_line)]"
do_terminal terminal-suspend
;;
resume)
echo "Crypto device list: [$(luks_line)]"
do_terminal terminal-resume
;;
terminal-suspend)
# now running on terminal
do_suspend
;;
terminal-resume)
# now running on terminal
do_resume
;;
*)
echo "Crypto error: $1"
exit $NA
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment