]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device: introduce device_get_sysattr_safe_string()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 11 Mar 2026 20:39:42 +0000 (05:39 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 17 May 2026 17:55:56 +0000 (02:55 +0900)
This introduce a helper function that verifies read sysattr value.
Some sysattr value may come from firmware, and kernel may expose unsafe
string. The introduced function should be used when we use the result as
a string.

src/libsystemd/sd-device/device-private.h
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-device/test-sd-device.c

index f2f349f2acac9e65bed452ad7bee282ae20293a1..27aa6bf2fc2c3f639f65bcf1eacac33578355de2 100644 (file)
@@ -16,6 +16,7 @@ int device_get_property_bool(sd_device *device, const char *key);
 int device_get_property_int(sd_device *device, const char *key, int *ret);
 int device_get_property_uint(sd_device *device, const char *key, unsigned *ret);
 int device_get_ifname(sd_device *device, const char **ret);
+int device_get_sysattr_safe_string(sd_device *device, const char *sysattr, const char **ret);
 int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value);
 int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret_value);
 static inline int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value) {
index 307137b431a8b99492d76831604e5587f3ef69e7..09a48a74c5a4b18ae5dac4da127be5f6dd7ce7e9 100644 (file)
@@ -2619,6 +2619,34 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
         return sd_device_get_sysattr_value_with_size(device, sysattr, ret_value, NULL);
 }
 
+int device_get_sysattr_safe_string(sd_device *device, const char *sysattr, const char **ret) {
+        const char *value;
+        int r;
+
+        r = sd_device_get_sysattr_value(device, sysattr, &value);
+        if (r < 0)
+                return r;
+
+        if (!string_is_safe(value,
+                            STRING_ALLOW_EMPTY |
+                            STRING_ALLOW_NEWLINES |
+                            STRING_ALLOW_BACKSLASHES |
+                            STRING_ALLOW_QUOTES |
+                            STRING_ALLOW_GLOBS)) {
+                if (DEBUG_LOGGING) {
+                        _cleanup_free_ char *escaped = cescape(value);
+                        log_device_debug(device, "sd-device: '%s' sysattr contains invalid characters, refusing: %s",
+                                         sysattr, strnull(escaped));
+                }
+                return -ENXIO;
+        }
+
+        if (ret)
+                *ret = value;
+
+        return 0;
+}
+
 int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value) {
         const char *value;
         int r;
index bf62e9082b56e111a1a21eed52fc7a39be00eead..9201919898a025065f2774c68a93210da09dcfef 100644 (file)
@@ -305,6 +305,13 @@ static void test_sd_device_one(sd_device *d) {
                 ASSERT_OK(r = device_get_sysattr_unsigned(d, "nsid", &x));
                 ASSERT_EQ(x > 0, r > 0);
         }
+
+        const char *uevent;
+        if (sd_device_get_sysattr_value(d, "uevent", &uevent) >= 0) {
+                const char *uevent_safe;
+                ASSERT_OK(device_get_sysattr_safe_string(d, "uevent", &uevent_safe));
+                ASSERT_STREQ(uevent, uevent_safe);
+        }
 }
 
 static void exclude_problematic_devices(sd_device_enumerator *e) {