mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-15 05:57:26 +03:00
sd-device,udev: refuse invalid devlink and store in normalized form
This is especially for the case that the path contains "..". Prompted by https://github.com/systemd/systemd/pull/27164#issuecomment-1498863858. This also makes SYMLINK= gracefully handle paths prefixed with "/dev/", and manage devlink paths with path_hash_ops.
This commit is contained in:
parent
733b7bfd79
commit
2c5f119c3c
@ -38,7 +38,7 @@ void device_set_db_persist(sd_device *device);
|
|||||||
void device_set_devlink_priority(sd_device *device, int priority);
|
void device_set_devlink_priority(sd_device *device, int priority);
|
||||||
int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
|
int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
|
||||||
int device_add_devlink(sd_device *device, const char *devlink);
|
int device_add_devlink(sd_device *device, const char *devlink);
|
||||||
void device_remove_devlink(sd_device *device, const char *devlink);
|
int device_remove_devlink(sd_device *device, const char *devlink);
|
||||||
bool device_has_devlink(sd_device *device, const char *devlink);
|
bool device_has_devlink(sd_device *device, const char *devlink);
|
||||||
int device_add_property(sd_device *device, const char *property, const char *value);
|
int device_add_property(sd_device *device, const char *property, const char *value);
|
||||||
int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) _printf_(3, 4);
|
int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) _printf_(3, 4);
|
||||||
|
@ -1473,34 +1473,58 @@ int device_add_tag(sd_device *device, const char *tag, bool both) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *prefix_dev(const char *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
if (path_startswith(p, "/dev/"))
|
||||||
|
return strdup(p);
|
||||||
|
|
||||||
|
return path_join("/dev/", p);
|
||||||
|
}
|
||||||
|
|
||||||
int device_add_devlink(sd_device *device, const char *devlink) {
|
int device_add_devlink(sd_device *device, const char *devlink) {
|
||||||
|
char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
assert(devlink);
|
assert(devlink);
|
||||||
|
|
||||||
r = set_put_strdup(&device->devlinks, devlink);
|
if (!path_is_safe(devlink))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
p = prefix_dev(devlink);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
path_simplify(p);
|
||||||
|
|
||||||
|
r = set_ensure_consume(&device->devlinks, &path_hash_ops_free, p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
device->devlinks_generation++;
|
device->devlinks_generation++;
|
||||||
device->property_devlinks_outdated = true;
|
device->property_devlinks_outdated = true;
|
||||||
|
|
||||||
return 0;
|
return r; /* return 1 when newly added, 0 when already exists */
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_remove_devlink(sd_device *device, const char *devlink) {
|
int device_remove_devlink(sd_device *device, const char *devlink) {
|
||||||
_cleanup_free_ char *s = NULL;
|
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||||
|
|
||||||
assert(device);
|
assert(device);
|
||||||
assert(devlink);
|
assert(devlink);
|
||||||
|
|
||||||
s = set_remove(device->devlinks, devlink);
|
p = prefix_dev(devlink);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
s = set_remove(device->devlinks, p);
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return 0; /* does not exist */
|
||||||
|
|
||||||
device->devlinks_generation++;
|
device->devlinks_generation++;
|
||||||
device->property_devlinks_outdated = true;
|
device->property_devlinks_outdated = true;
|
||||||
|
return 1; /* removed */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool device_has_devlink(sd_device *device, const char *devlink) {
|
bool device_has_devlink(sd_device *device, const char *devlink) {
|
||||||
|
@ -2574,9 +2574,9 @@ static int udev_rule_apply_token_to_event(
|
|||||||
count, token->value);
|
count, token->value);
|
||||||
|
|
||||||
for (const char *p = buf;;) {
|
for (const char *p = buf;;) {
|
||||||
_cleanup_free_ char *word = NULL, *path = NULL;
|
_cleanup_free_ char *path = NULL;
|
||||||
|
|
||||||
r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
|
r = extract_first_word(&p, &path, NULL, EXTRACT_RETAIN_ESCAPE);
|
||||||
if (r == -ENOMEM)
|
if (r == -ENOMEM)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -2586,19 +2586,22 @@ static int udev_rule_apply_token_to_event(
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
path = path_join("/dev/", word);
|
|
||||||
if (!path)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (token->op == OP_REMOVE) {
|
if (token->op == OP_REMOVE) {
|
||||||
device_remove_devlink(dev, path);
|
r = device_remove_devlink(dev, path);
|
||||||
log_event_debug(dev, token, "Dropped SYMLINK '%s'", path);
|
if (r == -ENOMEM)
|
||||||
|
return log_oom();
|
||||||
|
if (r < 0)
|
||||||
|
log_event_warning_errno(dev, token, r, "Failed to remove devlink '%s', ignoring: %m", path);
|
||||||
|
else if (r > 0)
|
||||||
|
log_event_debug(dev, token, "Dropped SYMLINK '%s'", path);
|
||||||
} else {
|
} else {
|
||||||
r = device_add_devlink(dev, path);
|
r = device_add_devlink(dev, path);
|
||||||
|
if (r == -ENOMEM)
|
||||||
|
return log_oom();
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_event_error_errno(dev, token, r, "Failed to add devlink '%s': %m", path);
|
log_event_warning_errno(dev, token, r, "Failed to add devlink '%s', ignoring: %m", path);
|
||||||
|
else if (r > 0)
|
||||||
log_event_debug(dev, token, "Added SYMLINK '%s'", path);
|
log_event_debug(dev, token, "Added SYMLINK '%s'", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -212,13 +212,37 @@ EOF
|
|||||||
{
|
{
|
||||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||||
exp_links => ["boot_disk1", "boot_diskXY1"],
|
exp_links => ["boot_disk1", "boot_diskXY1"],
|
||||||
not_exp_links => ["boot_diskXX1", "hoge"],
|
not_exp_links => ["boot_diskXX1"],
|
||||||
}],
|
}],
|
||||||
rules => <<EOF
|
rules => <<EOF
|
||||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="32", SYMLINK+="boot_diskXX%n"
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="32", SYMLINK+="boot_diskXX%n"
|
||||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="1", SYMLINK+="boot_diskXY%n"
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="1", SYMLINK+="boot_diskXY%n"
|
||||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n", SYMLINK+="hoge"
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
|
||||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK-="hoge"
|
EOF
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "SYMLINK tests",
|
||||||
|
devices => [
|
||||||
|
{
|
||||||
|
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||||
|
exp_links => ["link1", "link2/foo", "link3/aaa/bbb",
|
||||||
|
"default___replace_test/foo_aaa",
|
||||||
|
"string_escape___replace/foo_bbb",
|
||||||
|
"env_with_space",
|
||||||
|
"default/replace/mode_foo__hoge",
|
||||||
|
"replace_env_harder_foo__hoge"],
|
||||||
|
not_exp_links => ["removed", "unsafe/../../path"],
|
||||||
|
}],
|
||||||
|
rules => <<EOF
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="removed"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK-="removed"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="unsafe/../../path"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="link1 link2/foo link3/aaa/bbb"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="default?;;replace%%test/foo'aaa"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", OPTIONS="string_escape=replace", SYMLINK+="string_escape replace/foo%%bbb"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ENV{.HOGE}="env with space", SYMLINK+="%E{.HOGE}"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ENV{.HOGE}="default/replace/mode?foo;;hoge", SYMLINK+="%E{.HOGE}"
|
||||||
|
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", OPTIONS="string_escape=replace", ENV{.HOGE}="replace/env/harder?foo;;hoge", SYMLINK+="%E{.HOGE}"
|
||||||
EOF
|
EOF
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user