start to enforce plain ascii or valid utf8

No device node or symlink can have other characters as plain
readable ascii or valid utf8. The /dev/disk/by-label/* symlinks
can no longer contain weird stuff read from untrusted sources.

Signed-off-by: Kay Sievers <kay.sievers@suse.de>
This commit is contained in:
Kay Sievers
2005-08-28 15:55:58 +02:00
parent 5b13ecb830
commit 764ce7f2ab
4 changed files with 66 additions and 10 deletions
+19 -1
View File
@@ -1324,7 +1324,25 @@ EOF
devpath => "/block/sda/sda1",
exp_name => "sane",
rules => <<EOF
BUS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/sbin/badprogram)", RESULT="name_ _/sbin/badprogram_", NAME="sane"
BUS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/sbin/badprogram)", RESULT=="name_ _/sbin/badprogram_", NAME="sane"
EOF
},
{
desc => "untrusted string sanitize (don't replace utf8)",
subsys => "block",
devpath => "/block/sda/sda1",
exp_name => "uber",
rules => <<EOF
BUS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xc3\\xbcber" RESULT=="\xc3\xbcber", NAME="uber"
EOF
},
{
desc => "untrusted string sanitize (replace invalid utf8)",
subsys => "block",
devpath => "/block/sda/sda1",
exp_name => "replaced",
rules => <<EOF
BUS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xef\\xe8garbage", RESULT=="[?][?]garbage", NAME="replaced"
EOF
},
{
+18 -3
View File
@@ -362,6 +362,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize,
char *head, *tail, *pos, *cpos, *attr, *rest;
int len;
int i;
int count;
unsigned int next_free_number;
struct sysfs_class_device *class_dev_parent;
enum subst_type {
@@ -544,7 +545,9 @@ found:
i = strlen(temp2);
while (i > 0 && isspace(temp2[i-1]))
temp2[--i] = '\0';
replace_untrusted_chars(temp2);
count = replace_untrusted_chars(temp2);
if (count)
info("%i untrusted character(s) replaced" , count);
strlcat(string, temp2, maxsize);
dbg("substitute sysfs value '%s'", temp2);
break;
@@ -812,9 +815,13 @@ try_parent:
if (rule->program.operation != KEY_OP_NOMATCH)
goto exit;
} else {
int count;
dbg("PROGRAM matches");
remove_trailing_char(result, '\n');
replace_untrusted_chars(result);
count = replace_untrusted_chars(result);
if (count)
info("%i untrusted character(s) replaced" , count);
dbg("result is '%s'", result);
strlcpy(udev->program_result, result, sizeof(udev->program_result));
dbg("PROGRAM returned successful");
@@ -960,6 +967,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s
if (!udev->symlink_final && rule->symlink.operation != KEY_OP_UNSET) {
char temp[PATH_SIZE];
char *pos, *next;
int count;
if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL)
udev->symlink_final = 1;
@@ -969,7 +977,10 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s
}
strlcpy(temp, key_val(rule, &rule->symlink), sizeof(temp));
apply_format(udev, temp, sizeof(temp), class_dev, sysfs_device);
dbg("rule applied, added symlink '%s'", temp);
count = replace_untrusted_chars(temp);
if (count)
info("%i untrusted character(s) replaced" , count);
dbg("rule applied, added symlink(s) '%s'", temp);
/* add multiple symlinks separated by spaces */
pos = temp;
@@ -993,9 +1004,13 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s
/* set name, later rules with name set will be ignored */
if (rule->name.operation != KEY_OP_UNSET) {
int count;
name_set = 1;
strlcpy(udev->name, key_val(rule, &rule->name), sizeof(udev->name));
apply_format(udev, udev->name, sizeof(udev->name), class_dev, sysfs_device);
count = replace_untrusted_chars(udev->name);
if (count)
info("%i untrusted character(s) replaced", count);
info("rule applied, '%s' becomes '%s'", udev->kernel_name, udev->name);
if (udev->type != DEV_NET)
+1 -1
View File
@@ -42,9 +42,9 @@ extern int add_matching_files(struct list_head *name_list, const char *dirname,
/* udev_utils_string.c */
extern int strcmp_pattern(const char *p, const char *s);
extern int string_is_true(const char *str);
extern void replace_untrusted_chars(char *string);
extern void remove_trailing_char(char *path, char c);
extern int utf8_encoded_valid_unichar(const char *str);
extern int replace_untrusted_chars(char *str);
/* udev_utils_file.c */
extern int create_path(const char *path);
+28 -5
View File
@@ -232,12 +232,35 @@ int utf8_encoded_valid_unichar(const char *str)
return len;
}
void replace_untrusted_chars(char *string)
/* replace everything but whitelisted plain ascii and valid utf8 */
int replace_untrusted_chars(char *str)
{
size_t len;
size_t i = 0;
int replaced = 0;
for (len = 0; string[len] != '\0'; len++) {
if (strchr(";,~\\()\'", string[len]))
string[len] = '_';
while (str[i] != '\0') {
int len;
/* valid printable ascii char */
if ((str[i] >= '0' && str[i] <= '9') ||
(str[i] >= 'A' && str[i] <= 'Z') ||
(str[i] >= 'a' && str[i] <= 'z') ||
strchr(" #$%+-./:=?@_", str[i])) {
i++;
continue;
}
/* valid utf8 is accepted */
len = utf8_encoded_valid_unichar(&str[i]);
if (len > 1) {
i += len;
continue;
}
/* everything else is garbage */
str[i] = '_';
i++;
replaced++;
}
return replaced;
}