]>
Commit | Line | Data |
---|---|---|
ec71c73b GKH |
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() | |
5 | ||
6 | From: Jan Kara <jack@suse.cz> | |
7 | ||
8 | commit 1c2d14212b15a60300a2d4f6364753e87394c521 upstream. | |
9 | ||
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 | |
15 | possibility. | |
16 | ||
17 | File size limits computed with the new function for the full range of | |
18 | possible block sizes look like: | |
19 | ||
20 | bits file_size | |
21 | 10 17247252480 | |
22 | 11 275415851008 | |
23 | 12 2196873666560 | |
24 | 13 2197948973056 | |
25 | 14 2198486220800 | |
26 | 15 2198754754560 | |
27 | 16 2198888906752 | |
28 | ||
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> | |
33 | ||
34 | --- | |
35 | fs/ext2/super.c | 41 ++++++++++++++++++++++++++--------------- | |
36 | 1 file changed, 26 insertions(+), 15 deletions(-) | |
37 | ||
38 | --- a/fs/ext2/super.c | |
39 | +++ b/fs/ext2/super.c | |
40 | @@ -761,7 +761,8 @@ static loff_t ext2_max_size(int bits) | |
41 | { | |
42 | loff_t res = EXT2_NDIR_BLOCKS; | |
43 | int meta_blocks; | |
44 | - loff_t upper_limit; | |
45 | + unsigned int upper_limit; | |
46 | + unsigned int ppb = 1 << (bits-2); | |
47 | ||
48 | /* This is calculated to be the largest file size for a | |
49 | * dense, file such that the total number of | |
50 | @@ -775,24 +776,34 @@ static loff_t ext2_max_size(int bits) | |
51 | /* total blocks in file system block size */ | |
52 | upper_limit >>= (bits - 9); | |
53 | ||
54 | - | |
55 | - /* indirect blocks */ | |
56 | - meta_blocks = 1; | |
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))); | |
61 | - | |
62 | - upper_limit -= meta_blocks; | |
63 | - upper_limit <<= bits; | |
64 | - | |
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) | |
71 | + goto check_lfs; | |
72 | + | |
73 | + res = upper_limit; | |
74 | + /* How many metadata blocks are needed for addressing upper_limit? */ | |
75 | + upper_limit -= EXT2_NDIR_BLOCKS; | |
76 | + /* indirect blocks */ | |
77 | + meta_blocks = 1; | |
78 | + upper_limit -= ppb; | |
79 | + /* double indirect blocks */ | |
80 | + if (upper_limit < ppb * ppb) { | |
81 | + meta_blocks += 1 + DIV_ROUND_UP(upper_limit, ppb); | |
82 | + res -= meta_blocks; | |
83 | + goto check_lfs; | |
84 | + } | |
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); | |
90 | + res -= meta_blocks; | |
91 | +check_lfs: | |
92 | res <<= bits; | |
93 | - if (res > upper_limit) | |
94 | - res = upper_limit; | |
95 | - | |
96 | if (res > MAX_LFS_FILESIZE) | |
97 | res = MAX_LFS_FILESIZE; | |
98 |