idempotent seal-unseal; e2fsck works as intended; profiling patch applied reliably

This commit is contained in:
Anderson Rosenberg 2025-10-23 14:20:05 -04:00
parent 82229709b6
commit 2f46219400
No known key found for this signature in database
GPG key ID: 7ACF448C0590AB9C
7 changed files with 66 additions and 33 deletions

View file

@ -97,7 +97,7 @@ Due to potential security implications of arbitrary code execution (firewall.rul
### Commandline argumentop
- `systemd.volatile=overlay` controls the switch between Protected Mode (when present) and Maintenance Mode (when omitted)
- `reliant.e2fsck` runs `e2fsck -p` on every volume before mount to avoid needing an extra reboot in case of accidental data corruption
- `reliant.e2fsck` attempts to run `e2fsck -p` on volumes in case mount fails
- `reliant.dvl=VOLUME_ID` limits the amount of volumes displayed in Qubes app menu, manager, and other places, useful for when you want to avoid showing your hidden qubes in public
- Displayed volume limit does **NOT** provide plausible deniability or actual device inspection

View file

@ -37,12 +37,7 @@ install() {
inst /etc/reliant.conf
# Other binaries
inst_multiple dmesg lsblk blockdev mount dd wc sed sort sleep md5sum find modprobe cut grep mkdir rm rmdir tail
# Optional profiling
if [ "$RELIANT_PROFILING" = "true" ]; then
inst /usr/lib/systemd/systemd-volatile-root.reliant-profiling /usr/lib/systemd/systemd-volatile-root
fi
inst_multiple dmesg e2fsck lsblk blockdev mount dd wc sed sort sleep md5sum find findmnt modprobe cut grep mkdir rm rmdir tail
return 0
}

View file

@ -115,7 +115,7 @@ main() {
# Seal all volumes
for path in '/run/shufflecake/'*; do
name="${path##*/}"
reliant-seal "$name"
reliant-seal "$name" &>/dev/null
done
}

View file

@ -172,9 +172,6 @@ systemctl enable shufflecake-close.service
# reliant-system/tools
surgeon-dissect -t varlibqubes
reliant-snapshot-rw
if [ "$RELIANT_PROFILING" = "true" ]; then
reliant-profiling-patch-systemd
fi
# reliant-system/qubes-sflc
depmod -a "$RELIANT_KERNEL_VERSION"
@ -182,7 +179,23 @@ depmod -a "$RELIANT_KERNEL_VERSION"
# reliant-system/dracut
dracut --force --regenerate-all
if [ "$RELIANT_PROFILING" = "true" ]; then
RELIANT_PROFILING=true dracut --force "/boot/initramfs-$RELIANT_KERNEL_VERSION.reliant-profiling.img"
# Perform the patch
reliant-profiling-patch-systemd
old=/usr/lib/systemd/systemd-volatile-root
new=/usr/lib/systemd/systemd-volatile-root.reliant-profiling
# Switch
tmpname="/tmp/reliant.$(uuidgen)"
mv "$old" "$tmpname"
mv "$new" "$old"
# Build
dracut --force "/boot/initramfs-$RELIANT_KERNEL_VERSION.reliant-profiling.img"
# Switch back
rm "$old"
mv "$tmpname" "$old"
rm "$tmpname"
fi
# Report successful installation

View file

@ -71,8 +71,12 @@ fi
# Create the volume root directory under /run
mkdir -m 750 /run/shufflecake
# Check if we need to e2fsck
reliant_e2fsck=$(grep -q reliant.e2fsck /proc/cmdline)
# Check if e2fsck has been enabled
if grep -q reliant.e2fsck /proc/cmdline; then
reliant_e2fsck=$RELIANT_TRUE
else
reliant_e2fsck=$RELIANT_FALSE
fi
# Mount each volume
find /dev/mapper -maxdepth 1 -name 'sflc_0_*' | sort | while read -r device; do
@ -83,14 +87,13 @@ find /dev/mapper -maxdepth 1 -name 'sflc_0_*' | sort | while read -r device; do
name="${device##*/}"
mountpoint="/run/shufflecake/$name"
# e2fsck if requested
if [ "$reliant_e2fsck" ]; then
e2fsck -p "$device" &> /dev/null || true # If the user has mixed filesystems, it will fail for some
fi
# Mount in /run/shufflecake
mkdir -m 750 "$mountpoint"
mount -o ro,noatime,nodiratime "$device" "$mountpoint" &> /dev/null || true # Allow it to silently fail in case there's no filesystem or it is corrupted
if ! mount -o ro,noatime,nodiratime "$device" "$mountpoint" &>/dev/null && [ $reliant_e2fsck -eq $RELIANT_TRUE ]; then
# If e2fsck is enabled, we get a second chance
e2fsck -p "$device" &>/dev/null || true
mount -o ro,noatime,nodiratime "$device" "$mountpoint" &>/dev/null || true
fi
# Apply the displayed volume limit if required
if [ $dvl_required -eq $RELIANT_TRUE ] && [ "$device" = "$dvl_device" ]; then

View file

@ -4,23 +4,24 @@ RED="\e[31;1m"
GREEN="\e[32;1m"
ENDCOLOR="\e[0m"
# Checks
if [ "$#" -ne 1 ]; then
echo "Expected 1 argument."
exit 1
fi
if [ "$EUID" -ne 0 ]; then
echo "Must be superuser."
exit 1
fi
if [ ! -d /run/shufflecake ]; then
echo "Running in unsafe/maintenance mode, reliant-seal not available."
exit 1
fi
# Target volume
name=$1
# Shutdown qubes and remove links in /var/lib/qubes
echo -n "Destroying links... "
for appvm in "/run/shufflecake/$name/appvms/"*; do
qube="${appvm##*/}"
@ -37,16 +38,16 @@ for appvm in "/run/shufflecake/$name/appvms/"*; do
done
echo "Done."
echo -n "Sealing mountpoint... "
mount -o remount,ro,noatime,nodiratime "/run/shufflecake/$name"
echo "Done."
# Idempotent unmount
if findmnt "/run/shufflecake/$name" &> /dev/null; then
echo -n "Sealing mountpoint... "
mount -o remount,ro,noatime,nodiratime "/run/shufflecake/$name"
umount "/run/shufflecake/$name" && rmdir "/run/shufflecake/$name"
echo "Done."
fi
echo -n "Sealing device... "
blockdev --setro "/dev/mapper/$name"
echo "Done."
echo -n "Unmounting device... "
umount "/run/shufflecake/$name" && rmdir "/run/shufflecake/$name"
echo "Done."
echo -e "${GREEN}Sealed.${ENDCOLOR} See reliant-status for more information."

View file

@ -1,34 +1,54 @@
#!/usr/bin/bash
#TODO: check status, report if other volumes are already unsealed
set -euo pipefail
RED="\e[31;1m"
GREEN="\e[32;1m"
ENDCOLOR="\e[0m"
# Checks
if [ "$#" -lt 1 ]; then
echo "Expected at least 1 argument."
exit 1
fi
if [ "$EUID" -ne 0 ]; then
echo "Must be superuser."
exit 1
fi
if [ ! -d /run/shufflecake ]; then
echo "Running in unsafe/maintenance mode, reliant-unseal not available."
exit 1
fi
# Target volume
name=$1
device="/dev/mapper/$name"
# Future proposal for RELIANT_PARANOID
# Check if other volumes are unsealed
# unsealed_present=0
# for current_device in /dev/mapper/sflc_0_*; do
# if [ "$current_device" != "$device" ] && [ "$(blockdev --getro "$current_device")" -eq 0 ]; then
# unsealed_present=1
# fi
#done
#if [ $unsealed_present -eq 1 ]; then
# read -r -p "[WARN]: Other volumes are already unsealed. Proceed? [Y/N]: "
# if [[ ! $REPLY =~ ^[Yy] ]]; then
# echo "Aborted."
# exit 0
# fi
#fi
echo -n "Unsealing device... "
blockdev --setrw "$device"
echo "Done."
# Idempotent mount
mount_options="rw,noatime,nodiratime"
if findmnt "/run/shufflecake/$name" &> /dev/null; then
mount_options="remount,$mount_options"
fi
echo -n "Unsealing mountpoint... "
mount -o rw,noatime,nodiratime --mkdir=0750 "$device" "/run/shufflecake/$name"
mount -o "$mount_options" --mkdir=0750 "$device" "/run/shufflecake/$name"
echo "Done."
# Check if we were given a qube list
@ -39,6 +59,7 @@ else
allowed_only=1
fi
# Load the app menu shortcuts, firewall rules, etc.
echo "Creating links... "
for appvm in "/run/shufflecake/$name/appvms/"*; do
qube="${appvm##*/}"