1 From 1c2d14212b15a60300a2d4f6364753e87394c521 Mon Sep 17 00:00:00 2001
2 From: Jan Kara <jack@suse.cz>
3 Date: Tue, 29 Jan 2019 17:17:24 +0100
4 Subject: ext2: Fix underflow in ext2_max_size()
6 From: Jan Kara <jack@suse.cz>
8 commit 1c2d14212b15a60300a2d4f6364753e87394c521 upstream.
10 When ext2 filesystem is created with 64k block size, ext2_max_size()
11 will return value less than 0. Also, we cannot write any file in this fs
12 since the sb->maxbytes is less than 0. The core of the problem is that
13 the size of block index tree for such large block size is more than
14 i_blocks can carry. So fix the computation to count with this
17 File size limits computed with the new function for the full range of
18 possible block sizes look like:
29 CC: stable@vger.kernel.org
30 Reported-by: yangerkun <yangerkun@huawei.com>
31 Signed-off-by: Jan Kara <jack@suse.cz>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35 fs/ext2/super.c | 41 ++++++++++++++++++++++++++---------------
36 1 file changed, 26 insertions(+), 15 deletions(-)
40 @@ -757,7 +757,8 @@ static loff_t ext2_max_size(int bits)
42 loff_t res = EXT2_NDIR_BLOCKS;
45 + unsigned int upper_limit;
46 + unsigned int ppb = 1 << (bits-2);
48 /* This is calculated to be the largest file size for a
49 * dense, file such that the total number of
50 @@ -771,24 +772,34 @@ static loff_t ext2_max_size(int bits)
51 /* total blocks in file system block size */
52 upper_limit >>= (bits - 9);
55 - /* indirect blocks */
57 - /* double indirect blocks */
58 - meta_blocks += 1 + (1LL << (bits-2));
59 - /* tripple indirect blocks */
60 - meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
62 - upper_limit -= meta_blocks;
63 - upper_limit <<= bits;
65 + /* Compute how many blocks we can address by block tree */
66 res += 1LL << (bits-2);
67 res += 1LL << (2*(bits-2));
68 res += 1LL << (3*(bits-2));
69 + /* Does block tree limit file size? */
70 + if (res < upper_limit)
74 + /* How many metadata blocks are needed for addressing upper_limit? */
75 + upper_limit -= EXT2_NDIR_BLOCKS;
76 + /* indirect blocks */
79 + /* double indirect blocks */
80 + if (upper_limit < ppb * ppb) {
81 + meta_blocks += 1 + DIV_ROUND_UP(upper_limit, ppb);
85 + meta_blocks += 1 + ppb;
86 + upper_limit -= ppb * ppb;
87 + /* tripple indirect blocks for the rest */
88 + meta_blocks += 1 + DIV_ROUND_UP(upper_limit, ppb) +
89 + DIV_ROUND_UP(upper_limit, ppb*ppb);
93 - if (res > upper_limit)
96 if (res > MAX_LFS_FILESIZE)
97 res = MAX_LFS_FILESIZE;