Skip to content

Commit b175948

Browse files
committed
root-hashes-gui.sh: generalize to work on debian/ubuntu/pureos/qubesos (luks+lvm; qubesos untested: I use btrfs)
TODO: tpm prompt for password is silenced still, and UX not so good to guide user to reseal/reset tpm/primary handle... Signed-off-by: Thierry Laurion <insurgo@riseup.net>
1 parent 16a083e commit b175948

3 files changed

Lines changed: 100 additions & 41 deletions

File tree

initrd/bin/root-hashes-gui.sh

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ ROOT_MOUNT="/root"
1313
export CONFIG_ROOT_DIRLIST_PRETTY=$(echo $CONFIG_ROOT_DIRLIST | sed -e 's/^/\//;s/ / \//g')
1414

1515
update_root_checksums() {
16+
TRACE_FUNC
1617
if ! detect_root_device; then
1718
whiptail_error --title 'ERROR: No Valid Root Disk Found' \
1819
--msgbox "No Valid Root Disk Found" 0 80
@@ -31,6 +32,7 @@ update_root_checksums() {
3132
mount -o rw,remount /boot
3233
fi
3334

35+
DEBUG "calculating hashes for $CONFIG_ROOT_DIRLIST_PRETTY on $ROOT_MOUNT"
3436
echo "+++ Calculating hashes for all files in $CONFIG_ROOT_DIRLIST_PRETTY "
3537
# Intentional wordsplit
3638
# shellcheck disable=SC2086
@@ -47,6 +49,8 @@ update_root_checksums() {
4749
unmount_root_device
4850
}
4951
check_root_checksums() {
52+
TRACE_FUNC
53+
DEBUG "verifying existing hash file for $CONFIG_ROOT_DIRLIST_PRETTY"
5054
if ! detect_root_device; then
5155
whiptail_error --title 'ERROR: No Valid Root Disk Found' \
5256
--msgbox "No Valid Root Disk Found" 0 80
@@ -74,6 +78,7 @@ check_root_checksums() {
7478
update_root_checksums
7579
return 0
7680
else
81+
DEBUG "user chose not to create root hash file, returning"
7782
exit 1
7883
fi
7984
fi
@@ -124,6 +129,7 @@ check_root_checksums() {
124129

125130
return 0
126131
else
132+
DEBUG "user chose not to update signatures after new-files warning"
127133
return 1
128134
fi
129135
fi
@@ -154,6 +160,7 @@ check_root_checksums() {
154160
update_root_checksums
155161
return 0
156162
else
163+
DEBUG "user chose not to update signatures after hash-check-failure"
157164
return 1
158165
fi
159166
fi
@@ -164,21 +171,43 @@ check_root_checksums() {
164171
open_block_device_lvm() {
165172
TRACE_FUNC
166173
local VG="$1"
174+
local LV MAPPER_VG MAPPER_LV name lvpath
167175

168176
if ! lvm vgchange -ay "$VG"; then
169177
DEBUG "Can't open LVM VG: $VG"
170178
return 1
171179
fi
172180

173-
# Use the LV 'root'. This is the default name used by Qubes. There's no
174-
# way to configure this at the moment.
175-
if ! [ -e "/dev/mapper/$VG-root" ]; then
176-
DEBUG "LVM volume group does not have 'root' logical volume"
181+
# Prefer an LV named 'root' (used by Qubes), but fall back to any LV
182+
# in the VG. This ensures Ubuntu-style names (e.g. ubuntu-vg/ubuntu-root)
183+
# also work.
184+
LV="/dev/$VG/root"
185+
if ! [ -e "$LV" ]; then
186+
MAPPER_VG="${VG//-/--}"
187+
LV="/dev/mapper/${MAPPER_VG}-root"
188+
fi
189+
if ! [ -e "$LV" ]; then
190+
DEBUG "LVM VG $VG has no 'root' LV, enumerating all LVs"
191+
# list LV names and try each one
192+
for name in $(lvm lvs --noheadings -o lv_name --separator ' ' "$VG" 2>/dev/null); do
193+
lvpath="/dev/$VG/$name"
194+
if ! [ -e "$lvpath" ]; then
195+
MAPPER_LV="${name//-/--}"
196+
lvpath="/dev/mapper/${VG//-/--}-${MAPPER_LV}"
197+
fi
198+
if [ -e "$lvpath" ]; then
199+
DEBUG "trying LV $lvpath"
200+
LV="$lvpath"
201+
break
202+
fi
203+
done
204+
fi
205+
if ! [ -e "$LV" ]; then
206+
DEBUG "no usable LV found in VG $VG"
177207
return 1
178208
fi
179-
180-
# Use the root LV now
181-
open_block_device_layers "/dev/mapper/$VG-root"
209+
# Use selected LV
210+
open_block_device_layers "$LV"
182211
}
183212

184213
# Open a LUKS device, then continue looking for more layers.
@@ -269,12 +298,21 @@ open_root_device_no_clean_up() {
269298
close_block_device_lvm() {
270299
TRACE_FUNC
271300
local VG="$1"
301+
local name lvpath MAPPER_VG MAPPER_LV
272302

273-
# We always use the LV 'root' currently
274-
local LV="/dev/mapper/$VG-root"
275-
if [ -e "$LV" ]; then
276-
close_block_device_layers "$LV"
277-
fi
303+
MAPPER_VG="${VG//-/--}"
304+
305+
# Close any layers found in all LVs in this VG, not just 'root'.
306+
for name in $(lvm lvs --noheadings -o lv_name --separator ' ' "$VG" 2>/dev/null); do
307+
lvpath="/dev/$VG/$name"
308+
if ! [ -e "$lvpath" ]; then
309+
MAPPER_LV="${name//-/--}"
310+
lvpath="/dev/mapper/${MAPPER_VG}-${MAPPER_LV}"
311+
fi
312+
if [ -e "$lvpath" ]; then
313+
close_block_device_layers "$lvpath"
314+
fi
315+
done
278316

279317
# The LVM VG might be open even if no 'root' LV exists, still try to close it.
280318
lvm vgchange -an "$VG" || \
@@ -368,6 +406,7 @@ detect_root_device()
368406

369407
# generate list of possible boot devices
370408
fdisk -l 2>/dev/null | grep "Disk /dev/" | cut -f2 -d " " | cut -f1 -d ":" > /tmp/disklist
409+
DEBUG "detect_root_device: initial disklist=$(cat /tmp/disklist | tr '\n' ' ')"
371410

372411
# filter out extraneous options
373412
> /tmp_root_device_list

initrd/etc/functions

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,12 +1279,12 @@ find_lvm_vg_name() {
12791279
DEVICE="$1"
12801280

12811281
mkdir -p /tmp/root-hashes-gui
1282-
if ! lvm pvs "$DEVICE" >/tmp/root-hashes-gui/lvm_vg 2>/dev/null; then
1282+
if ! lvm pvs --noheadings -o vg_name "$DEVICE" >/tmp/root-hashes-gui/lvm_vg 2>/dev/null; then
12831283
# It's not an LVM PV
12841284
return 1
12851285
fi
12861286

1287-
VG="$(tail -n +2 /tmp/root-hashes-gui/lvm_vg | awk '{print $2}')"
1287+
VG="$(awk 'NF {print $1; exit}' /tmp/root-hashes-gui/lvm_vg)"
12881288
if [ -z "$VG" ]; then
12891289
DEBUG "Could not find LVM2 VG from lvm pvs output:"
12901290
DEBUG "$(cat /tmp/root-hashes-gui/lvm_vg)"
@@ -1298,34 +1298,37 @@ find_lvm_vg_name() {
12981298
# GPT-partitioned disk.
12991299
is_gpt_bios_grub() {
13001300
TRACE_FUNC
1301-
DEBUG "is_gpt_bios_grub: PART_DEV=$1"
1302-
1303-
local PART_DEV="$1" DEVICE NUMBER
1304-
1305-
# Figure out the partitioned device containing this device (if there is
1306-
# one) from /sys/class/block.
1307-
local DEVICE_MATCHES=("/sys/class/block/"*"/$(basename "$PART_DEV")")
1308-
DEBUG "is_gpt_bios_grub: DEVICE_MATCHES=${DEVICE_MATCHES[*]}"
1301+
# $1 is the device path being tested (e.g. /dev/vda1)
1302+
local PART_DEV="$1"
1303+
DEBUG "PART_DEV=$PART_DEV"
1304+
1305+
# identify the base device and partition number with a regex
1306+
local partname device number
1307+
partname=$(basename "$PART_DEV")
1308+
1309+
# Split trailing digits from the base device name.
1310+
number="${partname##*[!0-9]}"
1311+
if [ -z "$number" ]; then
1312+
DEBUG "cannot parse partition name '$partname'"
1313+
return 0 # not a recognised partition
1314+
fi
13091315

1310-
DEVICE="$(echo "${DEVICE_MATCHES[0]}" | cut -d/ -f5)"
1311-
if [ "${#DEVICE_MATCHES[@]}" -ne 1 ] || [ "$DEVICE" = "*" ]; then
1312-
DEBUG "is_gpt_bios_grub: ambiguous DEVICE, returning false"
1313-
return 0
1316+
device="${partname%"$number"}"
1317+
# nvme/mmc names include an extra 'p' separator before the partition
1318+
# number (e.g. nvme0n1p2, mmcblk0p1). Remove only that separator.
1319+
if [[ "$device" == *p && "${device%p}" == *[0-9] ]]; then
1320+
device="${device%p}"
13141321
fi
13151322

1316-
# Extract the partition number
1317-
if ! [[ $(basename "$PART_DEV") =~ ([0-9]+)$ ]]; then
1318-
DEBUG "is_gpt_bios_grub: cannot parse partition number"
1319-
return 0 # Can't figure out the partition number
1323+
if [ -z "$device" ]; then
1324+
DEBUG "cannot parse partition device from '$partname'"
1325+
return 0
13201326
fi
13211327

1322-
NUMBER="${BASH_REMATCH[1]}"
1323-
DEBUG "is_gpt_bios_grub: DEVICE=$DEVICE NUMBER=$NUMBER"
1328+
DEBUG "DEVICE=$device NUMBER=$number"
13241329

1325-
# Now we know the device and partition number, get the type. This is
1326-
# specific to GPT disks, MBR disks are shown differently by fdisk.
1327-
TRACE "$PART_DEV is partition $NUMBER of $DEVICE"
1328-
if [ "$(fdisk -l "/dev/$DEVICE" 2>/dev/null | awk '$1 == '"$NUMBER"' {print $5}')" == grub ]; then
1330+
# GPT disks list type in column 5; fall through to 1 otherwise
1331+
if [ "$(fdisk -l "/dev/$device" 2>/dev/null | awk '$1 == '"$number"' {print $5}')" == grub ]; then
13291332
return 0
13301333
fi
13311334
return 1
@@ -1354,9 +1357,17 @@ mount_possible_boot_device() {
13541357

13551358
# Skip bios-grub partitions on GPT disks, LUKS partitions, and LVM PVs,
13561359
# we can't mount these as /boot.
1357-
if is_gpt_bios_grub "$BOOT_DEV" || cryptsetup isLuks "$BOOT_DEV" ||
1358-
find_lvm_vg_name "$BOOT_DEV" >/dev/null; then
1359-
TRACE "$BOOT_DEV is not a mountable partition for /boot"
1360+
# Skip partitions we definitely can't mount for /boot. Log each reason.
1361+
if is_gpt_bios_grub "$BOOT_DEV"; then
1362+
DEBUG "$BOOT_DEV is GPT BIOS/GRUB partition, skipping"
1363+
return 1
1364+
fi
1365+
if cryptsetup isLuks "$BOOT_DEV"; then
1366+
DEBUG "$BOOT_DEV is a LUKS volume, skipping"
1367+
return 1
1368+
fi
1369+
if find_lvm_vg_name "$BOOT_DEV" >/dev/null; then
1370+
DEBUG "$BOOT_DEV is an LVM PV, skipping"
13601371
return 1
13611372
fi
13621373

@@ -1388,6 +1399,15 @@ mount_possible_boot_device() {
13881399
detect_boot_device() {
13891400
TRACE_FUNC
13901401
local devname
1402+
DEBUG "CONFIG_BOOT_DEV=$CONFIG_BOOT_DEV"
1403+
# If /boot is already mounted and appears to be a valid boot tree, just
1404+
# use its device. This avoids remount churn and makes the later lookup
1405+
# fast.
1406+
mounted_boot_dev="$(awk '$2=="/boot" {print $1; exit}' /proc/mounts)"
1407+
if [ -n "$mounted_boot_dev" ] && ls -d /boot/grub* >/dev/null 2>&1; then
1408+
CONFIG_BOOT_DEV="$mounted_boot_dev"
1409+
return 0
1410+
fi
13911411
# unmount /boot to be safe
13921412
cd / && umount /boot 2>/dev/null
13931413

@@ -1425,6 +1445,7 @@ detect_boot_device() {
14251445

14261446
# no valid boot device found
14271447
echo "Unable to locate /boot files on any mounted disk"
1448+
DEBUG "detect_boot_device: failed to find a bootable device"
14281449
return 1
14291450
}
14301451

initrd/etc/gui_functions

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,7 @@ show_system_info() {
183183
EC_VER: ${EC_VER}"
184184

185185
local disk_info="$(disk_info_sysfs)"
186-
TRACE_FUNC
187-
DEBUG "show_system_info: disk_info=\n${disk_info}"
186+
DEBUG "disk_info=\n${disk_info}"
188187

189188
local msgbox="${BOARD_NAME}
190189

0 commit comments

Comments
 (0)