From 1b35b9fabbbd02d6e34e7dce7eb30d58efdcccf3 Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Wed, 17 Apr 2024 15:48:19 -0400 Subject: [PATCH] Add a bunch of TRACE_FUNC and make sure DEBUG calls can inject their output to kmesg DEBUG function modified to split on last space before reaching safe max 960 characters This max characters lenght to be passed to kmesg was roughtly determined by PREFIX_MAX taken into consideration for LOG_LINE_MAX of printk of oldest 5.5.x kernel we need to respect: grep: build/ppc64/linux-5.5/linux-talos-2/source: warning: recursive directory loop build/ppc64/linux-5.5/kernel/printk/printk.c:446:#define PREFIX_MAX 48 build/ppc64/linux-5.5/kernel/printk/printk.c:448:#define PREFIX_MAX 32 build/ppc64/linux-5.5/kernel/printk/printk.c:450:#define LOG_LINE_MAX (1024 - PREFIX_MAX) build/ppc64/linux-5.5/kernel/printk/printk.c:1315: char prefix[PREFIX_MAX]; build/ppc64/linux-5.5/kernel/printk/printk.c:1356: text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); build/ppc64/linux-5.5/kernel/printk/printk.c:1386: LOG_LINE_MAX + PREFIX_MAX); build/ppc64/linux-5.5/kernel/printk/printk.c:1428: text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); build/ppc64/linux-5.5/kernel/printk/printk.c:1466: LOG_LINE_MAX + PREFIX_MAX); build/ppc64/linux-5.5/kernel/printk/printk.c:2066:#define PREFIX_MAX 0 build/ppc64/linux-5.5/kernel/printk/printk.c:2370: static char text[LOG_LINE_MAX + PREFIX_MAX]; build/ppc64/linux-5.5/include/uapi/linux/rtnetlink.h:552: __PREFIX_MAX build/ppc64/linux-5.5/include/uapi/linux/rtnetlink.h:555:#define PREFIX_MAX (__PREFIX_MAX - 1) build/ppc64/linux-5.5/linux-5.5/linux-talos-2/usr/include/linux/rtnetlink.h:552: __PREFIX_MAX build/ppc64/linux-5.5/linux-5.5/linux-talos-2/usr/include/linux/rtnetlink.h:555:#define PREFIX_MAX (__PREFIX_MAX - 1) Each DEBUG call also adds "DEBUG: " leaving us to a safe 960 char limit to respect and wrap around. Otherwise, calling DEBUG fails from scripts setting "set -e -o pipefail" Signed-off-by: Thierry Laurion --- initrd/bin/kexec-insert-key | 4 ++++ initrd/bin/kexec-unseal-key | 1 - initrd/etc/ash_functions | 6 ++++-- initrd/etc/functions | 9 +++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/initrd/bin/kexec-insert-key b/initrd/bin/kexec-insert-key index f06c54833..ba2fecae8 100755 --- a/initrd/bin/kexec-insert-key +++ b/initrd/bin/kexec-insert-key @@ -29,6 +29,7 @@ if [ -r "$TMP_KEY_LVM" ]; then fi # Measure the LUKS headers before we unseal the disk key +TRACE_FUNC cat "$TMP_KEY_DEVICES" | cut -d\ -f1 | xargs /bin/qubes-measure-luks || die "LUKS measure failed" @@ -43,6 +44,7 @@ mkdir -p "$INITRD_DIR/etc" # Attempt to unseal the disk key from the TPM # should we give this some number of tries? unseal_failed="n" +TRACE_FUNC if ! kexec-unseal-key "$INITRD_DIR/secret.key"; then unseal_failed="y" echo @@ -51,6 +53,7 @@ fi # Override PCR 4 so that user can't read the key DEBUG "Extending TPM PCR 4 to prevent further secret unsealing" +TRACE_FUNC tpmr extend -ix 4 -ic generic || die 'Unable to scramble PCR' @@ -70,6 +73,7 @@ if [ "$unseal_failed" = "y" ]; then fi fi +TRACE_FUNC echo echo '+++ Building initrd' # pad the initramfs (dracut doesn't pad the last gz blob) diff --git a/initrd/bin/kexec-unseal-key b/initrd/bin/kexec-unseal-key index 3f18c4358..3a39ed1d3 100755 --- a/initrd/bin/kexec-unseal-key +++ b/initrd/bin/kexec-unseal-key @@ -3,7 +3,6 @@ # The TOTP secret will be shown to the user on each encryption attempt. # It will then need to be bundled into initrd that is booted with Qubes. set -e -o pipefail -. /etc/functions TPM_INDEX=3 TPM_SIZE=312 diff --git a/initrd/etc/ash_functions b/initrd/etc/ash_functions index ba7baa591..32ef223a4 100644 --- a/initrd/etc/ash_functions +++ b/initrd/etc/ash_functions @@ -23,13 +23,15 @@ warn() { } DEBUG() { - if [ "$CONFIG_DEBUG_OUTPUT" = "y" ];then - echo "DEBUG: $*" | while read line; do + if [ "$CONFIG_DEBUG_OUTPUT" = "y" ]; then + # fold -s -w 960 will wrap lines at 960 characters on the last space before the limit + echo "DEBUG: $*" | fold -s -w 960 | while read line; do echo "$line" | tee -a /tmp/debug.log /dev/kmsg >/dev/null done fi } + TRACE() { if [ "$CONFIG_ENABLE_FUNCTION_TRACING_OUTPUT" = "y" ];then echo "TRACE: $*" | tee -a /tmp/debug.log /dev/kmsg > /dev/null; diff --git a/initrd/etc/functions b/initrd/etc/functions index f5df01695..df1f1d39e 100755 --- a/initrd/etc/functions +++ b/initrd/etc/functions @@ -695,12 +695,14 @@ scan_boot_options() { } calc() { + TRACE_FUNC awk "BEGIN { print "$*" }" } # truncate a file to a size only if it is longer (busybox truncate lacks '<' and # always sets the file size) truncate_max_bytes() { + TRACE_FUNC local bytes="$1" local file="$2" if [ "$(stat -c %s "$file")" -gt "$bytes" ]; then @@ -712,6 +714,7 @@ truncate_max_bytes() { # trips up many scripts, it's very difficult to diagnose by looking at the # output. Delete line breaks and spaces to really get plain hex output. tohex_plain() { + TRACE_FUNC xxd -p | tr -d '\n ' } @@ -721,10 +724,12 @@ tohex_plain() { # Note that also unlike GNU xxd, non-hex chars in input corrupt the output (GNU # xxd ignores them). fromhex_plain() { + TRACE_FUNC fold -w 60 | xxd -p -r } print_battery_health() { + TRACE_FUNC if [ -d /sys/class/power_supply/BAT* ]; then battery_health=$(calc $(cat /sys/class/power_supply/BAT*/charge_full)/$(cat /sys/class/power_supply/BAT*/charge_full_design)*100 | awk -F "." {'print $1'}) echo "$battery_health" @@ -732,6 +737,7 @@ print_battery_health() { } print_battery_charge() { + TRACE_FUNC if [ -d /sys/class/power_supply/BAT* ]; then battery_charge=$(calc $(cat /sys/class/power_supply/BAT*/charge_now)/$(cat /sys/class/power_supply/BAT*/charge_full)*100 | awk -F "." {'print $1'}) echo "$battery_charge" @@ -739,6 +745,7 @@ print_battery_charge() { } generate_random_mac_address() { + TRACE_FUNC #Borrowed from https://stackoverflow.com/questions/42660218/bash-generate-random-mac-address-unicast hexdump -n 6 -ve '1/1 "%.2x "' /dev/urandom | awk -v a="2,6,a,e" -v r="$RANDOM" 'BEGIN{srand(r);}NR==1{split(a,b,",");r=int(rand()*4+1);printf "%s%s:%s:%s:%s:%s:%s\n",substr($1,0,1),b[r],$2,$3,$4,$5,$6}' } @@ -750,6 +757,7 @@ generate_random_mac_address() { # (unlike trap). E.g.: # at_exit shred "$file" #<-- file is expanded when calling at_exit, no extra quoting needed at_exit() { + TRACE_FUNC AT_EXIT_HANDLERS+=("$@") # Command and args AT_EXIT_HANDLERS+=("$#") # Number of elements in this command } @@ -764,6 +772,7 @@ at_exit() { AT_EXIT_HANDLERS=() # Each handler is an array AT_EXIT_HANDLER_{i} run_at_exit_handlers() { + TRACE_FUNC local cmd_pos cmd_len cmd_pos="${#AT_EXIT_HANDLERS[@]}" # Silence trace if there are no handlers, this is common and occurs a lot