Skip to content

Commit c15bf33

Browse files
LiBaokun96gregkh
authored andcommitted
ext4: fix slab-use-after-free in ext4_es_insert_extent()
commit 768d612 upstream. Yikebaer reported an issue: ================================================================== BUG: KASAN: slab-use-after-free in ext4_es_insert_extent+0xc68/0xcb0 fs/ext4/extents_status.c:894 Read of size 4 at addr ffff888112ecc1a4 by task syz-executor/8438 CPU: 1 PID: 8438 Comm: syz-executor Not tainted 6.5.0-rc5 #1 Call Trace: [...] kasan_report+0xba/0xf0 mm/kasan/report.c:588 ext4_es_insert_extent+0xc68/0xcb0 fs/ext4/extents_status.c:894 ext4_map_blocks+0x92a/0x16f0 fs/ext4/inode.c:680 ext4_alloc_file_blocks.isra.0+0x2df/0xb70 fs/ext4/extents.c:4462 ext4_zero_range fs/ext4/extents.c:4622 [inline] ext4_fallocate+0x251c/0x3ce0 fs/ext4/extents.c:4721 [...] Allocated by task 8438: [...] kmem_cache_zalloc include/linux/slab.h:693 [inline] __es_alloc_extent fs/ext4/extents_status.c:469 [inline] ext4_es_insert_extent+0x672/0xcb0 fs/ext4/extents_status.c:873 ext4_map_blocks+0x92a/0x16f0 fs/ext4/inode.c:680 ext4_alloc_file_blocks.isra.0+0x2df/0xb70 fs/ext4/extents.c:4462 ext4_zero_range fs/ext4/extents.c:4622 [inline] ext4_fallocate+0x251c/0x3ce0 fs/ext4/extents.c:4721 [...] Freed by task 8438: [...] kmem_cache_free+0xec/0x490 mm/slub.c:3823 ext4_es_try_to_merge_right fs/ext4/extents_status.c:593 [inline] __es_insert_extent+0x9f4/0x1440 fs/ext4/extents_status.c:802 ext4_es_insert_extent+0x2ca/0xcb0 fs/ext4/extents_status.c:882 ext4_map_blocks+0x92a/0x16f0 fs/ext4/inode.c:680 ext4_alloc_file_blocks.isra.0+0x2df/0xb70 fs/ext4/extents.c:4462 ext4_zero_range fs/ext4/extents.c:4622 [inline] ext4_fallocate+0x251c/0x3ce0 fs/ext4/extents.c:4721 [...] ================================================================== The flow of issue triggering is as follows: 1. remove es raw es es removed es1 |-------------------| -> |----|.......|------| 2. insert es es insert es1 merge with es es1 merge with es and free es1 |----|.......|------| -> |------------|------| -> |-------------------| es merges with newes, then merges with es1, frees es1, then determines if es1->es_len is 0 and triggers a UAF. The code flow is as follows: ext4_es_insert_extent es1 = __es_alloc_extent(true); es2 = __es_alloc_extent(true); __es_remove_extent(inode, lblk, end, NULL, es1) __es_insert_extent(inode, &newes, es1) ---> insert es1 to es tree __es_insert_extent(inode, &newes, es2) ext4_es_try_to_merge_right ext4_es_free_extent(inode, es1) ---> es1 is freed if (es1 && !es1->es_len) // Trigger UAF by determining if es1 is used. We determine whether es1 or es2 is used immediately after calling __es_remove_extent() or __es_insert_extent() to avoid triggering a UAF if es1 or es2 is freed. Reported-by: Yikebaer Aizezi <[email protected]> Closes: https://lore.kernel.org/lkml/CALcu4raD4h9coiyEBL4Bm0zjDwxC2CyPiTwsP3zFuhot6y9Beg@mail.gmail.com Fixes: 2a69c45 ("ext4: using nofail preallocation in ext4_es_insert_extent()") Cc: [email protected] Signed-off-by: Baokun Li <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 05874c6 commit c15bf33

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

fs/ext4/extents_status.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -878,23 +878,29 @@ void ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
878878
err1 = __es_remove_extent(inode, lblk, end, NULL, es1);
879879
if (err1 != 0)
880880
goto error;
881+
/* Free preallocated extent if it didn't get used. */
882+
if (es1) {
883+
if (!es1->es_len)
884+
__es_free_extent(es1);
885+
es1 = NULL;
886+
}
881887

882888
err2 = __es_insert_extent(inode, &newes, es2);
883889
if (err2 == -ENOMEM && !ext4_es_must_keep(&newes))
884890
err2 = 0;
885891
if (err2 != 0)
886892
goto error;
893+
/* Free preallocated extent if it didn't get used. */
894+
if (es2) {
895+
if (!es2->es_len)
896+
__es_free_extent(es2);
897+
es2 = NULL;
898+
}
887899

888900
if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) &&
889901
(status & EXTENT_STATUS_WRITTEN ||
890902
status & EXTENT_STATUS_UNWRITTEN))
891903
__revise_pending(inode, lblk, len);
892-
893-
/* es is pre-allocated but not used, free it. */
894-
if (es1 && !es1->es_len)
895-
__es_free_extent(es1);
896-
if (es2 && !es2->es_len)
897-
__es_free_extent(es2);
898904
error:
899905
write_unlock(&EXT4_I(inode)->i_es_lock);
900906
if (err1 || err2)
@@ -1491,8 +1497,12 @@ void ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
14911497
*/
14921498
write_lock(&EXT4_I(inode)->i_es_lock);
14931499
err = __es_remove_extent(inode, lblk, end, &reserved, es);
1494-
if (es && !es->es_len)
1495-
__es_free_extent(es);
1500+
/* Free preallocated extent if it didn't get used. */
1501+
if (es) {
1502+
if (!es->es_len)
1503+
__es_free_extent(es);
1504+
es = NULL;
1505+
}
14961506
write_unlock(&EXT4_I(inode)->i_es_lock);
14971507
if (err)
14981508
goto retry;
@@ -2047,19 +2057,25 @@ void ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
20472057
err1 = __es_remove_extent(inode, lblk, lblk, NULL, es1);
20482058
if (err1 != 0)
20492059
goto error;
2060+
/* Free preallocated extent if it didn't get used. */
2061+
if (es1) {
2062+
if (!es1->es_len)
2063+
__es_free_extent(es1);
2064+
es1 = NULL;
2065+
}
20502066

20512067
err2 = __es_insert_extent(inode, &newes, es2);
20522068
if (err2 != 0)
20532069
goto error;
2070+
/* Free preallocated extent if it didn't get used. */
2071+
if (es2) {
2072+
if (!es2->es_len)
2073+
__es_free_extent(es2);
2074+
es2 = NULL;
2075+
}
20542076

20552077
if (allocated)
20562078
__insert_pending(inode, lblk);
2057-
2058-
/* es is pre-allocated but not used, free it. */
2059-
if (es1 && !es1->es_len)
2060-
__es_free_extent(es1);
2061-
if (es2 && !es2->es_len)
2062-
__es_free_extent(es2);
20632079
error:
20642080
write_unlock(&EXT4_I(inode)->i_es_lock);
20652081
if (err1 || err2)

0 commit comments

Comments
 (0)