Introduce several more helper functions to read sysfs attributes and use them where applicable (#41065)

Let's not use sd_device_get_sysattr_value() unless the result is
sanitized, escaped, or filtered.
This commit is contained in:
Yu Watanabe
2026-05-18 07:26:44 +09:00
committed by GitHub
29 changed files with 393 additions and 396 deletions
+9 -18
View File
@@ -66,13 +66,9 @@ static int has_multiple_graphics_cards(void) {
return r;
FOREACH_DEVICE(e, dev) {
const char *s;
unsigned long c;
uint32_t c;
if (sd_device_get_sysattr_value(dev, "class", &s) < 0)
continue;
if (safe_atolu(s, &c) < 0)
if (device_get_sysattr_u32(dev, "class", &c) < 0)
continue;
if (c != PCI_CLASS_GRAPHICS_CARD)
@@ -180,7 +176,7 @@ static int same_device(sd_device *a, sd_device *b) {
static int validate_device(sd_device *device) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerate = NULL;
const char *v, *sysname;
const char *sysname;
sd_device *parent;
int r;
@@ -205,10 +201,10 @@ static int validate_device(sd_device *device) {
if (r > 0)
return true; /* We assume LED device is always valid. */
r = sd_device_get_sysattr_value(device, "type", &v);
r = device_get_sysattr_streq(device, "type", "raw");
if (r < 0)
return log_device_debug_errno(device, r, "Failed to read 'type' sysattr: %m");
if (!streq(v, "raw"))
if (r == 0)
return true;
r = find_pci_or_platform_parent(device, &parent);
@@ -281,7 +277,7 @@ static int validate_device(sd_device *device) {
const char *other_sysname = NULL, *other_type = NULL;
(void) sd_device_get_sysname(other, &other_sysname);
(void) sd_device_get_sysattr_value(other, "type", &other_type);
(void) device_get_sysattr_safe_string(other, "type", &other_type);
log_device_debug(device,
"Found another %s backlight device %s on the same PCI, skipping.",
strna(other_type), strna(other_sysname));
@@ -295,7 +291,7 @@ static int validate_device(sd_device *device) {
const char *other_sysname = NULL, *other_type = NULL;
(void) sd_device_get_sysname(other, &other_sysname);
(void) sd_device_get_sysattr_value(other, "type", &other_type);
(void) device_get_sysattr_safe_string(other, "type", &other_type);
log_device_debug(device,
"Found another %s backlight device %s, which has higher precedence, skipping.",
strna(other_type), strna(other_sysname));
@@ -316,7 +312,7 @@ static int read_max_brightness(sd_device *device, unsigned *ret) {
r = device_get_sysattr_unsigned(device, "max_brightness", &max_brightness);
if (r < 0)
return log_device_warning_errno(device, r, "Failed to read/parse 'max_brightness' attribute: %m");
return log_device_warning_errno(device, r, "Failed to read 'max_brightness' attribute: %m");
/* If max_brightness is 0, then there is no actual backlight device. This happens on desktops
* with Asus mainboards that load the eeepc-wmi module. */
@@ -418,21 +414,16 @@ static int shall_clamp(sd_device *device, unsigned *ret) {
}
static int read_brightness(sd_device *device, unsigned max_brightness, unsigned *ret_brightness) {
const char *value;
unsigned brightness;
int r;
assert(device);
assert(ret_brightness);
r = sd_device_get_sysattr_value(device, "brightness", &value);
r = device_get_sysattr_unsigned(device, "brightness", &brightness);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to read 'brightness' attribute: %m");
r = safe_atou(value, &brightness);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse 'brightness' attribute: %s", value);
if (brightness > max_brightness)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL),
"brightness=%u is larger than max_brightness=%u",
+1
View File
@@ -103,6 +103,7 @@ typedef enum Glyph Glyph;
typedef enum ImageClass ImageClass;
typedef enum JobMode JobMode;
typedef enum RuntimeScope RuntimeScope;
typedef enum StringSafeFlags StringSafeFlags;
typedef enum TimestampStyle TimestampStyle;
typedef enum UnitActiveState UnitActiveState;
typedef enum UnitDependency UnitDependency;
+5 -1
View File
@@ -1113,7 +1113,11 @@ bool string_is_safe(const char *p, StringSafeFlags flags) {
return false;
for (const char *t = p; *t; t++) {
if ((*t > 0 && *t < ' ') || *t == 0x7f) /* never allow control characters */
/* never allow control characters, except for new line */
if ((*t > 0 && *t < ' ' && *t != '\n') || *t == 0x7f)
return false;
if (!FLAGS_SET(flags, STRING_ALLOW_NEWLINES) && *t == '\n')
return false;
if (!FLAGS_SET(flags, STRING_ALLOW_BACKSLASHES) && *t == '\\')
+5 -4
View File
@@ -223,10 +223,11 @@ static inline int strdup_to(char **ret, const char *src) {
typedef enum StringSafeFlags {
STRING_ASCII = 1 << 0, /* Verify string is 7-Bit ASCII (rather than just UTF-8) */
STRING_ALLOW_EMPTY = 1 << 1, /* Allow empty strings */
STRING_ALLOW_BACKSLASHES = 1 << 2, /* Allow backslashes (\) */
STRING_ALLOW_QUOTES = 1 << 3, /* Allow quotes (" or ') */
STRING_ALLOW_GLOBS = 1 << 4, /* Allow globs (?, * or [) */
STRING_FILENAME = 1 << 5, /* Verify the string is valid as regular filename */
STRING_ALLOW_NEWLINES = 1 << 2, /* Allow newlines (\n) */
STRING_ALLOW_BACKSLASHES = 1 << 3, /* Allow backslashes (\) */
STRING_ALLOW_QUOTES = 1 << 4, /* Allow quotes (" or ') */
STRING_ALLOW_GLOBS = 1 << 5, /* Allow globs (?, * or [) */
STRING_FILENAME = 1 << 6, /* Verify the string is valid as regular filename */
} StringSafeFlags;
bool string_is_safe(const char *p, StringSafeFlags flags) _pure_;
+7 -4
View File
@@ -20,6 +20,7 @@
#include "constants.h"
#include "daemon-util.h"
#include "device-private.h"
#include "device-util.h"
#include "env-file.h"
#include "env-util.h"
#include "extract-word.h"
@@ -442,12 +443,14 @@ static int get_sysattr(sd_device *device, const char *key, char **ret) {
if (!device)
return -ENODEV;
r = sd_device_get_sysattr_value(device, key, &s);
r = device_get_sysattr_safe_string(device, key, &s);
if (r < 0)
return r;
return log_device_debug_errno(device, r, "Failed to read '%s' attribute: %m", key);
if (!string_is_safe_for_dbus(s))
return -ENXIO;
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENXIO),
"'%s' attribute is not safe for exposing through DBus: %s",
key, s);
return strdup_to(ret, empty_to_null(s));
}
@@ -703,7 +706,7 @@ static const char* fallback_chassis_by_device_tree(Context *c) {
if (!c->device_tree)
return NULL;
r = sd_device_get_sysattr_value(c->device_tree, "chassis-type", &type);
r = device_get_sysattr_safe_string(c->device_tree, "chassis-type", &type);
if (r < 0) {
log_debug_errno(r, "Failed to read device-tree chassis type, ignoring: %m");
return NULL;
+19 -6
View File
@@ -16,13 +16,26 @@ 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_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) {
return device_get_sysattr_unsigned_full(device, sysattr, 0, ret_value);
int device_get_sysattr_streq(sd_device *device, const char *sysattr, const char *expected);
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);
int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret);
static inline int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret) {
return device_get_sysattr_unsigned_full(device, sysattr, /* base= */ 0, ret);
}
int device_get_sysattr_u32(sd_device *device, const char *sysattr, uint32_t *ret_value);
int device_get_sysattr_u64(sd_device *device, const char *sysattr, uint64_t *ret_value);
int device_get_sysattr_u8_full(sd_device *device, const char *sysattr, unsigned base, uint8_t *ret);
static inline int device_get_sysattr_u8(sd_device *device, const char *sysattr, uint8_t *ret) {
return device_get_sysattr_u8_full(device, sysattr, /* base= */ 0, ret);
}
int device_get_sysattr_u16_full(sd_device *device, const char *sysattr, unsigned base, uint16_t *ret);
static inline int device_get_sysattr_u16(sd_device *device, const char *sysattr, uint16_t *ret) {
return device_get_sysattr_u16_full(device, sysattr, /* base= */ 0, ret);
}
int device_get_sysattr_u32_full(sd_device *device, const char *sysattr, unsigned base, uint32_t *ret);
static inline int device_get_sysattr_u32(sd_device *device, const char *sysattr, uint32_t *ret) {
return device_get_sysattr_u32_full(device, sysattr, /* base= */ 0, ret);
}
int device_get_sysattr_u64(sd_device *device, const char *sysattr, uint64_t *ret);
int device_get_sysattr_bool(sd_device *device, const char *sysattr);
int device_get_devlink_priority(sd_device *device, int *ret);
int device_get_devnode_mode(sd_device *device, mode_t *ret);
+102 -83
View File
@@ -15,6 +15,7 @@
#include "dirent-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "escape.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@@ -30,7 +31,6 @@
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "utf8.h"
int device_new_aux(sd_device **ret) {
sd_device *device;
@@ -96,10 +96,10 @@ static bool property_is_valid(const char *key, const char *value) {
return true;
/* refuse invalid UTF8 and control characters */
if (!utf8_is_valid(value) || string_has_cc(value, /* ok= */ NULL))
return false;
return true;
return string_is_safe(value,
STRING_ALLOW_BACKSLASHES |
STRING_ALLOW_QUOTES |
STRING_ALLOW_GLOBS);
}
int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db) {
@@ -108,8 +108,15 @@ int device_add_property_aux(sd_device *device, const char *key, const char *valu
assert(device);
assert(key);
if (!property_is_valid(key, value))
if (!property_is_valid(key, value)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *escaped_key = cescape(key),
*escaped_value = cescape(strempty(value));
log_device_debug(device, "sd-device: Refusing invalid property: %s=%s",
strnull(escaped_key), strnull(escaped_value));
}
return -EINVAL;
}
if (db)
properties = &device->properties_db;
@@ -830,7 +837,7 @@ int device_read_uevent_file(sd_device *device) {
device->uevent_loaded = true;
const char *uevent;
r = sd_device_get_sysattr_value(device, "uevent", &uevent);
r = device_get_sysattr_safe_string(device, "uevent", &uevent);
if (ERRNO_IS_NEG_PRIVILEGE(r) || ERRNO_IS_NEG_DEVICE_ABSENT(r))
/* The uevent files may be write-only, the device may be already removed, or the device
* may not have the uevent file. */
@@ -881,7 +888,7 @@ int device_read_uevent_file(sd_device *device) {
return 0;
}
_public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
_public_ int sd_device_get_ifindex(sd_device *device, int *ret) {
int r;
assert_return(device, -EINVAL);
@@ -893,8 +900,8 @@ _public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) {
if (device->ifindex <= 0)
return -ENOENT;
if (ifindex)
*ifindex = device->ifindex;
if (ret)
*ret = device->ifindex;
return 0;
}
@@ -1251,7 +1258,7 @@ _public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
if (!device->subsystem_set) {
const char *subsystem;
r = sd_device_get_sysattr_value(device, "subsystem", &subsystem);
r = device_get_sysattr_safe_string(device, "subsystem", &subsystem);
if (r < 0 && r != -ENOENT)
return log_device_debug_errno(device, r,
"sd-device: Failed to read subsystem for %s: %m",
@@ -1341,7 +1348,7 @@ _public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *device, cons
}
}
_public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
_public_ int sd_device_get_devnum(sd_device *device, dev_t *ret) {
int r;
assert_return(device, -EINVAL);
@@ -1353,8 +1360,8 @@ _public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) {
if (major(device->devnum) <= 0)
return -ENOENT;
if (devnum)
*devnum = device->devnum;
if (ret)
*ret = device->devnum;
return 0;
}
@@ -1391,7 +1398,7 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
if (!device->driver_set) {
const char *driver = NULL;
r = sd_device_get_sysattr_value(device, "driver", &driver);
r = device_get_sysattr_safe_string(device, "driver", &driver);
if (r < 0 && r != -ENOENT)
return log_device_debug_errno(device, r,
"sd-device: Failed to read driver: %m");
@@ -2261,7 +2268,7 @@ _public_ int sd_device_has_current_tag(sd_device *device, const char *tag) {
return set_contains(device->current_tags, tag);
}
_public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **ret_value) {
_public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **ret) {
const char *value;
int r;
@@ -2276,8 +2283,8 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co
if (!value)
return -ENOENT;
if (ret_value)
*ret_value = value;
if (ret)
*ret = value;
return 0;
}
@@ -2608,11 +2615,24 @@ cache_result:
return device_get_cached_sysattr_value(device, sysattr, ret_value, ret_size);
}
_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value) {
return sd_device_get_sysattr_value_with_size(device, sysattr, ret_value, NULL);
_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret) {
return sd_device_get_sysattr_value_with_size(device, sysattr, ret, NULL);
}
int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value) {
int device_get_sysattr_streq(sd_device *device, const char *sysattr, const char *expected) {
const char *value;
int r;
assert(expected);
r = sd_device_get_sysattr_value(device, sysattr, &value);
if (r < 0)
return r;
return streq(value, expected);
}
int device_get_sysattr_safe_string(sd_device *device, const char *sysattr, const char **ret) {
const char *value;
int r;
@@ -2620,73 +2640,72 @@ int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_valu
if (r < 0)
return r;
int v;
r = safe_atoi(value, &v);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
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_value)
*ret_value = v;
/* We return "true" if the value is positive. */
return v > 0;
if (ret)
*ret = value;
return 0;
}
int device_get_sysattr_unsigned_full(sd_device *device, const char *sysattr, unsigned base, unsigned *ret_value) {
const char *value;
int r;
#define DEFINE_DEVICE_GET_SYSATTR_PARSE(name, type, parser) \
int device_get_sysattr_##name(sd_device *device, const char *sysattr, type *ret) { \
const char *value; \
int r; \
\
r = sd_device_get_sysattr_value(device, sysattr, &value); \
if (r < 0) \
return r; \
\
type v; \
r = parser(value, &v); \
if (r < 0) \
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr); \
\
if (ret) \
*ret = v; \
/* We return "true" if the value is positive. */ \
return v > 0; \
}
r = sd_device_get_sysattr_value(device, sysattr, &value);
if (r < 0)
return r;
#define DEFINE_DEVICE_GET_SYSATTR_PARSE_BASE(name, type, parser) \
int device_get_sysattr_##name##_full(sd_device *device, const char *sysattr, unsigned base, type *ret) { \
const char *value; \
int r; \
\
r = sd_device_get_sysattr_value(device, sysattr, &value); \
if (r < 0) \
return r; \
\
type v; \
r = parser(value, base, &v); \
if (r < 0) \
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr); \
\
if (ret) \
*ret = v; \
/* We return "true" if the value is positive. */ \
return v > 0; \
}
unsigned v;
r = safe_atou_full(value, base, &v);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
if (ret_value)
*ret_value = v;
/* We return "true" if the value is positive. */
return v > 0;
}
int device_get_sysattr_u32(sd_device *device, const char *sysattr, uint32_t *ret_value) {
const char *value;
int r;
r = sd_device_get_sysattr_value(device, sysattr, &value);
if (r < 0)
return r;
uint32_t v;
r = safe_atou32(value, &v);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
if (ret_value)
*ret_value = v;
/* We return "true" if the value is positive. */
return v > 0;
}
int device_get_sysattr_u64(sd_device *device, const char *sysattr, uint64_t *ret_value) {
const char *value;
int r;
r = sd_device_get_sysattr_value(device, sysattr, &value);
if (r < 0)
return r;
uint64_t v;
r = safe_atou64(value, &v);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse '%s' attribute: %m", sysattr);
if (ret_value)
*ret_value = v;
/* We return "true" if the value is positive. */
return v > 0;
}
DEFINE_DEVICE_GET_SYSATTR_PARSE(int, int, safe_atoi);
DEFINE_DEVICE_GET_SYSATTR_PARSE_BASE(unsigned, unsigned, safe_atou_full);
DEFINE_DEVICE_GET_SYSATTR_PARSE_BASE(u8, uint8_t, safe_atou8_full);
DEFINE_DEVICE_GET_SYSATTR_PARSE_BASE(u16, uint16_t, safe_atou16_full);
DEFINE_DEVICE_GET_SYSATTR_PARSE_BASE(u32, uint32_t, safe_atou32_full);
DEFINE_DEVICE_GET_SYSATTR_PARSE(u64, uint64_t, safe_atou64);
int device_get_sysattr_bool(sd_device *device, const char *sysattr) {
const char *value;
+42
View File
@@ -305,6 +305,48 @@ 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);
}
if (sd_device_get_ifindex(d, &ifindex) >= 0) {
int i;
ASSERT_OK_POSITIVE(device_get_sysattr_int(d, "ifindex", &i));
ASSERT_EQ(i, ifindex);
unsigned u;
ASSERT_OK_POSITIVE(device_get_sysattr_unsigned(d, "ifindex", &u));
ASSERT_EQ(u, (unsigned) ifindex);
uint64_t u64;
ASSERT_OK_POSITIVE(device_get_sysattr_u64(d, "ifindex", &u64));
ASSERT_EQ(u64, (uint64_t) ifindex);
uint32_t u32;
ASSERT_OK_POSITIVE(device_get_sysattr_u32(d, "ifindex", &u32));
ASSERT_EQ(u32, (uint32_t) ifindex);
if (ifindex <= UINT16_MAX) {
uint16_t u16;
ASSERT_OK_POSITIVE(device_get_sysattr_u16(d, "ifindex", &u16));
ASSERT_EQ(u16, (uint16_t) ifindex);
}
if (ifindex <= UINT8_MAX) {
uint8_t u8;
ASSERT_OK_POSITIVE(device_get_sysattr_u8(d, "ifindex", &u8));
ASSERT_EQ(u8, (uint8_t) ifindex);
}
const char *s;
ASSERT_OK(sd_device_get_sysattr_value(d, "ifindex", &s));
ASSERT_OK_POSITIVE(device_get_sysattr_streq(d, "ifindex", s));
ASSERT_OK_ZERO(device_get_sysattr_streq(d, "ifindex", "hoge"));
}
}
static void exclude_problematic_devices(sd_device_enumerator *e) {
+5 -8
View File
@@ -13,6 +13,7 @@
#include "bus-locator.h"
#include "cgroup-util.h"
#include "conf-parser.h"
#include "device-private.h"
#include "device-util.h"
#include "efi-loader.h"
#include "errno-util.h"
@@ -676,21 +677,17 @@ static int manager_count_external_displays(Manager *m) {
continue;
/* Ignore ports that are not enabled */
const char *enabled;
r = sd_device_get_sysattr_value(d, "enabled", &enabled);
if (r == -ENOENT)
r = device_get_sysattr_streq(d, "enabled", "enabled");
if (IN_SET(r, 0, -ENOENT))
continue;
if (r < 0)
return r;
if (!streq(enabled, "enabled"))
continue;
/* We count any connector which is not explicitly "disconnected" as connected. */
const char *status = NULL;
r = sd_device_get_sysattr_value(d, "status", &status);
r = device_get_sysattr_streq(d, "status", "disconnected");
if (r < 0 && r != -ENOENT)
return r;
if (!streq_ptr(status, "disconnected"))
if (r <= 0)
n++;
}
+3 -2
View File
@@ -4,6 +4,7 @@
#include "alloc-util.h"
#include "device-enumerator-private.h"
#include "device-private.h"
#include "device-util.h"
#include "glyph-util.h"
#include "path-util.h"
@@ -61,8 +62,8 @@ static int show_sysfs_one(
is_master = sd_device_has_current_tag(dev_list[*i_dev], "master-of-seat") > 0;
if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0)
(void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name);
if (device_get_sysattr_safe_string(dev_list[*i_dev], "name", &name) < 0)
(void) device_get_sysattr_safe_string(dev_list[*i_dev], "id", &name);
/* Look if there's more coming after this */
for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) {
+8 -6
View File
@@ -12,6 +12,7 @@
#include "bus-util.h"
#include "bus-wait-for-jobs.h"
#include "chase.h"
#include "device-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "escape.h"
@@ -840,7 +841,7 @@ static int find_loop_device(const char *backing_file, sd_device **ret) {
FOREACH_DEVICE(e, dev) {
const char *s;
r = sd_device_get_sysattr_value(dev, "loop/backing_file", &s);
r = device_get_sysattr_safe_string(dev, "loop/backing_file", &s);
if (r < 0) {
log_device_debug_errno(dev, r, "Failed to read \"loop/backing_file\" sysattr, ignoring: %m");
continue;
@@ -1227,7 +1228,6 @@ static int acquire_description(sd_device *d) {
}
static int acquire_removable(sd_device *d) {
const char *v;
int r;
assert(d);
@@ -1237,8 +1237,13 @@ static int acquire_removable(sd_device *d) {
return 0;
for (;;) {
if (sd_device_get_sysattr_value(d, "removable", &v) >= 0)
r = device_get_sysattr_bool(d, "removable");
if (r == 0)
return 0; /* not a removable device */
if (r > 0)
break;
if (r != -ENOENT)
return log_device_debug_errno(d, r, "Failed to read 'removable' sysattr: %m");
r = sd_device_get_parent(d, &d);
if (r == -ENODEV)
@@ -1251,9 +1256,6 @@ static int acquire_removable(sd_device *d) {
return r;
}
if (parse_boolean(v) <= 0)
return 0;
log_debug("Discovered removable device.");
if (arg_action == ACTION_DEFAULT) {
+4 -8
View File
@@ -23,6 +23,7 @@
#include "alloc-util.h"
#include "arphrd-util.h"
#include "bitfield.h"
#include "device-private.h"
#include "device-util.h"
#include "dns-domain.h"
#include "errno-util.h"
@@ -66,7 +67,6 @@
#include "networkd-wifi.h"
#include "networkd-wwan-bus.h"
#include "ordered-set.h"
#include "parse-util.h"
#include "set.h"
#include "socket-util.h"
#include "string-table.h"
@@ -1334,13 +1334,9 @@ static int link_get_network(Link *link, Network **ret) {
continue;
if (network->match.ifname && link->dev) {
uint8_t name_assign_type = NET_NAME_UNKNOWN;
const char *attr;
if (sd_device_get_sysattr_value(link->dev, "name_assign_type", &attr) >= 0)
(void) safe_atou8(attr, &name_assign_type);
warn = name_assign_type == NET_NAME_ENUM;
uint8_t name_assign_type;
if (device_get_sysattr_u8(link->dev, "name_assign_type", &name_assign_type) >= 0)
warn = name_assign_type == NET_NAME_ENUM;
}
log_link_full(link, warn ? LOG_WARNING : LOG_DEBUG,
+2 -1
View File
@@ -3,6 +3,7 @@
#include "sd-netlink.h"
#include "device-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "hashmap.h"
@@ -282,7 +283,7 @@ int link_set_sr_iov_ifindices(Link *link) {
/* This may return -EINVAL or -ENODEV, instead of -ENOENT, if the device has been removed or is being
* removed. Let's ignore the error codes here. */
r = sd_device_get_sysattr_value(link->dev, "dev_port", &dev_port);
r = device_get_sysattr_safe_string(link->dev, "dev_port", &dev_port);
if (ERRNO_IS_NEG_DEVICE_ABSENT(r) || r == -EINVAL)
return 0;
if (r < 0)
+2 -1
View File
@@ -10,6 +10,7 @@
#include "sd-device.h"
#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "escape.h"
@@ -82,7 +83,7 @@ static int find_device(
return log_full_errno(ERRNO_IS_DEVICE_ABSENT(r) ? LOG_DEBUG : LOG_ERR, r,
"Failed to open device '%s': %m", sysname);
r = sd_device_get_sysattr_value(device, "name", &name);
r = device_get_sysattr_safe_string(device, "name", &name);
if (r < 0)
return log_device_debug_errno(device, r, "Device has no name, ignoring: %m");
+7 -8
View File
@@ -43,7 +43,7 @@ static int device_is_power_sink(sd_device *device) {
FOREACH_DEVICE(e, d) {
const char *val;
r = sd_device_get_sysattr_value(d, "power_role", &val);
r = device_get_sysattr_safe_string(d, "power_role", &val);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(d, r, "Failed to read 'power_role' sysfs attribute, ignoring: %m");
@@ -75,11 +75,10 @@ static bool battery_is_discharging(sd_device *d) {
assert(d);
r = sd_device_get_sysattr_value(d, "scope", &val);
if (r < 0) {
if (r != -ENOENT)
log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
} else if (streq(val, "Device")) {
r = device_get_sysattr_streq(d, "scope", "Device");
if (r < 0 && r != -ENOENT)
log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
if (r > 0) {
log_device_debug(d, "The power supply is a device battery, ignoring device.");
return false;
}
@@ -93,7 +92,7 @@ static bool battery_is_discharging(sd_device *d) {
}
/* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */
r = sd_device_get_sysattr_value(d, "status", &val);
r = device_get_sysattr_safe_string(d, "status", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m");
return true;
@@ -130,7 +129,7 @@ int on_ac_power(void) {
* https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */
const char *val;
r = sd_device_get_sysattr_value(d, "type", &val);
r = device_get_sysattr_safe_string(d, "type", &val);
if (r < 0) {
log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring device: %m");
continue;
+2 -1
View File
@@ -15,6 +15,7 @@
#include "alloc-util.h"
#include "blockdev-util.h"
#include "data-fd-util.h"
#include "device-private.h"
#include "device-util.h"
#include "devnum-util.h"
#include "dissect-image.h"
@@ -1027,7 +1028,7 @@ int loop_device_open(
#endif
nr = info.lo_number;
if (sd_device_get_sysattr_value(dev, "loop/backing_file", &s) >= 0) {
if (device_get_sysattr_safe_string(dev, "loop/backing_file", &s) >= 0) {
backing_file = strdup(s);
if (!backing_file)
return -ENOMEM;
+2 -2
View File
@@ -178,7 +178,7 @@ int device_get_sysattr_bool_filtered(sd_device *device, const char *sysattr) {
return device_get_sysattr_bool(device, sysattr);
}
int device_get_sysattr_value_filtered(sd_device *device, const char *sysattr, const char **ret_value) {
int device_get_sysattr_safe_string_filtered(sd_device *device, const char *sysattr, const char **ret_value) {
int r;
r = naming_sysattr_allowed(device, sysattr);
@@ -187,5 +187,5 @@ int device_get_sysattr_value_filtered(sd_device *device, const char *sysattr, co
if (r == 0)
return -ENOENT;
return sd_device_get_sysattr_value(device, sysattr, ret_value);
return device_get_sysattr_safe_string(device, sysattr, ret_value);
}
+1 -1
View File
@@ -104,4 +104,4 @@ DECLARE_STRING_TABLE_LOOKUP(alternative_names_policy, NamePolicy);
int device_get_sysattr_int_filtered(sd_device *device, const char *sysattr, int *ret_value);
int device_get_sysattr_unsigned_filtered(sd_device *device, const char *sysattr, unsigned *ret_value);
int device_get_sysattr_bool_filtered(sd_device *device, const char *sysattr);
int device_get_sysattr_value_filtered(sd_device *device, const char *sysattr, const char **ret_value);
int device_get_sysattr_safe_string_filtered(sd_device *device, const char *sysattr, const char **ret_value);
+4 -25
View File
@@ -5,6 +5,7 @@
#include "alloc-util.h"
#include "conf-parser.h"
#include "device-private.h"
#include "device-util.h"
#include "ether-addr-util.h"
#include "netif-sriov.h"
@@ -267,28 +268,11 @@ int sr_iov_set_netlink_message(SRIOV *sr_iov, SRIOVAttribute attr, sd_netlink_me
}
int sr_iov_get_num_vfs(sd_device *device, uint32_t *ret) {
const char *str;
uint32_t n;
int r;
assert(device);
assert(ret);
r = sd_device_get_sysattr_value(device, "device/sriov_numvfs", &str);
if (r < 0)
return r;
r = safe_atou32(str, &n);
if (r < 0)
return r;
*ret = n;
return 0;
return device_get_sysattr_u32(device, "device/sriov_numvfs", ret);
}
int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_iov_by_section) {
char val[DECIMAL_STR_MAX(uint32_t)];
const char *str;
int r;
assert(device);
@@ -327,14 +311,9 @@ int sr_iov_set_num_vfs(sd_device *device, uint32_t num_vfs, OrderedHashmap *sr_i
* maximum allowed number of VFs from the sriov_totalvfs sysattr. Note that the sysattr
* currently exists only for PCI drivers. Hence, ignore -ENOENT.
* TODO: netdevsim provides the information in debugfs. */
r = sd_device_get_sysattr_value(device, "device/sriov_totalvfs", &str);
uint32_t max_num_vfs;
r = device_get_sysattr_u32(device, "device/sriov_totalvfs", &max_num_vfs);
if (r >= 0) {
uint32_t max_num_vfs;
r = safe_atou32(str, &max_num_vfs);
if (r < 0)
return log_device_debug_errno(device, r, "Failed to parse device/sriov_totalvfs sysfs attribute '%s': %m", str);
if (num_vfs > max_num_vfs)
return log_device_debug_errno(device, SYNTHETIC_ERRNO(ERANGE),
"Specified number of virtual functions is out of range. "
+3 -9
View File
@@ -5,6 +5,7 @@
#include "alloc-util.h"
#include "battery-capacity.h"
#include "battery-util.h"
#include "device-private.h"
#include "device-util.h"
#include "extract-word.h"
#include "fd-util.h"
@@ -368,20 +369,13 @@ int battery_trip_point_alarm_exists(void) {
return log_debug_errno(r, "Failed to initialize battery enumerator: %m");
FOREACH_DEVICE(e, dev) {
const char *alarm_attr;
int has_alarm;
has_battery = true;
r = sd_device_get_sysattr_value(dev, "alarm", &alarm_attr);
int has_alarm;
r = device_get_sysattr_int(dev, "alarm", &has_alarm);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read battery alarm attribute: %m");
r = safe_atoi(alarm_attr, &has_alarm);
if (r < 0)
return log_device_debug_errno(dev, r,
"Failed to parse battery alarm attribute '%s': %m",
alarm_attr);
if (has_alarm <= 0)
return false;
}
+4 -4
View File
@@ -71,8 +71,8 @@ int sd_device_get_syspath(sd_device *device, const char **ret);
int sd_device_get_subsystem(sd_device *device, const char **ret);
int sd_device_get_driver_subsystem(sd_device *device, const char **ret);
int sd_device_get_devtype(sd_device *device, const char **ret);
int sd_device_get_devnum(sd_device *device, dev_t *devnum);
int sd_device_get_ifindex(sd_device *device, int *ifindex);
int sd_device_get_devnum(sd_device *device, dev_t *ret);
int sd_device_get_ifindex(sd_device *device, int *ret);
int sd_device_get_driver(sd_device *device, const char **ret);
int sd_device_get_devpath(sd_device *device, const char **ret);
int sd_device_get_devname(sd_device *device, const char **ret);
@@ -102,10 +102,10 @@ sd_device* sd_device_get_child_next(sd_device *device, const char **ret_suffix);
int sd_device_has_tag(sd_device *device, const char *tag);
int sd_device_has_current_tag(sd_device *device, const char *tag);
int sd_device_get_property_value(sd_device *device, const char *key, const char **value);
int sd_device_get_property_value(sd_device *device, const char *key, const char **ret);
int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret);
int sd_device_get_sysattr_value_with_size(sd_device *device, const char *sysattr, const char **ret_value, size_t *ret_size);
int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret_value);
int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **ret);
int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value);
int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4);
+24 -1
View File
@@ -1547,6 +1547,18 @@ TEST(string_is_safe) {
ASSERT_FALSE(string_is_safe("a\"b", STRING_ASCII));
ASSERT_FALSE(string_is_safe("a*b", STRING_ASCII));
/* STRING_ALLOW_NEWLINES: newlines allowed, quotes/globs still rejected. */
ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("hello world", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("\n", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("a\nb", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("foo\n", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("\nfoo", STRING_ALLOW_NEWLINES));
ASSERT_TRUE(string_is_safe("foo\nbar", STRING_ALLOW_NEWLINES));
ASSERT_FALSE(string_is_safe("foo\\nbar", STRING_ALLOW_NEWLINES)); /* literal backslash, not newline, rejected */
ASSERT_FALSE(string_is_safe("\"", STRING_ALLOW_NEWLINES)); /* quotes still rejected */
ASSERT_FALSE(string_is_safe("*", STRING_ALLOW_NEWLINES)); /* globs still rejected */
/* STRING_ALLOW_BACKSLASHES: backslashes allowed, quotes/globs still rejected. */
ASSERT_TRUE(string_is_safe("hello", STRING_ALLOW_BACKSLASHES));
ASSERT_TRUE(string_is_safe("hello world", STRING_ALLOW_BACKSLASHES));
@@ -1555,6 +1567,7 @@ TEST(string_is_safe) {
ASSERT_TRUE(string_is_safe("foo\\", STRING_ALLOW_BACKSLASHES));
ASSERT_TRUE(string_is_safe("\\foo", STRING_ALLOW_BACKSLASHES));
ASSERT_TRUE(string_is_safe("foo\\nbar", STRING_ALLOW_BACKSLASHES)); /* literal backslash, not newline */
ASSERT_FALSE(string_is_safe("foo\nbar", STRING_ALLOW_BACKSLASHES)); /* newline still rejected */
ASSERT_FALSE(string_is_safe("\"", STRING_ALLOW_BACKSLASHES)); /* quotes still rejected */
ASSERT_FALSE(string_is_safe("*", STRING_ALLOW_BACKSLASHES)); /* globs still rejected */
@@ -1565,6 +1578,7 @@ TEST(string_is_safe) {
ASSERT_TRUE(string_is_safe("'", STRING_ALLOW_QUOTES));
ASSERT_TRUE(string_is_safe("hello\"world", STRING_ALLOW_QUOTES));
ASSERT_TRUE(string_is_safe("it's", STRING_ALLOW_QUOTES));
ASSERT_FALSE(string_is_safe("a\nb", STRING_ALLOW_QUOTES)); /* newline still rejected */
ASSERT_FALSE(string_is_safe("a\\b", STRING_ALLOW_QUOTES)); /* backslashes still rejected */
ASSERT_FALSE(string_is_safe("*", STRING_ALLOW_QUOTES)); /* globs still rejected */
@@ -1577,6 +1591,7 @@ TEST(string_is_safe) {
ASSERT_TRUE(string_is_safe("foo*bar", STRING_ALLOW_GLOBS));
ASSERT_TRUE(string_is_safe("foo?bar", STRING_ALLOW_GLOBS));
ASSERT_TRUE(string_is_safe("foo[bar", STRING_ALLOW_GLOBS));
ASSERT_FALSE(string_is_safe("foo\nbar", STRING_ALLOW_GLOBS)); /* newline still rejected */
ASSERT_FALSE(string_is_safe("\"", STRING_ALLOW_GLOBS)); /* quotes still rejected */
ASSERT_FALSE(string_is_safe("a\\b", STRING_ALLOW_GLOBS)); /* backslashes still rejected */
@@ -1618,10 +1633,18 @@ TEST(string_is_safe) {
ASSERT_TRUE(string_is_safe("foo\"bar", STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES));
/* All allow flags combined: only baseline (control chars, invalid UTF-8) and STRING_FILENAME apply. */
StringSafeFlags all = STRING_ALLOW_EMPTY | STRING_ASCII | STRING_ALLOW_BACKSLASHES | STRING_ALLOW_QUOTES | STRING_ALLOW_GLOBS | STRING_FILENAME;
StringSafeFlags all =
STRING_ASCII |
STRING_ALLOW_EMPTY |
STRING_ALLOW_NEWLINES |
STRING_ALLOW_BACKSLASHES |
STRING_ALLOW_QUOTES |
STRING_ALLOW_GLOBS |
STRING_FILENAME;
ASSERT_TRUE(string_is_safe("hello.txt", all));
ASSERT_TRUE(string_is_safe("foo-bar_baz.conf", all));
ASSERT_TRUE(string_is_safe("a", all));
ASSERT_TRUE(string_is_safe("foo\nbar", all)); /* newline allowed */
ASSERT_TRUE(string_is_safe("foo\\bar", all)); /* backslash allowed */
ASSERT_TRUE(string_is_safe("foo\"bar", all)); /* quote allowed */
ASSERT_TRUE(string_is_safe("foo'bar", all)); /* quote allowed */
+7 -11
View File
@@ -6,10 +6,10 @@
#include "sd-hwdb.h"
#include "alloc-util.h"
#include "device-private.h"
#include "device-util.h"
#include "hwdb-util.h"
#include "options.h"
#include "parse-util.h"
#include "string-util.h"
#include "udev-builtin.h"
@@ -48,20 +48,16 @@ int udev_builtin_hwdb_lookup(
}
static const char* modalias_usb(sd_device *dev, char *s, size_t size) {
const char *v, *p, *n = NULL;
uint16_t vn, pn;
const char *n = NULL;
uint16_t v, p;
if (sd_device_get_sysattr_value(dev, "idVendor", &v) < 0)
if (device_get_sysattr_u16_full(dev, "idVendor", 16, &v) < 0)
return NULL;
if (sd_device_get_sysattr_value(dev, "idProduct", &p) < 0)
if (device_get_sysattr_u16_full(dev, "idProduct", 16, &p) < 0)
return NULL;
if (safe_atoux16(v, &vn) < 0)
return NULL;
if (safe_atoux16(p, &pn) < 0)
return NULL;
(void) sd_device_get_sysattr_value(dev, "product", &n);
(void) device_get_sysattr_safe_string(dev, "product", &n);
(void) snprintf(s, size, "usb:v%04Xp%04X:%s", vn, pn, strempty(n));
(void) snprintf(s, size, "usb:v%04Xp%04X:%s", v, p, strempty(n));
return s;
}
+9 -13
View File
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <linux/input.h>
#include "device-private.h"
#include "device-util.h"
#include "fd-util.h"
#include "parse-util.h"
@@ -85,7 +86,7 @@ static void get_cap_mask(
unsigned long val;
int r;
if (sd_device_get_sysattr_value(pdev, attr, &v) < 0)
if (device_get_sysattr_safe_string(pdev, attr, &v) < 0)
v = "";
xsprintf(text, "%s", v);
@@ -130,17 +131,14 @@ static void get_cap_mask(
}
static struct input_id get_input_id(sd_device *dev) {
const char *v;
struct input_id id = {};
if (sd_device_get_sysattr_value(dev, "id/bustype", &v) >= 0)
(void) safe_atoux16(v, &id.bustype);
if (sd_device_get_sysattr_value(dev, "id/vendor", &v) >= 0)
(void) safe_atoux16(v, &id.vendor);
if (sd_device_get_sysattr_value(dev, "id/product", &v) >= 0)
(void) safe_atoux16(v, &id.product);
if (sd_device_get_sysattr_value(dev, "id/version", &v) >= 0)
(void) safe_atoux16(v, &id.version);
assert(dev);
(void) device_get_sysattr_u16_full(dev, "id/bustype", 16, &id.bustype);
(void) device_get_sysattr_u16_full(dev, "id/vendor", 16, &id.vendor);
(void) device_get_sysattr_u16_full(dev, "id/product", 16, &id.product);
(void) device_get_sysattr_u16_full(dev, "id/version", 16, &id.version);
return id;
}
@@ -386,9 +384,7 @@ static int builtin_input_id(UdevEvent *event, int argc, char *argv[]) {
/* walk up the parental chain until we find the real input device; the
* argument is very likely a subdevice of this, like eventN */
for (pdev = dev; pdev; ) {
const char *s;
if (sd_device_get_sysattr_value(pdev, "capabilities/ev", &s) >= 0)
if (sd_device_get_sysattr_value(pdev, "capabilities/ev", /* ret= */ NULL) >= 0)
break;
if (sd_device_get_parent_with_subsystem_devtype(pdev, "input", NULL, &pdev) >= 0)
+2 -1
View File
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include "device-private.h"
#include "device-util.h"
#include "errno-util.h"
#include "fd-util.h"
@@ -32,7 +33,7 @@ static int install_force_release(sd_device *dev, const unsigned *release, unsign
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get serio parent: %m");
r = sd_device_get_sysattr_value(atkbd, "force_release", &cur);
r = device_get_sysattr_safe_string(atkbd, "force_release", &cur);
if (r < 0)
return log_device_error_errno(atkbd, r, "Failed to get force-release attribute: %m");
+22 -36
View File
@@ -22,7 +22,6 @@
#include "device-private.h"
#include "device-util.h"
#include "dirent-util.h"
#include "escape.h"
#include "ether-addr-util.h"
#include "fd-util.h"
#include "fileio.h"
@@ -32,17 +31,10 @@
#include "stdio-util.h"
#include "string-util.h"
#include "udev-builtin.h"
#include "utf8.h"
#define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
#define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
static int log_invalid_device_attr(sd_device *dev, const char *attr, const char *value) {
_cleanup_free_ char *escaped = cescape(value);
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Invalid %s value '%s'.", attr, strnull(escaped));
}
static int device_get_parent_skip_virtio(sd_device *dev, sd_device **ret) {
int r;
@@ -183,7 +175,7 @@ static int get_port_specifier(sd_device *dev, char **ret) {
assert(ret);
/* First, try to use the kernel provided front panel port name for multiple port PCI device. */
r = device_get_sysattr_value_filtered(dev, "phys_port_name", &phys_port_name);
r = device_get_sysattr_safe_string_filtered(dev, "phys_port_name", &phys_port_name);
if (r >= 0 && !isempty(phys_port_name)) {
if (naming_scheme_has(NAMING_SR_IOV_R)) {
int vf_id = -1;
@@ -201,9 +193,6 @@ static int get_port_specifier(sd_device *dev, char **ret) {
}
}
if (!utf8_is_valid(phys_port_name) || string_has_cc(phys_port_name, /* ok= */ NULL))
return log_invalid_device_attr(dev, "phys_port_name", phys_port_name);
/* Otherwise, use phys_port_name as is. */
buf = strjoin("n", phys_port_name);
if (!buf)
@@ -260,7 +249,7 @@ static int pci_get_onboard_index(sd_device *dev, unsigned *ret) {
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Naming scheme does not allow onboard index==0.");
if (!is_valid_onboard_index(idx))
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENOENT),
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Not a valid onboard index: %u", idx);
*ret = idx;
@@ -304,13 +293,10 @@ static int names_pci_onboard_label(UdevEvent *event, sd_device *pci_dev, const c
assert(prefix);
/* retrieve on-board label from firmware */
r = device_get_sysattr_value_filtered(pci_dev, "label", &label);
r = device_get_sysattr_safe_string_filtered(pci_dev, "label", &label);
if (r < 0)
return log_device_debug_errno(pci_dev, r, "Failed to get PCI onboard label: %m");
if (!utf8_is_valid(label) || string_has_cc(label, /* ok= */ NULL))
return log_invalid_device_attr(dev, "label", label);
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%s%s",
naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
@@ -360,7 +346,7 @@ static bool is_pci_bridge(sd_device *dev) {
assert(dev);
if (device_get_sysattr_value_filtered(dev, "modalias", &v) < 0)
if (device_get_sysattr_safe_string_filtered(dev, "modalias", &v) < 0)
return false;
if (!startswith(v, "pci:"))
@@ -402,14 +388,14 @@ static int parse_hotplug_slot_from_function_id(sd_device *dev, int slots_dirfd,
return 0;
}
if (device_get_sysattr_value_filtered(dev, "function_id", &attr) < 0) {
if (device_get_sysattr_safe_string_filtered(dev, "function_id", &attr) < 0) {
*ret = 0;
return 0;
}
r = safe_atou64(attr, &function_id);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to parse function_id, ignoring: %s", attr);
return log_device_debug_errno(dev, r, "Failed to parse function_id, ignoring: '%s'", attr);
if (function_id <= 0 || function_id > UINT32_MAX)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
@@ -421,7 +407,7 @@ static int parse_hotplug_slot_from_function_id(sd_device *dev, int slots_dirfd,
"PCI slot path is too long, ignoring.");
if (faccessat(slots_dirfd, filename, F_OK, 0) < 0)
return log_device_debug_errno(dev, errno, "Cannot access %s under pci slots, ignoring: %m", filename);
return log_device_debug_errno(dev, errno, "Cannot access '%s' under pci slots, ignoring: %m", filename);
*ret = (uint32_t) function_id;
return 1; /* Found. We should ignore domain part. */
@@ -465,7 +451,7 @@ static int pci_get_hotplug_slot_from_address(
if (!path)
return log_oom_debug();
if (device_get_sysattr_value_filtered(pci, path, &address) < 0)
if (device_get_sysattr_safe_string_filtered(pci, path, &address) < 0)
continue;
/* match slot address with device by stripping the function */
@@ -544,7 +530,7 @@ static int get_device_firmware_node_sun(sd_device *dev, uint32_t *ret) {
assert(dev);
assert(ret);
r = device_get_sysattr_value_filtered(dev, "firmware_node/sun", &attr);
r = device_get_sysattr_safe_string_filtered(dev, "firmware_node/sun", &attr);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read firmware_node/sun, ignoring: %m");
@@ -721,10 +707,11 @@ static int names_vio(UdevEvent *event, const char *prefix) {
if (r != 8)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"VIO bus ID and slot ID have invalid length: %s", s);
"VIO bus ID and slot ID have invalid length: '%s'", s);
if (!in_charset(s, HEXDIGITS))
return log_invalid_device_attr(dev, "VIO bus ID and slot ID", s);
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"VIO bus ID and slot ID contain invalid characters: '%s'", s);
/* Parse only slot ID (the last 4 hexdigits). */
r = safe_atou_full(s + 4, 16, &slotid);
@@ -780,7 +767,8 @@ static int names_platform(UdevEvent *event, const char *prefix) {
return -EOPNOTSUPP;
if (!in_charset(vendor, validchars))
return log_invalid_device_attr(dev, "platform vendor", vendor);
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Platform vendor contains invalid characters: '%s'", vendor);
ascii_strlower(vendor);
@@ -876,7 +864,7 @@ static int names_devicetree_alias_prefix(UdevEvent *event, const char *prefix, c
if (!alias_index)
continue;
if (device_get_sysattr_value_filtered(aliases_dev, alias, &alias_path) < 0)
if (device_get_sysattr_safe_string_filtered(aliases_dev, alias, &alias_path) < 0)
continue;
if (!path_equal(ofnode_path, alias_path))
@@ -890,14 +878,14 @@ static int names_devicetree_alias_prefix(UdevEvent *event, const char *prefix, c
r = safe_atou(alias_index, &i);
if (r < 0)
return log_device_debug_errno(dev, r,
"Could not get index of alias %s: %m", alias);
"Could not get index of alias '%s': %m", alias);
conflict = alias_prefix;
}
/* ...but make sure we don't have an alias conflict */
if (i == 0 && device_get_sysattr_value_filtered(aliases_dev, conflict, NULL) >= 0)
if (i == 0 && device_get_sysattr_safe_string_filtered(aliases_dev, conflict, NULL) >= 0)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
"DeviceTree alias conflict: %s and %s both exist.",
"DeviceTree alias conflict: '%s' and '%s' both exist.",
alias_prefix, alias_prefix_0);
char str[ALTIFNAMSIZ];
@@ -1133,7 +1121,7 @@ static int names_ccw(UdevEvent *event, const char *prefix) {
*/
bus_id_len = strlen(bus_id);
if (!IN_SET(bus_id_len, 8, 9))
return log_device_debug_errno(cdev, SYNTHETIC_ERRNO(EINVAL), "Invalid bus_id: %s", bus_id);
return log_device_debug_errno(cdev, SYNTHETIC_ERRNO(EINVAL), "Invalid bus_id: '%s'", bus_id);
/* Strip leading zeros from the bus id for aesthetic purposes. This
* keeps the ccw names stable, yet much shorter in general case of
@@ -1208,7 +1196,7 @@ static int names_mac(UdevEvent *event, const char *prefix) {
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"addr_assign_type=%u, MAC address is not permanent.", assign_type);
r = device_get_sysattr_value_filtered(dev, "address", &s);
r = device_get_sysattr_safe_string_filtered(dev, "address", &s);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to read 'address' attribute: %m");
@@ -1253,14 +1241,12 @@ static int names_netdevsim(UdevEvent *event, const char *prefix) {
if (r < 0)
return log_device_debug_errno(netdevsimdev, r, "Failed to get device sysnum: %m");
r = device_get_sysattr_value_filtered(dev, "phys_port_name", &phys_port_name);
r = device_get_sysattr_safe_string_filtered(dev, "phys_port_name", &phys_port_name);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get 'phys_port_name' attribute: %m");
if (isempty(phys_port_name))
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EOPNOTSUPP),
"The 'phys_port_name' attribute is empty.");
if (!utf8_is_valid(phys_port_name) || string_has_cc(phys_port_name, /* ok= */ NULL))
return log_invalid_device_attr(dev, "phys_port_name", phys_port_name);
char str[ALTIFNAMSIZ];
if (snprintf_ok(str, sizeof str, "%si%un%s", prefix, addr, phys_port_name))
@@ -1295,7 +1281,7 @@ static int names_xen(UdevEvent *event, const char *prefix) {
p = startswith(vif, "vif-");
if (!p)
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid vif name: %s.", vif);
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid vif name: '%s'.", vif);
r = safe_atou_full(p, SAFE_ATO_REFUSE_PLUS_MINUS | SAFE_ATO_REFUSE_LEADING_ZERO |
SAFE_ATO_REFUSE_LEADING_WHITESPACE | 10, &id);
+16 -22
View File
@@ -108,7 +108,7 @@ static sd_device* handle_scsi_fibre_channel(sd_device *parent, char **path) {
return NULL;
if (sd_device_new_from_subsystem_sysname(&fcdev, "fc_transport", sysname) < 0)
return NULL;
if (sd_device_get_sysattr_value(fcdev, "port_name", &port) < 0)
if (device_get_sysattr_safe_string(fcdev, "port_name", &port) < 0)
return NULL;
format_lun_number(parent, &lun);
@@ -133,7 +133,7 @@ static sd_device* handle_scsi_sas_wide_port(sd_device *parent, char **path) {
return NULL;
if (sd_device_new_from_subsystem_sysname(&sasdev, "sas_device", sysname) < 0)
return NULL;
if (sd_device_get_sysattr_value(sasdev, "sas_address", &sas_address) < 0)
if (device_get_sysattr_safe_string(sasdev, "sas_address", &sas_address) < 0)
return NULL;
format_lun_number(parent, &lun);
@@ -175,7 +175,7 @@ static sd_device* handle_scsi_sas(sd_device *parent, char **path) {
return handle_scsi_sas_wide_port(parent, path);
/* Get connected phy */
if (sd_device_get_sysattr_value(target_sasdev, "phy_identifier", &phy_id) < 0)
if (device_get_sysattr_safe_string(target_sasdev, "phy_identifier", &phy_id) < 0)
return NULL;
/* The port's parent is either hba or expander */
@@ -187,7 +187,7 @@ static sd_device* handle_scsi_sas(sd_device *parent, char **path) {
/* Get expander device */
if (sd_device_new_from_subsystem_sysname(&expander_sasdev, "sas_device", sysname) >= 0) {
/* Get expander's address */
if (sd_device_get_sysattr_value(expander_sasdev, "sas_address", &sas_address) < 0)
if (device_get_sysattr_safe_string(expander_sasdev, "sas_address", &sas_address) < 0)
return NULL;
}
@@ -224,7 +224,7 @@ static sd_device* handle_scsi_iscsi(sd_device *parent, char **path) {
if (sd_device_new_from_subsystem_sysname(&sessiondev, "iscsi_session", sysname) < 0)
return NULL;
if (sd_device_get_sysattr_value(sessiondev, "targetname", &target) < 0)
if (device_get_sysattr_safe_string(sessiondev, "targetname", &target) < 0)
return NULL;
if (sd_device_get_sysnum(transportdev, &sysnum) < 0)
@@ -233,9 +233,9 @@ static sd_device* handle_scsi_iscsi(sd_device *parent, char **path) {
if (sd_device_new_from_subsystem_sysname(&conndev, "iscsi_connection", connname) < 0)
return NULL;
if (sd_device_get_sysattr_value(conndev, "persistent_address", &addr) < 0)
if (device_get_sysattr_safe_string(conndev, "persistent_address", &addr) < 0)
return NULL;
if (sd_device_get_sysattr_value(conndev, "persistent_port", &port) < 0)
if (device_get_sysattr_safe_string(conndev, "persistent_port", &port) < 0)
return NULL;
format_lun_number(parent, &lun);
@@ -268,7 +268,7 @@ static sd_device* handle_scsi_ata(sd_device *parent, char **path, char **compat_
if (sd_device_new_from_subsystem_sysname(&atadev, "ata_port", sysname) < 0)
return NULL;
if (sd_device_get_sysattr_value(atadev, "port_no", &port_no) < 0)
if (device_get_sysattr_safe_string(atadev, "port_no", &port_no) < 0)
return NULL;
if (bus != 0)
@@ -375,7 +375,7 @@ static sd_device* handle_scsi_hyperv(sd_device *parent, char **path, size_t guid
if (sd_device_get_parent(hostdev, &vmbusdev) < 0)
return NULL;
if (sd_device_get_sysattr_value(vmbusdev, "device_id", &guid_str) < 0)
if (device_get_sysattr_safe_string(vmbusdev, "device_id", &guid_str) < 0)
return NULL;
if (strlen(guid_str) < guid_str_len || guid_str[0] != '{' || guid_str[guid_str_len-1] != '}')
@@ -403,7 +403,7 @@ static sd_device* handle_scsi(sd_device *parent, char **path, char **compat_path
return parent;
/* firewire */
if (sd_device_get_sysattr_value(parent, "ieee1394_id", &id) >= 0) {
if (device_get_sysattr_safe_string(parent, "ieee1394_id", &id) >= 0) {
path_prepend(path, "ieee1394-0x%s", id);
*supported_parent = true;
return skip_subsystem(parent, "scsi");
@@ -472,18 +472,13 @@ static void handle_scsi_tape(sd_device *dev, char **path) {
static int get_usb_revision(sd_device *dev) {
uint8_t protocol;
const char *s;
int r;
assert(dev);
/* Returns usb revision 1, 2, or 3. */
r = sd_device_get_sysattr_value(dev, "bDeviceProtocol", &s);
if (r < 0)
return r;
r = safe_atou8_full(s, 16, &protocol);
r = device_get_sysattr_u8_full(dev, "bDeviceProtocol", 16, &protocol);
if (r < 0)
return r;
@@ -491,11 +486,10 @@ static int get_usb_revision(sd_device *dev) {
case USB_HUB_PR_HS_NO_TT: /* Full speed hub (USB1) or Hi-speed hub without TT (USB2) */
/* See speed_show() in drivers/usb/core/sysfs.c of the kernel. */
r = sd_device_get_sysattr_value(dev, "speed", &s);
r = device_get_sysattr_streq(dev, "speed", "480");
if (r < 0)
return r;
if (streq(s, "480"))
if (r > 0)
return 2;
return 1;
@@ -570,8 +564,8 @@ static sd_device* handle_ap(sd_device *parent, char **path) {
assert(parent);
assert(path);
if (sd_device_get_sysattr_value(parent, "type", &type) >= 0 &&
sd_device_get_sysattr_value(parent, "ap_functions", &func) >= 0)
if (device_get_sysattr_safe_string(parent, "type", &type) >= 0 &&
device_get_sysattr_safe_string(parent, "ap_functions", &func) >= 0)
path_prepend(path, "ap-%s-%s", type, func);
else {
const char *sysname;
@@ -787,7 +781,7 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
} else if (device_in_subsystem(parent, "nvme", "nvme-subsystem") > 0) {
const char *nsid;
if (sd_device_get_sysattr_value(dev, "nsid", &nsid) >= 0) {
if (device_get_sysattr_safe_string(dev, "nsid", &nsid) >= 0) {
path_prepend(&path, "nvme-%s", nsid);
if (compat_path)
path_prepend(&compat_path, "nvme-%s", nsid);
+74 -118
View File
@@ -11,120 +11,78 @@
#include <unistd.h>
#include "device-nodes.h"
#include "device-private.h"
#include "device-util.h"
#include "fd-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "strxcpyx.h"
#include "udev-builtin.h"
#include "udev-util.h"
static void set_usb_iftype(char *to, int if_class_num, size_t len) {
const char *type = "generic";
assert(to);
assert(len > 0);
static const char* set_usb_iftype(unsigned if_class_num) {
switch (if_class_num) {
case 1:
type = "audio";
break;
case 2: /* CDC-Control */
break;
case 3:
type = "hid";
break;
case 5: /* Physical */
break;
case 6:
type = "media";
break;
case 7:
type = "printer";
break;
case 8:
type = "storage";
break;
case 9:
type = "hub";
break;
case 0x0a: /* CDC-Data */
break;
case 0x0b: /* Chip/Smart Card */
break;
case 0x0d: /* Content Security */
break;
case 0x01:
return "audio";
case 0x03:
return "hid";
case 0x06:
return "media";
case 0x07:
return "printer";
case 0x08:
return "storage";
case 0x09:
return "hub";
case 0x0e:
type = "video";
break;
case 0xdc: /* Diagnostic Device */
break;
case 0xe0: /* Wireless Controller */
break;
case 0xfe: /* Application-specific */
break;
case 0xff: /* Vendor-specific */
break;
return "video";
default:
/* Other known types:
* 0x02: CDC-Control
* 0x05: Physical
* 0x0a: CDC-Data
* 0x0b: Chip/Smart Card
* 0x0d: Content Security
* 0xdc: Diagnostic Device
* 0xe0: Wireless Controller
* 0xfe: Application-specific
* 0xff: Vendor-specific */
return "generic";
}
strncpy(to, type, len);
to[len-1] = '\0';
}
static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) {
int type_num = 0;
const char *type = "generic";
assert(to);
if (safe_atoi(from, &type_num) >= 0)
switch (type_num) {
case 1: /* RBC devices */
type = "rbc";
break;
case 2:
type = "atapi";
break;
case 3:
type = "tape";
break;
case 4: /* UFI */
type = "floppy";
break;
case 6: /* Transparent SPC-2 devices */
type = "scsi";
break;
}
strscpy(to, len, type);
return type_num;
static const char* set_usb_mass_storage_ifsubtype(uint8_t type_num) {
switch (type_num) {
case 0x01: /* RBC devices */
return "rbc";
case 0x02:
return "atapi";
case 0x03:
return "tape";
case 0x04: /* UFI */
return "floppy";
case 0x06: /* Transparent SPC-2 devices */
return "scsi";
default:
return "generic";
}
}
static void set_scsi_type(char *to, const char *from, size_t len) {
unsigned type_num;
const char *type = "generic";
assert(to);
if (safe_atou(from, &type_num) >= 0)
switch (type_num) {
case 0:
case 0xe:
type = "disk";
break;
case 1:
type = "tape";
break;
case 4:
case 7:
case 0xf:
type = "optical";
break;
case 5:
type = "cd";
break;
}
strscpy(to, len, type);
static const char* set_scsi_type(unsigned type_num) {
switch (type_num) {
case 0x00:
case 0x0e:
return "disk";
case 0x01:
return "tape";
case 0x04:
case 0x07:
case 0x0f:
return "optical";
case 0x05:
return "cd";
default:
return "generic";
}
}
#define USB_DT_DEVICE 0x01
@@ -228,12 +186,12 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
sd_device *dev_interface, *dev_usb, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *syspath, *sysname, *interface_syspath, *vendor_id, *product_id,
*ifnum = NULL, *driver = NULL, *if_class, *if_subclass;
*ifnum = NULL, *driver = NULL, *type_str = NULL;
char *s, model_str[64] = "", model_str_enc[256], serial_str[UDEV_NAME_SIZE] = "",
packed_if_str[UDEV_NAME_SIZE] = "", revision_str[64] = "", type_str[64] = "",
packed_if_str[UDEV_NAME_SIZE] = "", revision_str[64] = "",
instance_str[64] = "", serial[256], vendor_str[64] = "", vendor_str_enc[256];
unsigned if_class_num;
int r, protocol = 0;
unsigned if_class_num, protocol = 0;
int r;
size_t l;
r = sd_device_get_syspath(dev, &syspath);
@@ -259,24 +217,21 @@ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
r = sd_device_get_syspath(dev_interface, &interface_syspath);
if (r < 0)
return log_device_debug_errno(dev_interface, r, "Failed to get syspath: %m");
(void) sd_device_get_sysattr_value(dev_interface, "bInterfaceNumber", &ifnum);
(void) sd_device_get_sysattr_value(dev_interface, "driver", &driver);
(void) device_get_sysattr_safe_string(dev_interface, "bInterfaceNumber", &ifnum);
(void) device_get_sysattr_safe_string(dev_interface, "driver", &driver);
r = sd_device_get_sysattr_value(dev_interface, "bInterfaceClass", &if_class);
r = device_get_sysattr_unsigned_full(dev_interface, "bInterfaceClass", 16, &if_class_num);
if (r < 0)
return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m");
return log_device_debug_errno(dev_interface, r, "Failed to read bInterfaceClass attribute: %m");
r = safe_atou_full(if_class, 16, &if_class_num);
if (r < 0)
return log_device_debug_errno(dev_interface, r, "Failed to parse if_class: %m");
if (if_class_num == 8) {
/* mass storage */
if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0)
protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1);
if (device_get_sysattr_unsigned_full(dev_interface, "bInterfaceSubClass", 16, &protocol) >= 0)
type_str = set_usb_mass_storage_ifsubtype(protocol);
} else
set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1);
type_str = set_usb_iftype(if_class_num);
log_device_debug(dev_interface, "if_class:%u protocol:%i", if_class_num, protocol);
log_device_debug(dev_interface, "if_class:%u protocol:%u", if_class_num, protocol);
/* usb device directory */
r = sd_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device", &dev_usb);
@@ -289,7 +244,7 @@ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
/* mass storage : SCSI or ATAPI */
if (IN_SET(protocol, 6, 2)) {
sd_device *dev_scsi;
const char *scsi_sysname, *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev;
const char *scsi_sysname, *scsi_model, *scsi_vendor, *scsi_rev;
int host, bus, target, lun;
/* get scsi device */
@@ -324,12 +279,13 @@ static int builtin_usb_id(UdevEvent *event, int argc, char *argv[]) {
udev_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1);
udev_replace_chars(model_str, NULL);
r = sd_device_get_sysattr_value(dev_scsi, "type", &scsi_type);
unsigned scsi_type;
r = device_get_sysattr_unsigned(dev_scsi, "type", &scsi_type);
if (r < 0) {
log_device_debug_errno(dev_scsi, r, "Failed to get SCSI type attribute: %m");
goto fallback;
}
set_scsi_type(type_str, scsi_type, sizeof(type_str)-1);
type_str = set_scsi_type(scsi_type);
r = sd_device_get_sysattr_value(dev_scsi, "rev", &scsi_rev);
if (r < 0) {
+2 -2
View File
@@ -162,7 +162,7 @@ static int print_all_attributes(sd_device *device, bool is_parent) {
if (skip_attribute(name))
continue;
r = sd_device_get_sysattr_value(device, name, &value);
r = device_get_sysattr_safe_string(device, name, &value);
if (r >= 0) {
/* skip any values that look like a path */
if (value[0] == '/')
@@ -264,7 +264,7 @@ static int print_all_attributes_in_json(sd_device *device, bool is_parent) {
if (skip_attribute(name))
continue;
r = sd_device_get_sysattr_value(device, name, &value);
r = device_get_sysattr_safe_string(device, name, &value);
if (r >= 0) {
/* skip any values that look like a path */
if (value[0] == '/')