Commit 13fe54a
committed
libext: fix heap overflow in ext_readlink and overflow in ext_readdir from a crafted ext4 image
Two memory-safety bugs reachable by mounting an attacker-supplied ext4 image
(a realistic threat for attached volumes / multi-tenant hosts). In a unikernel
these are kernel heap corruption.
1. ext_readlink() heap buffer overflow (critical). For a slow symlink it did:
void *buf = malloc(block_size); // e.g. 4096 bytes
ext_internal_read(fs, ref, offset, buf, fsize, &read_count);
where fsize is ext4_inode_get_size() - the raw 64-bit inode size read
straight off disk, fully attacker-controlled and NOT clamped. A crafted
symlink inode with i_size = 1 MiB (and i_blocks != 0 so the slow-symlink
branch is taken) makes ext_internal_read write ~1 MiB into the 4 KiB heap
buffer -> heap corruption / potential RCE, reached by readlink() or any path
traversal through the link. A symlink target is at most one block (bounded
by PATH_MAX), so clamp: reject fsize > block_size, guard uio_offset >= fsize
(which would otherwise underflow fsize-offset), and check malloc().
2. ext_readdir() d_name overflow. memcpy(dir->d_name, name, name_length) with
name_length from ext4_dir_en_get_name_len(), which on an old-rev image
(rev0, minor<5) folds in name_length_high and returns up to block_size-8
(~4088) while d_name is 256 bytes. Clamp name_length to sizeof(d_name)-1.
Verified with debugfs-crafted images: a normal symlink still reads back
correctly (tst-ext-readlink), and a symlink inode with i_size=1MiB now returns
EINVAL instead of overflowing the heap. Added tst-ext-readlink as a regression.1 parent d55b448 commit 13fe54a
3 files changed
Lines changed: 58 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
635 | 635 | | |
636 | 636 | | |
637 | 637 | | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
638 | 645 | | |
639 | 646 | | |
640 | 647 | | |
| |||
1341 | 1348 | | |
1342 | 1349 | | |
1343 | 1350 | | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
1344 | 1365 | | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
1345 | 1369 | | |
1346 | 1370 | | |
1347 | 1371 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
| 118 | + | |
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
0 commit comments