sd-device: seal object earlier

Previously, the sd_device object was sealed after it was verified. However,
the verifier device_verify() calls device_in_subsystem() which reads the uevent
file if the object is not sealed. Hence, basic information such as
MAJOR=/MINOR=/IFINDEX= and so on were updated by the uevent file,
and the ones passed through netlink were simply discarded.

Seal the device earlier, like we already do in device_clone_with_db().
This ensures all basic information passed through netlink is always honored.

Fixes the following issue:

$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:1
Oct 12 04:44:22 systemd-udevd[404]: loop1p1: Device is queued (SEQNUM=2244, ACTION=remove)

$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:2
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Processing device (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "INOTIFY_WATCH_REMOVE=1"
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Device processed (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: sd-device-monitor(worker): Passed 325 byte to netlink monitor.
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "PROCESSED=1"

Here, the main process of udevd receives the uevent with SEQNUM=2244 with
MAJOR=259 and MINOR=1. However, when it is forwarded to the udev worker,
MINOR= is changed to 2. Hence, the worker tries to read a wrong
non-existent database file and cannot remove stale devlinks.

Fixes a regression in ab1bd9daed.

(cherry picked from commit f58a2efc557a740891c5a56c82c971ae9a4e84c1)
This commit is contained in:
Yu Watanabe
2026-10-16 17:24:51 +01:00
committed by Luca Boccassi
parent 81795d8826
commit d2b81326ac
+5 -3
View File
@@ -461,8 +461,6 @@ static int device_verify(sd_device *device) {
"sd-device: Failed to set driver subsystem: %m");
}
device->sealed = true;
return 0;
}
@@ -478,6 +476,8 @@ int device_new_from_strv(sd_device **ret, char **strv) {
if (r < 0)
return r;
device_seal(device);
STRV_FOREACH(key, strv) {
r = device_append(device, *key, &major, &minor);
if (r < 0)
@@ -512,6 +512,8 @@ int device_new_from_nulstr(sd_device **ret, char *nulstr, size_t len) {
if (r < 0)
return r;
device_seal(device);
for (size_t i = 0; i < len; ) {
char *key;
const char *end;
@@ -661,7 +663,7 @@ int device_clone_with_db(sd_device *device, sd_device **ret) {
return r;
/* Seal device to prevent reading the uevent file, as the device may have been already removed. */
dest->sealed = true;
device_seal(dest);
/* Copy syspath, then also devname, sysname or sysnum can be obtained. */
r = device_set_syspath(dest, device->syspath, false);