From bc0835be6418282e3ddfe64605aef213bd4c39b3 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Mon, 12 Feb 2024 13:55:20 +0100 Subject: [PATCH 1/2] fix(dracut-util): do not call `strcmp` if the `value` argument is NULL The behavior of `strcmp` is undefined if any of its arguments is NULL, which can lead to a segfault depending on the implementation. So, this check is required to be able to use `getargs` with options where the value is optional, e.g., with `rd.break`. bsc#1219841 --- src/util/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/util.c b/src/util/util.c index b3498df6cd..1d152418d9 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -273,7 +273,7 @@ static int getargs(int argc, char **argv) cmdline = next_arg(cmdline, &key, &value); if (strcmp(key, search_key) == 0) { if (search_value) { - if (strcmp(value, search_value) == 0) { + if (value && strcmp(value, search_value) == 0) { printf("%s\n", value); found_value = true; } From ac5400abe21f607c7d92bed9ce87ca443794d290 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Tue, 16 Jan 2024 12:49:57 +0100 Subject: [PATCH 2/2] fix(dracut): correct regression with multiple `rd.break=` options (bsc#1221675) Since the introduction of the `dracut-util` binary to parse kernel command line arguments, if the user inputs multiple `rd.break=` options, dracut only stops the boot process at the last one. ``` [ 0.985362] localhost dracut-cmdline[245]: /bin/dracut-cmdline@18(): info 'Using kernel command line parameters:' ' ... rd.debug rd.break=cmdline rd.break=pre-pivot' ... [ 1.044979] localhost dracut-cmdline[245]: /bin/dracut-cmdline@48(): getarg rd.break=cmdline -d rdbreak=cmdline [ 1.044979] localhost dracut-cmdline[245]: /lib/dracut-lib.sh@155(getarg): debug_off [ 1.044979] localhost dracut-cmdline[245]: /lib/dracut-lib.sh@23(debug_off): set +x [ 1.044979] localhost dracut-cmdline[245]: /lib/dracut-lib.sh@218(getarg): return 1 ``` For options that can be specified multiple times, `getargs` should be used instead. ``` master> export CMDLINE="rd.break=cmdline rd.break=pre-udev rd.break=pre-pivot" master> ./dracut-getarg rd.break=cmdline master> echo $? 1 master> ./dracut-getarg rd.break=pre-udev master> echo $? 1 master> ./dracut-getarg rd.break=pre-pivot master> echo $? 0 master> ./dracut-getargs rd.break=cmdline cmdline master> echo $? 0 master> ./dracut-getargs rd.break=pre-udev pre-udev master> echo $? 0 master> ./dracut-getargs rd.break=pre-pivot pre-pivot master> echo $? 0 ``` Fixes 501d82f79675a6bf9b37e8250152515863a80236 --- modules.d/98dracut-systemd/dracut-cmdline.sh | 2 +- modules.d/98dracut-systemd/dracut-initqueue.sh | 2 +- modules.d/98dracut-systemd/dracut-mount.sh | 2 +- modules.d/98dracut-systemd/dracut-pre-mount.sh | 2 +- modules.d/98dracut-systemd/dracut-pre-pivot.sh | 4 ++-- modules.d/98dracut-systemd/dracut-pre-trigger.sh | 2 +- modules.d/98dracut-systemd/dracut-pre-udev.sh | 2 +- modules.d/99base/init.sh | 16 ++++++++-------- modules.d/99shutdown/shutdown.sh | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules.d/98dracut-systemd/dracut-cmdline.sh b/modules.d/98dracut-systemd/dracut-cmdline.sh index 44d5b31b96..8aea3a19aa 100755 --- a/modules.d/98dracut-systemd/dracut-cmdline.sh +++ b/modules.d/98dracut-systemd/dracut-cmdline.sh @@ -44,7 +44,7 @@ export fstype make_trace_mem "hook cmdline" '1+:mem' '1+:iomem' '3+:slab' # run scriptlets to parse the command line -getarg 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline" +getargs 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline" source_hook cmdline [ -f /lib/dracut/parse-resume.sh ] && . /lib/dracut/parse-resume.sh diff --git a/modules.d/98dracut-systemd/dracut-initqueue.sh b/modules.d/98dracut-systemd/dracut-initqueue.sh index ce919ce2e0..b0882dbe06 100755 --- a/modules.d/98dracut-systemd/dracut-initqueue.sh +++ b/modules.d/98dracut-systemd/dracut-initqueue.sh @@ -9,7 +9,7 @@ type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh source_conf /etc/conf.d make_trace_mem "hook initqueue" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=initqueue' -d 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue" +getargs 'rd.break=initqueue' -d 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue" RDRETRY=$(getarg rd.retry -d 'rd_retry=') RDRETRY=${RDRETRY:-180} diff --git a/modules.d/98dracut-systemd/dracut-mount.sh b/modules.d/98dracut-systemd/dracut-mount.sh index 2d90b08824..c1fbf88232 100755 --- a/modules.d/98dracut-systemd/dracut-mount.sh +++ b/modules.d/98dracut-systemd/dracut-mount.sh @@ -9,7 +9,7 @@ source_conf /etc/conf.d make_trace_mem "hook mount" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=mount' -d 'rdbreak=mount' && emergency_shell -n mount "Break mount" +getargs 'rd.break=mount' -d 'rdbreak=mount' && emergency_shell -n mount "Break before mount" # mount scripts actually try to mount the root filesystem, and may # be sourced any number of times. As soon as one suceeds, no more are sourced. i=0 diff --git a/modules.d/98dracut-systemd/dracut-pre-mount.sh b/modules.d/98dracut-systemd/dracut-pre-mount.sh index 7932084fd6..d7482c59d5 100755 --- a/modules.d/98dracut-systemd/dracut-pre-mount.sh +++ b/modules.d/98dracut-systemd/dracut-pre-mount.sh @@ -11,7 +11,7 @@ source_conf /etc/conf.d make_trace_mem "hook pre-mount" '1:shortmem' '2+:mem' '3+:slab' # pre pivot scripts are sourced just before we doing cleanup and switch over # to the new root. -getarg 'rd.break=pre-mount' 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break pre-mount" +getargs 'rd.break=pre-mount' -d 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break before pre-mount" source_hook pre-mount export -p > /dracut-state.sh diff --git a/modules.d/98dracut-systemd/dracut-pre-pivot.sh b/modules.d/98dracut-systemd/dracut-pre-pivot.sh index 0e4df68288..fa81b33543 100755 --- a/modules.d/98dracut-systemd/dracut-pre-pivot.sh +++ b/modules.d/98dracut-systemd/dracut-pre-pivot.sh @@ -11,11 +11,11 @@ source_conf /etc/conf.d make_trace_mem "hook pre-pivot" '1:shortmem' '2+:mem' '3+:slab' # pre pivot scripts are sourced just before we doing cleanup and switch over # to the new root. -getarg 'rd.break=pre-pivot' 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break pre-pivot" +getargs 'rd.break=pre-pivot' -d 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break before pre-pivot" source_hook pre-pivot # pre pivot cleanup scripts are sourced just before we switch over to the new root. -getarg 'rd.break=cleanup' 'rdbreak=cleanup' && emergency_shell -n cleanup "Break cleanup" +getargs 'rd.break=cleanup' -d 'rdbreak=cleanup' && emergency_shell -n cleanup "Break before cleanup" source_hook cleanup _bv=$(getarg rd.break -d rdbreak) && [ -z "$_bv" ] \ diff --git a/modules.d/98dracut-systemd/dracut-pre-trigger.sh b/modules.d/98dracut-systemd/dracut-pre-trigger.sh index 8d707b9b7f..8758ba9acc 100755 --- a/modules.d/98dracut-systemd/dracut-pre-trigger.sh +++ b/modules.d/98dracut-systemd/dracut-pre-trigger.sh @@ -12,7 +12,7 @@ make_trace_mem "hook pre-trigger" '1:shortmem' '2+:mem' '3+:slab' source_hook pre-trigger -getarg 'rd.break=pre-trigger' 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break pre-trigger" +getargs 'rd.break=pre-trigger' -d 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger" udevadm control --reload > /dev/null 2>&1 || : diff --git a/modules.d/98dracut-systemd/dracut-pre-udev.sh b/modules.d/98dracut-systemd/dracut-pre-udev.sh index e6a3518d37..a08f0fc711 100755 --- a/modules.d/98dracut-systemd/dracut-pre-udev.sh +++ b/modules.d/98dracut-systemd/dracut-pre-udev.sh @@ -10,7 +10,7 @@ source_conf /etc/conf.d make_trace_mem "hook pre-udev" '1:shortmem' '2+:mem' '3+:slab' # pre pivot scripts are sourced just before we doing cleanup and switch over # to the new root. -getarg 'rd.break=pre-udev' 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break pre-udev" +getargs 'rd.break=pre-udev' -d 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev" source_hook pre-udev _modprobe_d=/etc/modprobe.d diff --git a/modules.d/99base/init.sh b/modules.d/99base/init.sh index 978adb6ff4..f1320f13eb 100755 --- a/modules.d/99base/init.sh +++ b/modules.d/99base/init.sh @@ -123,7 +123,7 @@ fi # run scriptlets to parse the command line make_trace_mem "hook cmdline" '1+:mem' '1+:iomem' '3+:slab' -getarg 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline" +getargs 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline" source_hook cmdline [ -z "$root" ] && die "No or empty root= argument" @@ -133,7 +133,7 @@ export root rflags fstype netroot NEWROOT # pre-udev scripts run before udev starts, and are run only once. make_trace_mem "hook pre-udev" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=pre-udev' -d 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev" +getargs 'rd.break=pre-udev' -d 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev" source_hook pre-udev UDEV_LOG=err @@ -148,7 +148,7 @@ UDEV_QUEUE_EMPTY="udevadm settle --timeout=0" udevproperty "hookdir=$hookdir" make_trace_mem "hook pre-trigger" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=pre-trigger' -d 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger" +getargs 'rd.break=pre-trigger' -d 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger" source_hook pre-trigger udevadm control --reload > /dev/null 2>&1 || : @@ -157,7 +157,7 @@ udevadm trigger --type=subsystems --action=add > /dev/null 2>&1 udevadm trigger --type=devices --action=add > /dev/null 2>&1 make_trace_mem "hook initqueue" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=initqueue' -d 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue" +getargs 'rd.break=initqueue' -d 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue" RDRETRY=$(getarg rd.retry -d 'rd_retry=') RDRETRY=${RDRETRY:-180} @@ -223,10 +223,10 @@ unset RDRETRY # pre-mount happens before we try to mount the root filesystem, # and happens once. make_trace_mem "hook pre-mount" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=pre-mount' -d 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break pre-mount" +getargs 'rd.break=pre-mount' -d 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break before pre-mount" source_hook pre-mount -getarg 'rd.break=mount' -d 'rdbreak=mount' && emergency_shell -n mount "Break mount" +getargs 'rd.break=mount' -d 'rdbreak=mount' && emergency_shell -n mount "Break before mount" # mount scripts actually try to mount the root filesystem, and may # be sourced any number of times. As soon as one suceeds, no more are sourced. _i_mount=0 @@ -262,12 +262,12 @@ done # pre pivot scripts are sourced just before we doing cleanup and switch over # to the new root. make_trace_mem "hook pre-pivot" '1:shortmem' '2+:mem' '3+:slab' -getarg 'rd.break=pre-pivot' -d 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break pre-pivot" +getargs 'rd.break=pre-pivot' -d 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break before pre-pivot" source_hook pre-pivot make_trace_mem "hook cleanup" '1:shortmem' '2+:mem' '3+:slab' # pre pivot cleanup scripts are sourced just before we switch over to the new root. -getarg 'rd.break=cleanup' -d 'rdbreak=cleanup' && emergency_shell -n cleanup "Break cleanup" +getargs 'rd.break=cleanup' -d 'rdbreak=cleanup' && emergency_shell -n cleanup "Break before cleanup" source_hook cleanup # By the time we get here, the root filesystem should be mounted. diff --git a/modules.d/99shutdown/shutdown.sh b/modules.d/99shutdown/shutdown.sh index 73550ba9e3..f1fb9c746f 100755 --- a/modules.d/99shutdown/shutdown.sh +++ b/modules.d/99shutdown/shutdown.sh @@ -39,7 +39,7 @@ if [ "$ACTION" = "kexec" ] && ! command -v kexec > /dev/null 2>&1; then fi trap "emergency_shell --shutdown shutdown Signal caught!" 0 -getarg 'rd.break=pre-shutdown' && emergency_shell --shutdown pre-shutdown "Break before pre-shutdown" +getargs 'rd.break=pre-shutdown' && emergency_shell --shutdown pre-shutdown "Break before pre-shutdown" source_hook pre-shutdown @@ -149,7 +149,7 @@ while [ $_cnt -le 40 ]; do done [ $_cnt -ge 40 ] && _check_shutdown final -getarg 'rd.break=shutdown' && emergency_shell --shutdown shutdown "Break before shutdown" +getargs 'rd.break=shutdown' && emergency_shell --shutdown shutdown "Break before shutdown" case "$ACTION" in reboot | poweroff | halt)