From: Yu Watanabe Date: Mon, 9 Mar 2026 04:24:03 +0000 (+0900) Subject: sd-device: refuse spurious properties X-Git-Tag: v260-rc3~28^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a62cd5a153ffe18c27aff02685ed75c5bc4509a2;p=thirdparty%2Fsystemd.git sd-device: refuse spurious properties Properties are set through uevent, udev rules, or program output by IMPORT. They may contain spurious characters and udev database parsers may be confused. Let's refuse spurious properties. --- diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index e6b05b636a8..ef67c649d1e 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -30,6 +30,7 @@ #include "string-util.h" #include "strv.h" #include "time-util.h" +#include "utf8.h" int device_new_aux(sd_device **ret) { sd_device *device; @@ -81,12 +82,34 @@ static sd_device* device_free(sd_device *device) { DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free); +static bool property_is_valid(const char *key, const char *value) { + /* Device properties may be saved to database file, then may be parsed from the file. When if a + * property contains spurious characters, then the parser may be confused. Let's refuse spurious + * properties, even if it is internal, which will not be saved to database file, for consistency. */ + + if (isempty(key) || !in_charset(key, ALPHANUMERICAL "_.")) + return false; + + /* an empty value means unset the property, hence that's fine. */ + if (isempty(value)) + return true; + + /* refuse invalid UTF8 and control characters */ + if (!utf8_is_valid(value) || string_has_cc(value, /* ok= */ NULL)) + return false; + + return true; +} + int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db) { OrderedHashmap **properties; assert(device); assert(key); + if (!property_is_valid(key, value)) + return -EINVAL; + if (db) properties = &device->properties_db; else diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index db7c9420cc6..43b76f46e9b 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -841,6 +841,54 @@ TEST(devname_from_devnum) { } } +TEST(device_add_property) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *val; + + ASSERT_OK(sd_device_new_from_syspath(&dev, "/sys/class/net/lo")); + + /* add a property */ + ASSERT_OK(device_add_property(dev, "hoge", "foo")); + ASSERT_OK(sd_device_get_property_value(dev, "hoge", &val)); + ASSERT_STREQ(val, "foo"); + + /* update an existing property */ + ASSERT_OK(device_add_property(dev, "hoge", "bar")); + ASSERT_OK(sd_device_get_property_value(dev, "hoge", &val)); + ASSERT_STREQ(val, "bar"); + + /* remove an existing property */ + ASSERT_OK(device_add_property(dev, "hoge", NULL)); + ASSERT_ERROR(sd_device_get_property_value(dev, "hoge", &val), ENOENT); + + /* add a property again */ + ASSERT_OK(device_add_property(dev, "hoge", "foo")); + ASSERT_OK(sd_device_get_property_value(dev, "hoge", &val)); + ASSERT_STREQ(val, "foo"); + + /* remove it with an empty string */ + ASSERT_OK(device_add_property(dev, "hoge", "")); + ASSERT_ERROR(sd_device_get_property_value(dev, "hoge", &val), ENOENT); + + /* check internal property (starting with dot) */ + ASSERT_OK(device_add_property(dev, ".hoge", "baz")); + ASSERT_OK(sd_device_get_property_value(dev, ".hoge", &val)); + ASSERT_STREQ(val, "baz"); + + /* refuse invalid property names */ + ASSERT_ERROR(device_add_property(dev, "hoge-hoge", "aaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge=hoge", "aaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge hoge", "aaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge\nhoge", "aaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge\rhoge", "aaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge\thoge", "aaa"), EINVAL); + + /* refuse invalid property values */ + ASSERT_ERROR(device_add_property(dev, "hoge", "aaa\naaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge", "aaa\raaa"), EINVAL); + ASSERT_ERROR(device_add_property(dev, "hoge", "aaa\taaa"), EINVAL); +} + static int intro(void) { int r;