add patch remove-unused-mode-parameter
[ext4-patch-queue.git] / fix-warnings-about-stack-corruption
blob2059a9583dac5758da94fce8924508dda905f226
1 ext4: fix warning about stack corruption
3 From: Arnd Bergmann <arnd@arndb.de>
5 After commit 62d1034f53e3 ("fortify: use WARN instead of BUG for now"),
6 we get a warning about possible stack overflow from a memcpy that
7 was not strictly bounded to the size of the local variable:
9     inlined from 'ext4_mb_seq_groups_show' at fs/ext4/mballoc.c:2322:2:
10 include/linux/string.h:309:9: error: '__builtin_memcpy': writing between 161 and 1116 bytes into a region of size 160 overflows the destination [-Werror=stringop-overflow=]
12 We actually had a bug here that would have been found by the warning,
13 but it was already fixed last year in commit 30a9d7afe70e ("ext4: fix
14 stack memory corruption with 64k block size").
16 This replaces the fixed-length structure on the stack with a variable-length
17 structure, using the correct upper bound that tells the compiler that
18 everything is really fine here. I also change the loop count to check
19 for the same upper bound for consistency, but the existing code is
20 already correct here.
22 Note that while clang won't allow certain kinds of variable-length arrays
23 in structures, this particular instance is fine, as the array is at the
24 end of the structure, and the size is strictly bounded.
26 Signed-off-by: Arnd Bergmann <arnd@arndb.de>
27 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
28 ---
29  fs/ext4/mballoc.c | 11 ++++++-----
30  1 file changed, 6 insertions(+), 5 deletions(-)
32 diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
33 index 8779893d74e5..5a1052627a81 100644
34 --- a/fs/ext4/mballoc.c
35 +++ b/fs/ext4/mballoc.c
36 @@ -2295,9 +2295,12 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
37         int err, buddy_loaded = 0;
38         struct ext4_buddy e4b;
39         struct ext4_group_info *grinfo;
40 +       unsigned char blocksize_bits = min_t(unsigned char,
41 +                                            sb->s_blocksize_bits,
42 +                                            EXT4_MAX_BLOCK_LOG_SIZE);
43         struct sg {
44                 struct ext4_group_info info;
45 -               ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
46 +               ext4_grpblk_t counters[blocksize_bits + 2];
47         } sg;
49         group--;
50 @@ -2306,8 +2309,6 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
51                               " 2^0   2^1   2^2   2^3   2^4   2^5   2^6  "
52                               " 2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]\n");
54 -       i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
55 -               sizeof(struct ext4_group_info);
56         grinfo = ext4_get_group_info(sb, group);
57         /* Load the group info in memory only if not already loaded. */
58         if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
59 @@ -2319,7 +2320,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
60                 buddy_loaded = 1;
61         }
63 -       memcpy(&sg, ext4_get_group_info(sb, group), i);
64 +       memcpy(&sg, ext4_get_group_info(sb, group), sizeof(sg));
66         if (buddy_loaded)
67                 ext4_mb_unload_buddy(&e4b);
68 @@ -2327,7 +2328,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
69         seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
70                         sg.info.bb_fragments, sg.info.bb_first_free);
71         for (i = 0; i <= 13; i++)
72 -               seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ?
73 +               seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?
74                                 sg.info.bb_counters[i] : 0);
75         seq_printf(seq, " ]\n");