From 698360199c9aa75f109c31814010d8bfb8abf019 Mon Sep 17 00:00:00 2001 From: Jonathon Hall Date: Thu, 10 Nov 2022 10:13:38 -0500 Subject: [PATCH] kexec-parse-boot: Ensure kernel/initrd paths exist in boot option If a boot option doesn't refer to a valid file for the kernel/initrd, ignore it. Such an option is never bootable, because we would fail to find the kernel/initrd. This could happen if the path contained GRUB variables, or specified a device that wasn't /boot, etc. This is checked before expanding GRUB variables. It's unlikely that any kernel/initrd path containing variables would end up working when all variables expand to nothing (since we do not handle GRUB variables). Signed-off-by: Jonathon Hall --- initrd/bin/kexec-parse-boot | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/initrd/bin/kexec-parse-boot b/initrd/bin/kexec-parse-boot index b3dc6c0c..0aacd07e 100755 --- a/initrd/bin/kexec-parse-boot +++ b/initrd/bin/kexec-parse-boot @@ -28,15 +28,31 @@ fix_path() { fi } +# GRUB kernel lines (linux/multiboot) can include a command line. Check whether +# the file path exists in $bootdir. +check_path() { + local checkpath firstval + checkpath="$1" + firstval="$(echo "$checkpath" | cut -d\ -f1)" + if ! [ -r "$bootdir$firstval" ]; then return 1; fi + return 0 +} + echo_entry() { if [ "$kexectype" = "elf" ]; then if [ -z "$kernel" ]; then return; fi fix_path $kernel + # The kernel must exist - if it doesn't, ignore this entry, it + # wouldn't work anyway. This could happen if there was a + # GRUB variable in the kernel path, etc. + if ! check_path "$path"; then return; fi entry="$name|$kexectype|kernel $path" if [ -n "$initrd" ]; then for init in $(echo $initrd | tr ',' ' '); do fix_path $init + # The initrd must also exist + if ! check_path "$path"; then return; fi entry="$entry|initrd $path" done fi @@ -44,12 +60,18 @@ echo_entry() { entry="$entry|append $append" fi + # Double-expand here in case there are variables in the kernel + # parameters - some configs do this and can boot with empty + # expansions (Debian Live ISOs use this for loopback boots) echo $(eval "echo \"$entry\"") fi if [ "$kexectype" = "multiboot" -o "$kexectype" = "xen" ]; then if [ -z "$kernel" ]; then return; fi fix_path $kernel + # The kernel must exist + if ! check_path "$path"; then return; fi + # Double-expand to clear variable expansions echo $(eval "echo \"$name|$kexectype|kernel $path$modules\"") fi }