#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
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);
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);
}
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");
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++;
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)
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;
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++;