From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, nhuck15@gmail.com, qemu-devel@nongnu.org,
ppandit@redhat.com
Subject: [PATCH 1/2] vvfat: Check that updated filenames are valid
Date: Tue, 23 Jun 2020 19:55:33 +0200 [thread overview]
Message-ID: <20200623175534.38286-2-kwolf@redhat.com> (raw)
In-Reply-To: <20200623175534.38286-1-kwolf@redhat.com>
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 <nhuck15@gmail.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vvfat.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/block/vvfat.c b/block/vvfat.c
index c65a98e3ee..2fab371258 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -520,6 +520,25 @@ static void set_begin_of_direntry(direntry_t* direntry, uint32_t begin)
direntry->begin_hi = cpu_to_le16((begin >> 16) & 0xffff);
}
+static bool valid_filename(const unsigned char *name)
+{
+ unsigned char c;
+ if (!strcmp((const char*)name, ".") || !strcmp((const char*)name, "..")) {
+ return false;
+ }
+ for (; (c = *name); name++) {
+ if (!((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ c > 127 ||
+ strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != 0))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
static uint8_t to_valid_short_char(gunichar c)
{
c = g_unichar_toupper(c);
@@ -2098,6 +2117,10 @@ DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i))
}
lfn.checksum = 0x100; /* cannot use long name twice */
+ if (!valid_filename(lfn.name)) {
+ fprintf(stderr, "Invalid file name\n");
+ goto fail;
+ }
if (path_len + 1 + lfn.len >= PATH_MAX) {
fprintf(stderr, "Name too long: %s/%s\n", path, lfn.name);
goto fail;
--
2.25.4
next prev parent reply other threads:[~2020-06-23 17:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-23 17:55 [PATCH 0/2] vvfat: Two small patches Kevin Wolf
2020-06-23 17:55 ` Kevin Wolf [this message]
2020-06-23 18:21 ` [PATCH 1/2] vvfat: Check that updated filenames are valid Eric Blake
2020-06-24 12:36 ` Kevin Wolf
2020-06-23 17:55 ` [PATCH 2/2] vvfat: Fix array_remove_slice() Kevin Wolf
2020-06-23 18:30 ` Eric Blake
2020-06-24 12:42 ` Kevin Wolf
2020-06-23 18:32 ` [PATCH 0/2] vvfat: Two small patches no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200623175534.38286-2-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=nhuck15@gmail.com \
--cc=ppandit@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.