1 ext4: zero out the unused memory region in the extent tree block
3 From: Sriram Rajagopalan <sriramr@arista.com>
5 This commit zeroes out the unused memory region in the buffer_head
6 corresponding to the extent metablock after writing the extent header
7 and the corresponding extent node entries.
9 This is done to prevent random uninitialized data from getting into
10 the filesystem when the extent block is synced.
12 This fixes CVE-2019-11833.
14 Signed-off-by: Sriram Rajagopalan <sriramr@arista.com>
15 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
18 fs/ext4/extents.c | 17 +++++++++++++++--
19 1 file changed, 15 insertions(+), 2 deletions(-)
21 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
22 index 0f89f5190cd7..f2c62e2a0c98 100644
23 --- a/fs/ext4/extents.c
24 +++ b/fs/ext4/extents.c
25 @@ -1035,6 +1035,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
27 ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */
29 + size_t ext_size = 0;
31 /* make decision: where to split? */
32 /* FIXME: now decision is simplest: at current extent */
33 @@ -1126,6 +1127,10 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
34 le16_add_cpu(&neh->eh_entries, m);
37 + /* zero out unused area in the extent block */
38 + ext_size = sizeof(struct ext4_extent_header) +
39 + sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries);
40 + memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size);
41 ext4_extent_block_csum_set(inode, neh);
42 set_buffer_uptodate(bh);
44 @@ -1205,6 +1210,11 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
45 sizeof(struct ext4_extent_idx) * m);
46 le16_add_cpu(&neh->eh_entries, m);
48 + /* zero out unused area in the extent block */
49 + ext_size = sizeof(struct ext4_extent_header) +
50 + (sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries));
51 + memset(bh->b_data + ext_size, 0,
52 + inode->i_sb->s_blocksize - ext_size);
53 ext4_extent_block_csum_set(inode, neh);
54 set_buffer_uptodate(bh);
56 @@ -1270,6 +1280,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
57 ext4_fsblk_t newblock, goal = 0;
58 struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
60 + size_t ext_size = 0;
62 /* Try to prepend new index to old one */
64 @@ -1295,9 +1306,11 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
68 + ext_size = sizeof(EXT4_I(inode)->i_data);
69 /* move top-level index/leaf into new block */
70 - memmove(bh->b_data, EXT4_I(inode)->i_data,
71 - sizeof(EXT4_I(inode)->i_data));
72 + memmove(bh->b_data, EXT4_I(inode)->i_data, ext_size);
73 + /* zero out unused area in the extent block */
74 + memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size);
76 /* set size of new block */
77 neh = ext_block_hdr(bh);