Skip to content

Commit e20a917

Browse files
committed
udev-event: add replace_whitespace param to udev_event_apply_format
If replace_whitespace is true, each substitution value has all its whitespace removed/replaced by util_replace_whitespace (except the SUBST_RESULT substitution - $result{} or %c{} - which handles spaces itself as field separators). All existing callers are updated to pass false, so no functional change is made by this patch. This is needed so the SYMLINK assignment can replace any spaces introduced through variable substitution, becuase the SYMLINK value is a space-separated list of symlinks to create. Any variables that contain spaces will thus unexpectedly change the symlink value from a single symlink to multiple incorrectly-named symlinks. This is used in the next patch, which enables the whitespace replacement for SYMLINK variable substitution.
1 parent a9d99b3 commit e20a917

File tree

4 files changed

+59
-26
lines changed

4 files changed

+59
-26
lines changed

src/udev/udev-event.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ void udev_event_unref(struct udev_event *event) {
7373
free(event);
7474
}
7575

76-
size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) {
76+
size_t udev_event_apply_format(struct udev_event *event,
77+
const char *src, char *dest, size_t size,
78+
bool replace_whitespace) {
7779
struct udev_device *dev = event->dev;
7880
enum subst_type {
7981
SUBST_UNKNOWN,
@@ -130,8 +132,10 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
130132

131133
for (;;) {
132134
enum subst_type type = SUBST_UNKNOWN;
133-
char attrbuf[UTIL_PATH_SIZE];
134-
char *attr = NULL;
135+
char attrbuf[UTIL_PATH_SIZE], sbuf[UTIL_PATH_SIZE];
136+
char *attr = NULL, *_s;
137+
size_t _l;
138+
bool replws = replace_whitespace;
135139

136140
while (from[0] != '\0') {
137141
if (from[0] == '$') {
@@ -200,6 +204,19 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
200204
attr = NULL;
201205
}
202206

207+
/* result subst handles space as field separator */
208+
if (type == SUBST_RESULT)
209+
replws = false;
210+
211+
if (replws) {
212+
/* store dest string ptr and remaining len */
213+
_s = s;
214+
_l = l;
215+
/* temporarily use sbuf */
216+
s = &sbuf;
217+
l = UTIL_PATH_SIZE;
218+
}
219+
203220
switch (type) {
204221
case SUBST_DEVPATH:
205222
l = strpcpy(&s, l, udev_device_get_devpath(dev));
@@ -380,6 +397,20 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
380397
log_error("unknown substitution type=%i", type);
381398
break;
382399
}
400+
401+
/* replace whitespace in sbuf and copy to dest */
402+
if (replws) {
403+
size_t tmplen = UTIL_PATH_SIZE - l;
404+
405+
/* restore s and l to dest string values */
406+
s = _s;
407+
l = _l;
408+
409+
/* copy ws-replaced value to s */
410+
tmplen = util_replace_whitespace(sbuf, s, MIN(tmplen, l));
411+
l -= tmplen;
412+
s += tmplen;
413+
}
383414
}
384415

385416
out:
@@ -927,7 +958,7 @@ void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_
927958
const char *cmd = udev_list_entry_get_name(list_entry);
928959
enum udev_builtin_cmd builtin_cmd = udev_list_entry_get_num(list_entry);
929960

930-
udev_event_apply_format(event, cmd, command, sizeof(command));
961+
udev_event_apply_format(event, cmd, command, sizeof(command), false);
931962

932963
if (builtin_cmd < UDEV_BUILTIN_MAX)
933964
udev_builtin_run(event->dev, builtin_cmd, command, false);

src/udev/udev-rules.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct
16761676
name = rules_str(rules, cur->key.attr_off);
16771677
switch (cur->key.attrsubst) {
16781678
case SB_FORMAT:
1679-
udev_event_apply_format(event, name, nbuf, sizeof(nbuf));
1679+
udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false);
16801680
name = nbuf;
16811681
/* fall through */
16821682
case SB_NONE:
@@ -1838,7 +1838,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
18381838
_cleanup_free_ char *value = NULL;
18391839
size_t len;
18401840

1841-
udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
1841+
udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
18421842
sysctl_normalize(filename);
18431843
if (sysctl_read(filename, &value) < 0)
18441844
goto nomatch;
@@ -1916,7 +1916,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
19161916
struct stat statbuf;
19171917
int match;
19181918

1919-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename));
1919+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename), false);
19201920
if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) {
19211921
if (filename[0] != '/') {
19221922
char tmp[UTIL_PATH_SIZE];
@@ -1942,7 +1942,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
19421942
char result[UTIL_LINE_SIZE];
19431943

19441944
event->program_result = mfree(event->program_result);
1945-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program));
1945+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), program, sizeof(program), false);
19461946
log_debug("PROGRAM '%s' %s:%u",
19471947
program,
19481948
rules_str(rules, rule->rule.filename_off),
@@ -1969,7 +1969,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
19691969
case TK_M_IMPORT_FILE: {
19701970
char import[UTIL_PATH_SIZE];
19711971

1972-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
1972+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
19731973
if (import_file_into_properties(event->dev, import) != 0)
19741974
if (cur->key.op != OP_NOMATCH)
19751975
goto nomatch;
@@ -1978,7 +1978,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
19781978
case TK_M_IMPORT_PROG: {
19791979
char import[UTIL_PATH_SIZE];
19801980

1981-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
1981+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
19821982
log_debug("IMPORT '%s' %s:%u",
19831983
import,
19841984
rules_str(rules, rule->rule.filename_off),
@@ -2009,7 +2009,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
20092009
event->builtin_run |= (1 << cur->key.builtin_cmd);
20102010
}
20112011

2012-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command));
2012+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), command, sizeof(command), false);
20132013
log_debug("IMPORT builtin '%s' %s:%u",
20142014
udev_builtin_name(cur->key.builtin_cmd),
20152015
rules_str(rules, rule->rule.filename_off),
@@ -2077,7 +2077,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
20772077
case TK_M_IMPORT_PARENT: {
20782078
char import[UTIL_PATH_SIZE];
20792079

2080-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import));
2080+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), import, sizeof(import), false);
20812081
if (import_parent_into_properties(event->dev, import) != 0)
20822082
if (cur->key.op != OP_NOMATCH)
20832083
goto nomatch;
@@ -2115,7 +2115,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
21152115
break;
21162116
if (cur->key.op == OP_ASSIGN_FINAL)
21172117
event->owner_final = true;
2118-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner));
2118+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner), false);
21192119
event->owner_set = true;
21202120
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL);
21212121
if (r < 0) {
@@ -2141,7 +2141,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
21412141
break;
21422142
if (cur->key.op == OP_ASSIGN_FINAL)
21432143
event->group_final = true;
2144-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group));
2144+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group), false);
21452145
event->group_set = true;
21462146
r = get_group_creds(&gr, &event->gid);
21472147
if (r < 0) {
@@ -2165,7 +2165,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
21652165

21662166
if (event->mode_final)
21672167
break;
2168-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str));
2168+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), mode_str, sizeof(mode_str), false);
21692169
mode = strtol(mode_str, &endptr, 8);
21702170
if (endptr[0] != '\0') {
21712171
log_error("ignoring invalid mode '%s'", mode_str);
@@ -2222,7 +2222,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
22222222
const char *name, *label;
22232223

22242224
name = rules_str(rules, cur->key.attr_off);
2225-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), label_str, sizeof(label_str));
2225+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), label_str, sizeof(label_str), false);
22262226
if (label_str[0] != '\0')
22272227
label = label_str;
22282228
else
@@ -2256,10 +2256,10 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
22562256
char temp[UTIL_NAME_SIZE];
22572257

