1 ext4: fix use-after-free in dx_release()
3 From: Sahitya Tummala <stummala@codeaurora.org>
5 The buffer_head (frames[0].bh) and it's corresping page can be
6 potentially free'd once brelse() is done inside the for loop
7 but before the for loop exits in dx_release(). It can be free'd
8 in another context, when the page cache is flushed via
9 drop_caches_sysctl_handler(). This results into below data abort
10 when accessing info->indirect_levels in dx_release().
12 Unable to handle kernel paging request at virtual address ffffffc17ac3e01e
15 ext4_htree_fill_tree+0x2d4/0x300
16 ext4_readdir+0x244/0x6f8
17 iterate_dir+0xbc/0x160
18 SyS_getdents64+0x94/0x174
20 Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
21 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
22 Reviewed-by: Andreas Dilger <adilger@dilger.ca>
26 add a comment in dx_release()
28 fs/ext4/namei.c | 5 ++++-
29 1 file changed, 4 insertions(+), 1 deletion(-)
31 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
32 index 980166a..5d9ffa8 100644
35 @@ -871,12 +871,15 @@ static void dx_release(struct dx_frame *frames)
37 struct dx_root_info *info;
39 + unsigned int indirect_levels;
41 if (frames[0].bh == NULL)
44 info = &((struct dx_root *)frames[0].bh->b_data)->info;
45 - for (i = 0; i <= info->indirect_levels; i++) {
46 + /* save local copy, "info" may be freed after brelse() */
47 + indirect_levels = info->indirect_levels;
48 + for (i = 0; i <= indirect_levels; i++) {
49 if (frames[i].bh == NULL)
53 Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.
54 Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.