diff options
-rw-r--r-- | extras/volume_id/vol_id.c | 4 | ||||
-rw-r--r-- | udev.h | 6 | ||||
-rw-r--r-- | udev_rules.c | 21 | ||||
-rw-r--r-- | udev_utils_string.c | 25 | ||||
-rw-r--r-- | udevinfo.c | 2 |
5 files changed, 33 insertions, 25 deletions
diff --git a/extras/volume_id/vol_id.c b/extras/volume_id/vol_id.c index cb1d455891..53b4cfff0b 100644 --- a/extras/volume_id/vol_id.c +++ b/extras/volume_id/vol_id.c @@ -274,9 +274,9 @@ int main(int argc, char *argv[]) } set_str(label_safe, label, sizeof(label_safe)); - replace_untrusted_chars(label_safe); + replace_chars(label_safe, ALLOWED_CHARS_INPUT); set_str(uuid_safe, uuid, sizeof(uuid_safe)); - replace_untrusted_chars(uuid_safe); + replace_chars(uuid_safe, ALLOWED_CHARS_INPUT); switch (print) { case PRINT_EXPORT: @@ -34,6 +34,10 @@ #define NAME_SIZE 256 #define VALUE_SIZE 128 +#define ALLOWED_CHARS "#+-.:=@_%" +#define ALLOWED_CHARS_FILE ALLOWED_CHARS "/" +#define ALLOWED_CHARS_INPUT ALLOWED_CHARS " $/?," + #define DEFAULT_PARTITIONS_COUNT 15 #define UDEV_ALARM_TIMEOUT 180 @@ -149,7 +153,7 @@ extern void remove_trailing_chars(char *path, char c); extern size_t path_encode(char *s, size_t len); extern size_t path_decode(char *s); extern int utf8_encoded_valid_unichar(const char *str); -extern int replace_untrusted_chars(char *str); +extern int replace_chars(char *str, const char *white); /* udev_utils_file.c */ extern int create_path(const char *path); diff --git a/udev_rules.c b/udev_rules.c index edfe3fd94c..526993e21c 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -491,15 +491,15 @@ found: if (value == NULL) break; - /* strip trailing whitespace and replace untrusted characters of sysfs value */ + /* strip trailing whitespace, and replace unwanted characters */ size = strlcpy(temp2, value, sizeof(temp2)); if (size >= sizeof(temp2)) size = sizeof(temp2)-1; while (size > 0 && isspace(temp2[size-1])) temp2[--size] = '\0'; - count = replace_untrusted_chars(temp2); + count = replace_chars(temp2, ALLOWED_CHARS_INPUT); if (count > 0) - info("%i untrusted character(s) replaced" , count); + info("%i character(s) replaced" , count); strlcat(string, temp2, maxsize); dbg("substitute sysfs value '%s'", temp2); } @@ -776,9 +776,9 @@ try_parent: dbg("PROGRAM matches"); remove_trailing_chars(result, '\n'); - count = replace_untrusted_chars(result); + count = replace_chars(result, ALLOWED_CHARS_INPUT); if (count) - info("%i untrusted character(s) replaced" , count); + info("%i character(s) replaced" , count); dbg("result is '%s'", result); strlcpy(udev->program_result, result, sizeof(udev->program_result)); dbg("PROGRAM returned successful"); @@ -959,14 +959,13 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) info("reset symlink list"); name_list_cleanup(&udev->symlink_list); } + /* allow multiple symlinks separated by spaces */ strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp)); udev_rules_apply_format(udev, temp, sizeof(temp)); - count = replace_untrusted_chars(temp); + count = replace_chars(temp, ALLOWED_CHARS_FILE " "); if (count) - info("%i untrusted character(s) replaced" , count); + info("%i character(s) replaced" , count); dbg("rule applied, added symlink(s) '%s'", temp); - - /* add multiple symlinks separated by spaces */ pos = temp; while (isspace(pos[0])) pos++; @@ -995,9 +994,9 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) name_set = 1; strlcpy(udev->name, key_val(rule, &rule->name), sizeof(udev->name)); udev_rules_apply_format(udev, udev->name, sizeof(udev->name)); - count = replace_untrusted_chars(udev->name); + count = replace_chars(udev->name, ALLOWED_CHARS_FILE); if (count) - info("%i untrusted character(s) replaced", count); + info("%i character(s) replaced", count); info("rule applied, '%s' becomes '%s'", udev->dev->kernel, udev->name); if (strcmp(udev->dev->subsystem, "net") != 0) diff --git a/udev_utils_string.c b/udev_utils_string.c index 6f51aef014..e3dc137e63 100644 --- a/udev_utils_string.c +++ b/udev_utils_string.c @@ -216,8 +216,8 @@ int utf8_encoded_valid_unichar(const char *str) return len; } -/* replace everything but whitelisted plain ascii and valid utf8 */ -int replace_untrusted_chars(char *str) +/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ +int replace_chars(char *str, const char *white) { size_t i = 0; int replaced = 0; @@ -225,37 +225,42 @@ int replace_untrusted_chars(char *str) while (str[i] != '\0') { int len; - /* valid printable ascii char */ + /* accept whitelist */ + if (white != NULL && strchr(white, str[i]) != NULL) { + i++; + continue; + } + + /* accept plain ascii char */ if ((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'Z') || - (str[i] >= 'a' && str[i] <= 'z') || - strchr("#$%+-./:=?@_,", str[i])) { + (str[i] >= 'a' && str[i] <= 'z')) { i++; continue; } - /* hex encoding */ + /* accept hex encoding */ if (str[i] == '\\' && str[i+1] == 'x') { i += 2; continue; } - /* valid utf8 is accepted */ + /* accept valid utf8 */ len = utf8_encoded_valid_unichar(&str[i]); if (len > 1) { i += len; continue; } - /* whitespace replaced with ordinary space */ - if (isspace(str[i])) { + /* if space is allowed, replace whitespace with ordinary space */ + if (isspace(str[i]) && strchr(white, ' ') != NULL) { str[i] = ' '; i++; replaced++; continue; } - /* everything else is garbage */ + /* everything else is replaced with '_' */ str[i] = '_'; i++; replaced++; diff --git a/udevinfo.c b/udevinfo.c index f36f240f0a..cda229244d 100644 --- a/udevinfo.c +++ b/udevinfo.c @@ -93,7 +93,7 @@ static void print_all_attributes(const char *devpath, const char *key) continue; } - replace_untrusted_chars(value); + replace_chars(value, ALLOWED_CHARS_INPUT); printf(" %s{%s}==\"%s\"\n", key, dent->d_name, value); } } |