summaryrefslogtreecommitdiff
path: root/src/core/device.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-10-26 01:18:05 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-10-27 06:11:10 +0900
commitb6c86ae28149c4abb2f0bd6acab13153382da9e7 (patch)
treee7a17de16c26e0f505044def76d0e70cc23c5a94 /src/core/device.c
parent1ea74fca3a3c737f3901bc10d879b7830b3528bf (diff)
downloadsystemd-b6c86ae28149c4abb2f0bd6acab13153382da9e7.tar.gz
core/device: verify device syspath on switching root
Otherwise, if a device is removed while switching root, then the corresponding .device unit will never go to inactive state. This replaces the code dropped by cf1ac0cfe44997747b0f857a1d0b67cea1298272. Fixes #25106.
Diffstat (limited to 'src/core/device.c')
-rw-r--r--src/core/device.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/core/device.c b/src/core/device.c
index 7e354b2b4a..6e07f2745b 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -305,6 +305,19 @@ static int device_coldplug(Unit *u) {
found &= ~DEVICE_FOUND_UDEV;
if (state == DEVICE_PLUGGED)
state = DEVICE_TENTATIVE;
+
+ /* Also check the validity of the device syspath. Without this check, if the device was
+ * removed while switching root, it would never go to inactive state, as both Device.found
+ * and Device.enumerated_found do not have the DEVICE_FOUND_UDEV flag, so device_catchup() in
+ * device_update_found_one() does nothing in most cases. See issue #25106. Note that the
+ * syspath field is only serialized when systemd is sufficiently new and the device has been
+ * already processed by udevd. */
+ if (d->deserialized_sysfs) {
+ _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
+
+ if (sd_device_new_from_syspath(&dev, d->deserialized_sysfs) < 0)
+ state = DEVICE_DEAD;
+ }
}
if (d->found == found && d->state == state)