Skip to content

Commit a80d441

Browse files
committed
initrd: normalize root filesystem boot paths
Signed-off-by: Sean Rhodes <sean@starlabs.systems>
1 parent 3a1f044 commit a80d441

2 files changed

Lines changed: 73 additions & 5 deletions

File tree

initrd/bin/kexec-parse-boot.sh

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,28 @@ fix_path() {
6868
# GRUB kernel lines (linux/multiboot) can include a command line. Check whether
6969
# the file path exists in $bootdir.
7070
check_path() {
71-
local checkpath firstval
71+
local checkpath firstval relative relative_firstval
7272
checkpath="$1"
7373
firstval="$(echo "$checkpath" | cut -d\ -f1)"
74-
if ! [ -r "$bootdir$firstval" ]; then
75-
DEBUG "parse-boot: check_path $bootdir$firstval not found"
76-
return 1
74+
if [ -r "$bootdir$firstval" ]; then
75+
return 0
7776
fi
78-
return 0
77+
78+
# A GRUB configuration on a root filesystem can use /boot-prefixed
79+
# paths even though that directory is exposed directly at $bootdir.
80+
case "$firstval" in
81+
/boot/*)
82+
relative="${checkpath#/boot}"
83+
relative_firstval="$(echo "$relative" | cut -d\ -f1)"
84+
if [ -r "$bootdir$relative_firstval" ]; then
85+
path="$relative"
86+
return 0
87+
fi
88+
;;
89+
esac
90+
91+
DEBUG "parse-boot: check_path $bootdir$firstval not found"
92+
return 1
7993
}
8094

8195
echo_entry() {
@@ -160,6 +174,7 @@ grub_entry() {
160174
--nounzip*) val=$(echo $val | cut -d\ -f2-) ;;
161175
esac
162176
fix_path $val
177+
check_path "$path" 2>/dev/null || :
163178
modules="$modules|module $path"
164179
;;
165180
linux*)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
set -euo pipefail
5+
6+
repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
7+
tmpdir=$(mktemp -d)
8+
trap 'rm -rf "$tmpdir"' EXIT
9+
10+
mkdir -p "$tmpdir/boot/grub"
11+
touch "$tmpdir/boot/vmlinuz" "$tmpdir/boot/initrd" \
12+
"$tmpdir/boot/xen.gz" "$tmpdir/boot/dom0-vmlinuz" \
13+
"$tmpdir/boot/dom0-initrd"
14+
15+
printf '%s\n' \
16+
'menuentry "root boot" {' \
17+
' linux /boot/vmlinuz root=/dev/test' \
18+
' initrd /boot/initrd' \
19+
'}' \
20+
'menuentry "root xen" {' \
21+
' multiboot /boot/xen.gz placeholder' \
22+
' module /boot/dom0-vmlinuz root=/dev/test' \
23+
' module --nounzip /boot/dom0-initrd' \
24+
'}' >"$tmpdir/boot/grub/grub.cfg"
25+
26+
printf '%s\n' \
27+
'DEBUG() { :; }' \
28+
'DIE() { echo "$*" >&2; exit 1; }' >"$tmpdir/functions.sh"
29+
30+
sed "s|^\. /etc/functions.sh$|. $tmpdir/functions.sh|" \
31+
"$repo_root/initrd/bin/kexec-parse-boot.sh" >"$tmpdir/kexec-parse-boot.sh"
32+
chmod +x "$tmpdir/kexec-parse-boot.sh"
33+
34+
entry=$("$tmpdir/kexec-parse-boot.sh" "$tmpdir/boot" \
35+
"$tmpdir/boot/grub/grub.cfg")
36+
37+
case "$entry" in
38+
*'|kernel /vmlinuz|initrd /initrd|append root=/dev/test'*) ;;
39+
*)
40+
echo "Unexpected parsed entry: $entry" >&2
41+
exit 1
42+
;;
43+
esac
44+
45+
case "$entry" in
46+
*'|kernel /xen.gz placeholder|module /dom0-vmlinuz root=/dev/test|module /dom0-initrd'*) ;;
47+
*)
48+
echo "Unexpected parsed Xen entry: $entry" >&2
49+
exit 1
50+
;;
51+
esac
52+
53+
echo "Root-filesystem /boot path tests passed"

0 commit comments

Comments
 (0)