]>
Commit | Line | Data |
---|---|---|
9d4489d9 GKH |
1 | From foo@baz Wed Aug 9 11:19:16 PDT 2017 |
2 | From: Michal Hocko <mhocko@suse.com> | |
3 | Date: Tue, 10 Jan 2017 16:57:27 -0800 | |
4 | Subject: mm, slab: make sure that KMALLOC_MAX_SIZE will fit into MAX_ORDER | |
5 | ||
6 | From: Michal Hocko <mhocko@suse.com> | |
7 | ||
8 | ||
9 | [ Upstream commit bb1107f7c6052c863692a41f78c000db792334bf ] | |
10 | ||
11 | Andrey Konovalov has reported the following warning triggered by the | |
12 | syzkaller fuzzer. | |
13 | ||
14 | WARNING: CPU: 1 PID: 9935 at mm/page_alloc.c:3511 __alloc_pages_nodemask+0x159c/0x1e20 | |
15 | Kernel panic - not syncing: panic_on_warn set ... | |
16 | CPU: 1 PID: 9935 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #34 | |
17 | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 | |
18 | Call Trace: | |
19 | __alloc_pages_slowpath mm/page_alloc.c:3511 | |
20 | __alloc_pages_nodemask+0x159c/0x1e20 mm/page_alloc.c:3781 | |
21 | alloc_pages_current+0x1c7/0x6b0 mm/mempolicy.c:2072 | |
22 | alloc_pages include/linux/gfp.h:469 | |
23 | kmalloc_order+0x1f/0x70 mm/slab_common.c:1015 | |
24 | kmalloc_order_trace+0x1f/0x160 mm/slab_common.c:1026 | |
25 | kmalloc_large include/linux/slab.h:422 | |
26 | __kmalloc+0x210/0x2d0 mm/slub.c:3723 | |
27 | kmalloc include/linux/slab.h:495 | |
28 | ep_write_iter+0x167/0xb50 drivers/usb/gadget/legacy/inode.c:664 | |
29 | new_sync_write fs/read_write.c:499 | |
30 | __vfs_write+0x483/0x760 fs/read_write.c:512 | |
31 | vfs_write+0x170/0x4e0 fs/read_write.c:560 | |
32 | SYSC_write fs/read_write.c:607 | |
33 | SyS_write+0xfb/0x230 fs/read_write.c:599 | |
34 | entry_SYSCALL_64_fastpath+0x1f/0xc2 | |
35 | ||
36 | The issue is caused by a lack of size check for the request size in | |
37 | ep_write_iter which should be fixed. It, however, points to another | |
38 | problem, that SLUB defines KMALLOC_MAX_SIZE too large because the its | |
39 | KMALLOC_SHIFT_MAX is (MAX_ORDER + PAGE_SHIFT) which means that the | |
40 | resulting page allocator request might be MAX_ORDER which is too large | |
41 | (see __alloc_pages_slowpath). | |
42 | ||
43 | The same applies to the SLOB allocator which allows even larger sizes. | |
44 | Make sure that they are capped properly and never request more than | |
45 | MAX_ORDER order. | |
46 | ||
47 | Link: http://lkml.kernel.org/r/20161220130659.16461-2-mhocko@kernel.org | |
48 | Signed-off-by: Michal Hocko <mhocko@suse.com> | |
49 | Reported-by: Andrey Konovalov <andreyknvl@google.com> | |
50 | Acked-by: Christoph Lameter <cl@linux.com> | |
51 | Cc: Alexei Starovoitov <ast@kernel.org> | |
52 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
53 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
54 | Signed-off-by: Sasha Levin <alexander.levin@verizon.com> | |
55 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
56 | --- | |
57 | include/linux/slab.h | 4 ++-- | |
58 | 1 file changed, 2 insertions(+), 2 deletions(-) | |
59 | ||
60 | --- a/include/linux/slab.h | |
61 | +++ b/include/linux/slab.h | |
62 | @@ -203,7 +203,7 @@ size_t ksize(const void *); | |
63 | * (PAGE_SIZE*2). Larger requests are passed to the page allocator. | |
64 | */ | |
65 | #define KMALLOC_SHIFT_HIGH (PAGE_SHIFT + 1) | |
66 | -#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT) | |
67 | +#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) | |
68 | #ifndef KMALLOC_SHIFT_LOW | |
69 | #define KMALLOC_SHIFT_LOW 3 | |
70 | #endif | |
71 | @@ -216,7 +216,7 @@ size_t ksize(const void *); | |
72 | * be allocated from the same page. | |
73 | */ | |
74 | #define KMALLOC_SHIFT_HIGH PAGE_SHIFT | |
75 | -#define KMALLOC_SHIFT_MAX 30 | |
76 | +#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) | |
77 | #ifndef KMALLOC_SHIFT_LOW | |
78 | #define KMALLOC_SHIFT_LOW 3 | |
79 | #endif |