Commit 5c39ec96 authored by Marc A. Smith's avatar Marc A. Smith

"always replace spaces in symlinks, unless string_escape=none" -- This fix is…

"always replace spaces in symlinks, unless string_escape=none" -- This fix is backported from systemd which resolves an issue with whitespace characters in symbolic links created by [e]udev. See systemd/systemd issue # 4833 and systemd/systemd pull request # 4837 for details. This issue was originally observed with some NVMe devices when using eudev 3.2.x and this fix resolves eudev issue # 148.
parent 6b5db4f2
......@@ -241,7 +241,7 @@ int util_replace_whitespace(const char *str, char *to, size_t len)
to[j++] = str[i++];
}
to[j] = '\0';
return 0;
return j;
}
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
......
......@@ -62,7 +62,9 @@ void udev_event_unref(struct udev_event *event) {
free(event);
}
size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) {
size_t udev_event_apply_format(struct udev_event *event,
const char *src, char *dest, size_t size,
bool replace_whitespace) {
struct udev_device *dev = event->dev;
enum subst_type {
SUBST_UNKNOWN,
......@@ -117,8 +119,10 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
for (;;) {
enum subst_type type = SUBST_UNKNOWN;
char attrbuf[UTIL_PATH_SIZE];
char *attr = NULL;
char attrbuf[UTIL_PATH_SIZE], sbuf[UTIL_PATH_SIZE];
char *attr = NULL, *_s;
size_t _l;
bool replws = replace_whitespace;
while (from[0] != '\0') {
if (from[0] == '$') {
......@@ -187,6 +191,19 @@ subst:
attr = NULL;
}
/* result subst handles space as field separator */
if (type == SUBST_RESULT)
replws = false;
if (replws) {
/* store dest string ptr and remaining len */
_s = s;
_l = l;
/* temporarily use sbuf */
s = &sbuf;
l = UTIL_PATH_SIZE;
}
switch (type) {
case SUBST_DEVPATH:
l = strpcpy(&s, l, udev_device_get_devpath(dev));
......@@ -367,6 +384,20 @@ subst:
log_error("unknown substitution type=%i", type);
break;
}
/* replace whitespace in sbuf and copy to dest */
if (replws) {
size_t tmplen = UTIL_PATH_SIZE - l;
/* restore s and l to dest string values */
s = _s;
l = _l;
/* copy ws-replaced value to s */
tmplen = util_replace_whitespace(sbuf, s, MIN(tmplen, l));
l -= tmplen;
s += tmplen;
}
}
out:
......@@ -1026,7 +1057,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
if (builtin_cmd < UDEV_BUILTIN_MAX) {
char command[UTIL_PATH_SIZE];
udev_event_apply_format(event, cmd, command, sizeof(command));
udev_event_apply_format(event, cmd, command, sizeof(command), false);
udev_builtin_run(event->dev, builtin_cmd, command, false);
} else {
char program[UTIL_PATH_SIZE];
......@@ -1037,7 +1068,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
sleep(event->exec_delay);
}
udev_event_apply_format(event, cmd, program, sizeof(program));
udev_event_apply_format(event, cmd, program, sizeof(program), false);
envp = udev_device_get_properties_envp(event->dev);
udev_event_spawn(event, timeout_usec, timeout_warn_usec, program, envp, sigmask, NULL, 0);
}
......
This diff is collapsed.
......@@ -81,7 +81,9 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
/* udev-event.c */
struct udev_event *udev_event_new(struct udev_device *dev);
void udev_event_unref(struct udev_event *event);
size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size);
size_t udev_event_apply_format(struct udev_event *event,
const char *src, char *dest, size_t size,
bool replace_whitespace);
int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
char *result, size_t maxsize, int read_value);
int udev_event_spawn(struct udev_event *event,
......
......@@ -153,7 +153,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) {
char program[UTIL_PATH_SIZE];
udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program));
udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false);
printf("run: '%s'\n", program);
}
out:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment