Skip to content

Commit

Permalink
fix(dracut-systemd): rootfs-generator cannot write outside of generat…
Browse files Browse the repository at this point in the history
…or dir

Although it was already documented in systemd.generator(7) that generators must
not write to locations other than those passed as arguments, since
systemd/systemd@ca6ce62d systemd executes generators
in a mount namespace "sandbox", so now the hooks created by the rootfs-generator
are lost.

These hooks are created using the root= cmdline argument, so this patch moves
the creation of these hooks to a cmdline hook.

Fixes issue #2211
Fixes issue #2225
  • Loading branch information
aafeijoo-suse authored and LaszloGombos committed May 10, 2023
1 parent acfa793 commit 86c8a5a
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
2 changes: 2 additions & 0 deletions modules.d/98dracut-systemd/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ install() {

inst_script "$moddir/rootfs-generator.sh" "$systemdutildir"/system-generators/dracut-rootfs-generator

inst_hook cmdline 00 "$moddir/parse-root.sh"

for i in \
dracut-cmdline.service \
dracut-cmdline-ask.service \
Expand Down
38 changes: 38 additions & 0 deletions modules.d/98dracut-systemd/parse-root.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/sh

type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh

root=$(getarg root=)
case "${root#block:}" in
LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
root="block:$(label_uuid_to_dev "$root")"
rootok=1
;;
/dev/nfs | /dev/root) # ignore legacy
;;
/dev/*)
root="block:${root}"
rootok=1
;;
esac

if [ "$rootok" = "1" ]; then
root_dev="${root#block:}"
root_name="$(str_replace "$root_dev" '/' '\x2f')"
if ! [ -e "$hookdir/initqueue/finished/devexists-${root_name}.sh" ]; then

# If a LUKS device needs unlocking via systemd in the initrd, assume
# it's for the root device. In that case, don't block on it if it's
# after remote-fs-pre.target since the initqueue is ordered before it so
# it will never actually show up (think Tang-pinned rootfs).
cat > "$hookdir/initqueue/finished/devexists-${root_name}.sh" << EOF
if ! grep -q After=remote-fs-pre.target /run/systemd/generator/systemd-cryptsetup@*.service 2>/dev/null; then
[ -e "$root_dev" ]
fi
EOF
{
printf '[ -e "%s" ] || ' "$root_dev"
printf 'warn "\"%s\" does not exist"\n' "$root_dev"
} >> "$hookdir/emergency/80-${root_name}.sh"
fi
fi
20 changes: 1 addition & 19 deletions modules.d/98dracut-systemd/rootfs-generator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,10 @@ generator_wait_for_dev() {
local _name
local _timeout

_name="$(str_replace "$1" '/' '\x2f')"
_name=$(dev_unit_name "$1")
_timeout=$(getarg rd.timeout)
_timeout=${_timeout:-0}

if ! [ -e "$hookdir/initqueue/finished/devexists-${_name}.sh" ]; then

# If a LUKS device needs unlocking via systemd in the initrd, assume
# it's for the root device. In that case, don't block on it if it's
# after remote-fs-pre.target since the initqueue is ordered before it so
# it will never actually show up (think Tang-pinned rootfs).
cat > "$hookdir/initqueue/finished/devexists-${_name}.sh" << EOF
if ! grep -q After=remote-fs-pre.target "$GENERATOR_DIR"/systemd-cryptsetup@*.service 2>/dev/null; then
[ -e "$1" ]
fi
EOF
{
printf '[ -e "%s" ] || ' "$1"
printf 'warn "\"%s\" does not exist"\n' "$1"
} >> "$hookdir/emergency/80-${_name}.sh"
fi

_name=$(dev_unit_name "$1")
if ! [ -L "$GENERATOR_DIR"/initrd.target.wants/"${_name}".device ]; then
[ -d "$GENERATOR_DIR"/initrd.target.wants ] || mkdir -p "$GENERATOR_DIR"/initrd.target.wants
ln -s ../"${_name}".device "$GENERATOR_DIR"/initrd.target.wants/"${_name}".device
Expand Down

0 comments on commit 86c8a5a

Please sign in to comment.