Skip to content

Commit c79e243

Browse files
committed
vvfat: Check that updated filenames are valid
FAT allows only a restricted set of characters in file names, and for some of the illegal characters, it's actually important that we catch them: If filenames can contain '/', the guest can construct filenames containing "../" and escape from the assigned vvfat directory. The same problem could arise if ".." was ever accepted as a literal filename. Fix this by adding a check that all filenames are valid in check_directory_consistency(). Reported-by: Nathan Huckleberry <[email protected]> Signed-off-by: Kevin Wolf <[email protected]> Message-Id: <[email protected]> Reviewed-by: Eric Blake <[email protected]> Signed-off-by: Kevin Wolf <[email protected]>
1 parent f10802d commit c79e243

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

block/vvfat.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,12 +520,31 @@ static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
520520
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
521521
}
522522

523+
static bool valid_filename(const unsigned char *name)
524+
{
525+
unsigned char c;
526+
if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) {
527+
return false;
528+
}
529+
for (; (c = *name); name++) {
530+
if (!((c >= '0' && c <= '9') ||
531+
(c >= 'A' && c <= 'Z') ||
532+
(c >= 'a' && c <= 'z') ||
533+
c > 127 ||
534+
strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
535+
{
536+
return false;
537+
}
538+
}
539+
return true;
540+
}
541+
523542
static uint8_t to_valid_short_char(gunichar c)
524543
{
525544
c = g_unichar_toupper(c);
526545
if ((c >= '0' && c <= '9') ||
527546
(c >= 'A' && c <= 'Z') ||
528-
strchr("$%'-_@~`!(){}^#&", c) != 0) {
547+
strchr("$%'-_@~`!(){}^#&", c) != NULL) {
529548
return c;
530549
} else {
531550
return 0;
@@ -2098,6 +2117,10 @@ DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i))
20982117
}
20992118
lfn.checksum = 0x100; /* cannot use long name twice */
21002119

2120+
if (!valid_filename(lfn.name)) {
2121+
fprintf(stderr, "Invalid file name\n");
2122+
goto fail;
2123+
}
21012124
if (path_len + 1 + lfn.len >= PATH_MAX) {
21022125
fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
21032126
goto fail;

0 commit comments

Comments
 (0)