22582258
/* append value separated by space */
2259-
udev_event_apply_format(event, value, temp, sizeof(temp));
2259+
udev_event_apply_format(event, value, temp, sizeof(temp), false);
22602260
strscpyl(value_new, sizeof(value_new), value_old, " ", temp, NULL);
22612261
} else
2262-
udev_event_apply_format(event, value, value_new, sizeof(value_new));
2262+
udev_event_apply_format(event, value, value_new, sizeof(value_new), false);
22632263

22642264
udev_device_add_property(event->dev, name, value_new);
22652265
break;
@@ -2268,7 +2268,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
22682268
char tag[UTIL_PATH_SIZE];
22692269
const char *p;
22702270

2271-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag));
2271+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), tag, sizeof(tag), false);
22722272
if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL)
22732273
udev_device_cleanup_tags_list(event->dev);
22742274
for (p = tag; *p != '\0'; p++) {
@@ -2296,7 +2296,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
22962296
break;
22972297
if (cur->key.op == OP_ASSIGN_FINAL)
22982298
event->name_final = true;
2299-
udev_event_apply_format(event, name, name_str, sizeof(name_str));
2299+
udev_event_apply_format(event, name, name_str, sizeof(name_str), false);
23002300
if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
23012301
count = util_replace_chars(name_str, "/");
23022302
if (count > 0)
@@ -2336,7 +2336,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
23362336
udev_device_cleanup_devlinks_list(event->dev);
23372337

23382338
/* allow multiple symlinks separated by spaces */
2339-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp));
2339+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), temp, sizeof(temp), false);
23402340
if (esc == ESCAPE_UNSET)
23412341
count = util_replace_chars(temp, "/ ");
23422342
else if (esc == ESCAPE_REPLACE)
@@ -2376,7 +2376,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
23762376
strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
23772377
attr_subst_subdir(attr, sizeof(attr));
23782378

2379-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
2379+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
23802380
log_debug("ATTR '%s' writing '%s' %s:%u", attr, value,
23812381
rules_str(rules, rule->rule.filename_off),
23822382
rule->rule.filename_line);
@@ -2392,9 +2392,9 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
23922392
char value[UTIL_NAME_SIZE];
23932393
int r;
23942394

2395-
udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename));
2395+
udev_event_apply_format(event, rules_str(rules, cur->key.attr_off), filename, sizeof(filename), false);
23962396
sysctl_normalize(filename);
2397-
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value));
2397+
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), value, sizeof(value), false);
23982398
log_debug("SYSCTL '%s' writing '%s' %s:%u", filename, value,
23992399
rules_str(rules, rule->rule.filename_off), rule->rule.filename_line);
24002400
r = sysctl_write(filename, value);

src/udev/udev.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules);
8080
/* udev-event.c */
8181
struct udev_event *udev_event_new(struct udev_device *dev);
8282
void udev_event_unref(struct udev_event *event);
83-
size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size);
83+
size_t udev_event_apply_format(struct udev_event *event,
84+
const char *src, char *dest, size_t size,
85+
bool replace_whitespace);
8486
int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string,
8587
char *result, size_t maxsize, int read_value);
8688
int udev_event_spawn(struct udev_event *event,

src/udev/udevadm-test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
144144
udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) {
145145
char program[UTIL_PATH_SIZE];
146146

147-
udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program));
147+
udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false);
148148
printf("run: '%s'\n", program);
149149
}
150150
out:

0 commit comments

Comments
 (0)