[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/4] block/vvfat: Avoid out of bounds write in create_long_filena
From: |
Philippe Mathieu-Daudé |
Subject: |
[PATCH 4/4] block/vvfat: Avoid out of bounds write in create_long_filename() |
Date: |
Fri, 30 Apr 2021 18:25:19 +0200 |
The direntry_t::name holds 11 bytes:
typedef struct direntry_t {
uint8_t name[8 + 3];
...
However create_long_filename() writes up to 31 bytes into it:
421 for(i=0;i<26*number_of_entries;i++) {
422 int offset=(i%26);
423 if(offset<10) offset=1+offset;
424 else if(offset<22) offset=14+offset-10;
425 else offset=28+offset-22;
426 entry=array_get(&(s->directory),s->directory.next-1-(i/26));
427 if (i >= 2 * length + 2) {
428 entry->name[offset] = 0xff;
429 } else if (i % 2 == 0) {
430 entry->name[offset] = longname[i / 2] & 0xff;
431 } else {
432 entry->name[offset] = longname[i / 2] >> 8;
433 }
434 }
For example, if i=25, offset=28+25-22=31
Then in lines 428, 430 and 432 the entry->name[] array is written beside
its 11 bytes, as reported by Clang sanitizer:
block/vvfat.c:430:13: runtime error: index 14 out of bounds for type 'uint8_t
[11]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior block/vvfat.c:430:13
in
block/vvfat.c:432:13: runtime error: index 15 out of bounds for type 'uint8_t
[11]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior block/vvfat.c:432:13
in
block/vvfat.c:428:13: runtime error: index 18 out of bounds for type 'uint8_t
[11]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior block/vvfat.c:428:13
in
As I have no idea about what this code does, simply skip the writes if
out of range, since it is not worst than what we have currently (and
my tests using vvfat work identically).
Fixes: de167e416fa ("Virtual VFAT support (Johannes Schindelin)")
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
block/vvfat.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/block/vvfat.c b/block/vvfat.c
index c193a816646..c7162e77d68 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -423,6 +423,9 @@ static direntry_t *create_long_filename(BDRVVVFATState *s,
const char *filename)
if(offset<10) offset=1+offset;
else if(offset<22) offset=14+offset-10;
else offset=28+offset-22;
+ if (offset >= ARRAY_SIZE(entry->name)) {
+ continue;
+ }
entry=array_get(&(s->directory),s->directory.next-1-(i/26));
if (i >= 2 * length + 2) {
entry->name[offset] = 0xff;
--
2.26.3