Public bug reported:
== Description ==
The initramfs udevd is sometimes still running after the switch to the
real root filesystem. It then aborts on an assertion in chase(), leaving a
core dump behind on every affected boot.
The udev initramfs hook (debian/extra/initramfs-tools/scripts/init-bottom/udev)
in noble only does:
udevadm control --exit
mount -n -o move /dev "${rootmnt}/dev" ...
nuke /dev (or rm -rf /dev)
"udevadm control --exit" does not wait for udevd to terminate. If udevd
still has queued events, it keeps running while the initramfs is torn down.
It is still running after run-init switches to the real root, alongside the
systemd-udevd.service instance started by systemd.
Debian fixed this hook in systemd 256~rc3-3 (Debian bug #1056564,
salsa commit f2590632 "initramfs: call udevadm settle before control --exit
to ensure workers have stopped"):
udevadm settle --timeout=60
udevadm control --exit
noble (255.4-1ubuntu8.17) does not have this change.
Release: Ubuntu 24.04.4 LTS (noble)
Package: systemd / udev 255.4-1ubuntu8.17 (amd64)
Kernel: 6.8.0-138-generic
== Steps to reproduce ==
The problem is random.
Start a VM with Ubuntu-24.04 and reboot it several times until a coredump is
generated.
1. Boot Ubuntu 24.04 with the default initramfs-tools initramfs (udev hook
unmodified).
2. After boot, check "coredumpctl list".
3. reboot with 'reboot -f' until a coredump happens
== Expected result ==
The initramfs udevd has exited before the switch to the real root. Only
systemd-udevd.service runs afterwards and nothing crashes.
== Actual result ==
The initramfs udevd (started by initramfs-tools: "--daemon
--resolve-names=never", cgroup /init.scope) is still running after the
switch. It runs alongside systemd-udevd.service and aborts with SIGABRT:
Assertion 'path_is_absolute(p)' failed at src/basic/chase.c:648,
function chase(). Aborting.
Journal of the affected boot:
10:37:36 systemd[1]: Starting systemd-udev-trigger.service - Coldplug All
udev Devices...
10:37:36 systemd[1]: Finished systemd-udev-trigger.service - Coldplug All
udev Devices.
10:37:36 systemd[1]: Starting systemd-udevd.service - Rule-based Manager for
Device Events and Files...
10:37:36 systemd-udevd[437]: Using default interface naming scheme 'v255'.
10:37:36 systemd[1]: Started systemd-udevd.service - Rule-based Manager for
Device Events and Files.
10:37:37 systemd-coredump[526]: Process 156 (systemd-udevd) of user 0 dumped
core.
coredumpctl info:
PID: 156 (systemd-udevd)
Command Line: /usr/lib/systemd/systemd-udevd --daemon --resolve-names=never
Executable: /usr/bin/udevadm
Control Group: /init.scope
Signal: 6 (ABRT)
build-id: 83d1596822cd6fdd8bda1fc3d2501add8f16e141
When the core was opened, gdb reported every file mapping of the process as
"(deleted)": /usr/bin/udevadm, libc, hwdb.bin, modules.*.bin and others.
These are the initramfs copies, removed by run-init.
The same crash, with the same backtrace and the same paths, was seen on a
second machine (initramfs udevd PID 239 aborted 2 s after
systemd-udevd.service PID 487 started).
== Backtrace (udev-dbgsym 255.4-1ubuntu8.17) ==
#5 log_assert_failed () at ../src/basic/log.c:967
#6 chase (path=<optimized out>, root=0x5622716a3194 "/", flags=<optimized out>,
ret_path=0x7ffe92f19400, ret_fd=0x7ffe92f193f4) at
../src/basic/chase.c:648
root_abs = 0x0
absolute = "/usr/lib/udev/rules.d"
p = "usr/lib/udev/rules.d"
fd = 44
pfd = 45
r = 1
#7 chase_and_opendir (chase_flags=CHASE_PREFIX_ROOT, root=0x0, ...) at
../src/basic/chase.c:810
#8 conf_files_list_strv (suffix=".rules", root=0x0, dirs=..., flags=0) at
../src/basic/conf-files.c:166
#9 config_get_stats_by_path (suffix=".rules", check_dropins=false, root=0x0)
at ../src/shared/conf-parser.c:747
#10 udev_rules_should_reload (rules=0x5622924272e0) at
../src/udev/udev-rules.c:1685
#11 manager_reload (manager=..., force=false) at ../src/udev/udev-manager.c:271
now_usec = 4157749
#12 event_queue_start (manager=...) at ../src/udev/udev-manager.c:579
#13 on_post (s=..., userdata=...) at ../src/udev/udev-manager.c:1147
#14 source_dispatch () at ../src/libsystemd/sd-event/sd-event.c:4227
#15 sd_event_dispatch () at ../src/libsystemd/sd-event/sd-event.c:4808
#16 sd_event_run () at ../src/libsystemd/sd-event/sd-event.c:4869
#17 sd_event_loop () at ../src/libsystemd/sd-event/sd-event.c:4891
#18 manager_main () at ../src/udev/udev-manager.c:1346
#19 run_udevd () at ../src/udev/udevd.c:407
#20 run () at ../src/udev/udevadm.c:124
#21 main () at ../src/udev/udevadm.c:140
(full "thread apply all bt full" attached)
== Analysis ==
The crash happens when udevd's event queue becomes idle: on_post ->
event_queue_start -> manager_reload(force=false) -> udev_rules_should_reload()
-> chase("/usr/lib/udev/rules.d", root="/", CHASE_PREFIX_ROOT).
chase() opens "/" and calls chaseat(fd, "usr/lib/udev/rules.d", ...).
chaseat() returns an absolute path only if chaseat_needs_absolute() ->
dir_fd_is_root(fd) is true. dir_fd_is_root() compares the inode and mount ID
of "." and "..". chase() assumes that the result is always absolute when
root is "/" (comment at chase.c:640-646) and asserts on it at line 648.
Here chaseat() returned a relative path, so dir_fd_is_root() returned false
for the process's own "/". This fits a process whose root is still the old
initramfs rootfs after run-init has moved the real root over "/". That last
step is inferred and has not been verified.
== Proposed fix ==
1. Backport Debian commit f2590632 (#1056564) to noble: run
"udevadm settle --timeout=60" before "udevadm control --exit" in
init-bottom/udev. This removes the event backlog that keeps the
initramfs udevd alive.
2. Optionally, wait in init-bottom/udev until udevd has actually exited
(bounded, with a kill fallback) before tearing down /dev. settle +
"control --exit" still leaves a small window if new uevents arrive.
3. Upstream robustness (separate, lower priority): chase() could handle a
relative chaseat() result when root is "/" instead of asserting.
== References ==
- Debian bug #1056564 "udev: run-init stops while nuking initramfs contents",
fixed in systemd 256~rc3-3: https://bugs.debian.org/1056564
- Debian commit: https://salsa.debian.org/systemd-team/systemd/-/commit/f2590632
== Attachments ==
- crash3 (coredumpctl info + gdb "thread apply all bt full")
- coredump:
core.systemd-udevd.0.8933582c82164652916d2961fb4c2a6e.156.1792139856000000.zst
** Affects: systemd (Ubuntu)
Importance: Undecided
Status: New
** Tags: noble
** Attachment added: "coredumpctl info"
https://bugs.launchpad.net/bugs/2172311/+attachment/6013010/+files/crash3
** Tags added: noble
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2172311
Title:
[noble] initramfs udevd survives switch to real root and crashes:
"Assertion 'path_is_absolute(p)' failed at src/basic/chase.c:648" —
please backport Debian fix for #1056564
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2172311/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs