]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.85/dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.18.85 / dm-bufio-fix-integer-overflow-when-limiting-maximum-cache-size.patch
1 From 74d4108d9e681dbbe4a2940ed8fdff1f6868184c Mon Sep 17 00:00:00 2001
2 From: Eric Biggers <ebiggers@google.com>
3 Date: Wed, 15 Nov 2017 16:38:09 -0800
4 Subject: dm bufio: fix integer overflow when limiting maximum cache size
5
6 From: Eric Biggers <ebiggers@google.com>
7
8 commit 74d4108d9e681dbbe4a2940ed8fdff1f6868184c upstream.
9
10 The default max_cache_size_bytes for dm-bufio is meant to be the lesser
11 of 25% of the size of the vmalloc area and 2% of the size of lowmem.
12 However, on 32-bit systems the intermediate result in the expression
13
14 (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100
15
16 overflows, causing the wrong result to be computed. For example, on a
17 32-bit system where the vmalloc area is 520093696 bytes, the result is
18 1174405 rather than the expected 130023424, which makes the maximum
19 cache size much too small (far less than 2% of lowmem). This causes
20 severe performance problems for dm-verity users on affected systems.
21
22 Fix this by using mult_frac() to correctly multiply by a percentage. Do
23 this for all places in dm-bufio that multiply by a percentage. Also
24 replace (VMALLOC_END - VMALLOC_START) with VMALLOC_TOTAL, which contrary
25 to the comment is now defined in include/linux/vmalloc.h.
26
27 Depends-on: 9993bc635 ("sched/x86: Fix overflow in cyc2ns_offset")
28 Fixes: 95d402f057f2 ("dm: add bufio")
29 Signed-off-by: Eric Biggers <ebiggers@google.com>
30 Signed-off-by: Mike Snitzer <snitzer@redhat.com>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32
33 ---
34 drivers/md/dm-bufio.c | 15 ++++++---------
35 1 file changed, 6 insertions(+), 9 deletions(-)
36
37 --- a/drivers/md/dm-bufio.c
38 +++ b/drivers/md/dm-bufio.c
39 @@ -876,7 +876,8 @@ static void __get_memory_limit(struct dm
40 buffers = c->minimum_buffers;
41
42 *limit_buffers = buffers;
43 - *threshold_buffers = buffers * DM_BUFIO_WRITEBACK_PERCENT / 100;
44 + *threshold_buffers = mult_frac(buffers,
45 + DM_BUFIO_WRITEBACK_PERCENT, 100);
46 }
47
48 /*
49 @@ -1764,19 +1765,15 @@ static int __init dm_bufio_init(void)
50 memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches);
51 memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names);
52
53 - mem = (__u64)((totalram_pages - totalhigh_pages) *
54 - DM_BUFIO_MEMORY_PERCENT / 100) << PAGE_SHIFT;
55 + mem = (__u64)mult_frac(totalram_pages - totalhigh_pages,
56 + DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT;
57
58 if (mem > ULONG_MAX)
59 mem = ULONG_MAX;
60
61 #ifdef CONFIG_MMU
62 - /*
63 - * Get the size of vmalloc space the same way as VMALLOC_TOTAL
64 - * in fs/proc/internal.h
65 - */
66 - if (mem > (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100)
67 - mem = (VMALLOC_END - VMALLOC_START) * DM_BUFIO_VMALLOC_PERCENT / 100;
68 + if (mem > mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100))
69 + mem = mult_frac(VMALLOC_TOTAL, DM_BUFIO_VMALLOC_PERCENT, 100);
70 #endif
71
72 dm_bufio_default_cache_size = mem;