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 ### Commandline argumentop
- `systemd.volatile=overlay` controls the switch between Protected Mode (when present) and Maintenance Mode (when omitted) - `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 - `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 - Displayed volume limit does **NOT** provide plausible deniability or actual device inspection

View file

@ -37,12 +37,7 @@ install() {
inst /etc/reliant.conf inst /etc/reliant.conf
# Other binaries # Other binaries
inst_multiple dmesg lsblk blockdev mount dd wc sed sort sleep md5sum find modprobe cut grep mkdir rm rmdir tail inst_multiple dmesg e2fsck lsblk blockdev mount dd wc sed sort sleep md5sum find findmnt 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
return 0 return 0
} }

View file

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

View file

@ -172,9 +172,6 @@ systemctl enable shufflecake-close.service
# reliant-system/tools # reliant-system/tools
surgeon-dissect -t varlibqubes surgeon-dissect -t varlibqubes
reliant-snapshot-rw reliant-snapshot-rw
if [ "$RELIANT_PROFILING" = "true" ]; then
reliant-profiling-patch-systemd
fi
# reliant-system/qubes-sflc # reliant-system/qubes-sflc
depmod -a "$RELIANT_KERNEL_VERSION" depmod -a "$RELIANT_KERNEL_VERSION"
@ -182,7 +179,23 @@ depmod -a "$RELIANT_KERNEL_VERSION"
# reliant-system/dracut # reliant-system/dracut
dracut --force --regenerate-all dracut --force --regenerate-all
if [ "$RELIANT_PROFILING" = "true" ]; then 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 fi
# Report successful installation # Report successful installation

View file

@ -71,8 +71,12 @@ fi
# Create the volume root directory under /run # Create the volume root directory under /run
mkdir -m 750 /run/shufflecake mkdir -m 750 /run/shufflecake
# Check if we need to e2fsck # Check if e2fsck has been enabled
reliant_e2fsck=$(grep -q reliant.e2fsck /proc/cmdline) if grep -q reliant.e2fsck /proc/cmdline; then
reliant_e2fsck=$RELIANT_TRUE
else
reliant_e2fsck=$RELIANT_FALSE
fi
# Mount each volume # Mount each volume
find /dev/mapper -maxdepth 1 -name 'sflc_0_*' | sort | while read -r device; do 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##*/}" name="${device##*/}"
mountpoint="/run/shufflecake/$name" 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 # Mount in /run/shufflecake
mkdir -m 750 "$mountpoint" 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 # Apply the displayed volume limit if required
if [ $dvl_required -eq $RELIANT_TRUE ] && [ "$device" = "$dvl_device" ]; then if [ $dvl_required -eq $RELIANT_TRUE ] && [ "$device" = "$dvl_device" ]; then

View file

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

View file

@ -1,34 +1,54 @@
#!/usr/bin/bash #!/usr/bin/bash
#TODO: check status, report if other volumes are already unsealed
set -euo pipefail set -euo pipefail
RED="\e[31;1m" RED="\e[31;1m"
GREEN="\e[32;1m" GREEN="\e[32;1m"
ENDCOLOR="\e[0m" ENDCOLOR="\e[0m"
# Checks
if [ "$#" -lt 1 ]; then if [ "$#" -lt 1 ]; then
echo "Expected at least 1 argument." echo "Expected at least 1 argument."
exit 1 exit 1
fi fi
if [ "$EUID" -ne 0 ]; then if [ "$EUID" -ne 0 ]; then
echo "Must be superuser." echo "Must be superuser."
exit 1 exit 1
fi fi
if [ ! -d /run/shufflecake ]; then if [ ! -d /run/shufflecake ]; then
echo "Running in unsafe/maintenance mode, reliant-unseal not available." echo "Running in unsafe/maintenance mode, reliant-unseal not available."
exit 1 exit 1
fi fi
# Target volume
name=$1 name=$1
device="/dev/mapper/$name" 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... " echo -n "Unsealing device... "
blockdev --setrw "$device" blockdev --setrw "$device"
echo "Done." 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... " 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." echo "Done."
# Check if we were given a qube list # Check if we were given a qube list
@ -39,6 +59,7 @@ else
allowed_only=1 allowed_only=1
fi fi
# Load the app menu shortcuts, firewall rules, etc.
echo "Creating links... " echo "Creating links... "
for appvm in "/run/shufflecake/$name/appvms/"*; do for appvm in "/run/shufflecake/$name/appvms/"*; do
qube="${appvm##*/}" qube="${appvm##*/}"