]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: do not clear sd_device.all_tags even on TAG="hoge"
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 22 Feb 2026 19:58:43 +0000 (04:58 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 22 Feb 2026 20:46:42 +0000 (05:46 +0900)
The current tag concept has been introduced by
e77b146f825ef1bb63c297cc713962b94422d2c6 (v247) to make symlinks in
/run/udev/tags/ are 'sticky'.

However, when TAG= (rather than TAG+=) is specified, then the tags
assigned in the previous events were also cleared.
This fixes the issue and now symlinks in /run/udev/tags/ are really
'sticky'.

Fortunately, TAG= is mostly unused. So, the issue should not affect
and the fix should not change anything on almost all systems.

src/libsystemd/sd-device/device-private.c
src/libsystemd/sd-device/device-private.h
src/udev/udev-rules.c

index 828697e6176527c8c05c78b54d8fb82921de591a..d640eeb25025a7529fbc39be7cc4bdfb521b9f3f 100644 (file)
@@ -710,13 +710,23 @@ int device_copy_all_tags(sd_device *dest, sd_device *src) {
         return 0;
 }
 
-void device_cleanup_tags(sd_device *device) {
+int device_cleanup_tags(sd_device *device, sd_device *original) {
+        int r;
+
         assert(device);
 
-        device->all_tags = set_free(device->all_tags);
+        _cleanup_set_free_ Set *saved = TAKE_PTR(device->all_tags);
         device->current_tags = set_free(device->current_tags);
         device->property_tags_outdated = true;
         device->tags_generation++;
+
+        r = device_copy_all_tags(device, original);
+        if (r < 0) {
+                set_free_and_replace(device->all_tags, saved);
+                return r;
+        }
+
+        return 0;
 }
 
 void device_cleanup_devlinks(sd_device *device) {
index 376a4a479cd868604b4c08c19cdd5b494abe4474..90f4e103f5e9e24a67c7ced613481a842309c91d 100644 (file)
@@ -46,7 +46,7 @@ int device_add_propertyf(sd_device *device, const char *key, const char *format,
 int device_add_tag(sd_device *device, const char *tag, bool both);
 void device_remove_tag(sd_device *device, const char *tag);
 int device_copy_all_tags(sd_device *dest, sd_device *src);
-void device_cleanup_tags(sd_device *device);
+int device_cleanup_tags(sd_device *device, sd_device *original);
 void device_cleanup_devlinks(sd_device *device);
 
 uint64_t device_get_properties_generation(sd_device *device);
index 06686e3715e83df3904c35298a2ade2820680a53..f0e4fbccfd79194893d7c5b563a5a72180994abb 100644 (file)
@@ -2900,8 +2900,11 @@ static int udev_rule_apply_token_to_event(
 
                 assert(IN_SET(token->op, OP_ASSIGN, OP_ADD));
 
-                if (token->op == OP_ASSIGN)
-                        device_cleanup_tags(dev);
+                if (token->op == OP_ASSIGN) {
+                        r = device_cleanup_tags(dev, event->dev_db_clone);
+                        if (r < 0)
+                                log_event_warning_errno(event, token, r, "Failed to clear previously assigned tags, ignoring: %m");
+                }
 
                 r = device_add_tag(dev, buf, /* both= */ true);
                 if (r == -ENOMEM)