]>
Commit | Line | Data |
---|---|---|
28bdf407 GKH |
1 | From foo@baz Thu Dec 13 20:11:30 CET 2018 |
2 | From: Mike Kravetz <mike.kravetz@oracle.com> | |
3 | Date: Fri, 31 Mar 2017 15:12:07 -0700 | |
4 | Subject: mm/hugetlb.c: don't call region_abort if region_chg fails | |
5 | ||
6 | From: Mike Kravetz <mike.kravetz@oracle.com> | |
7 | ||
8 | commit ff8c0c53c47530ffea82c22a0a6df6332b56c957 upstream. | |
9 | ||
10 | Changes to hugetlbfs reservation maps is a two step process. The first | |
11 | step is a call to region_chg to determine what needs to be changed, and | |
12 | prepare that change. This should be followed by a call to call to | |
13 | region_add to commit the change, or region_abort to abort the change. | |
14 | ||
15 | The error path in hugetlb_reserve_pages called region_abort after a | |
16 | failed call to region_chg. As a result, the adds_in_progress counter in | |
17 | the reservation map is off by 1. This is caught by a VM_BUG_ON in | |
18 | resv_map_release when the reservation map is freed. | |
19 | ||
20 | syzkaller fuzzer (when using an injected kmalloc failure) found this | |
21 | bug, that resulted in the following: | |
22 | ||
23 | kernel BUG at mm/hugetlb.c:742! | |
24 | Call Trace: | |
25 | hugetlbfs_evict_inode+0x7b/0xa0 fs/hugetlbfs/inode.c:493 | |
26 | evict+0x481/0x920 fs/inode.c:553 | |
27 | iput_final fs/inode.c:1515 [inline] | |
28 | iput+0x62b/0xa20 fs/inode.c:1542 | |
29 | hugetlb_file_setup+0x593/0x9f0 fs/hugetlbfs/inode.c:1306 | |
30 | newseg+0x422/0xd30 ipc/shm.c:575 | |
31 | ipcget_new ipc/util.c:285 [inline] | |
32 | ipcget+0x21e/0x580 ipc/util.c:639 | |
33 | SYSC_shmget ipc/shm.c:673 [inline] | |
34 | SyS_shmget+0x158/0x230 ipc/shm.c:657 | |
35 | entry_SYSCALL_64_fastpath+0x1f/0xc2 | |
36 | RIP: resv_map_release+0x265/0x330 mm/hugetlb.c:742 | |
37 | ||
38 | Link: http://lkml.kernel.org/r/1490821682-23228-1-git-send-email-mike.kravetz@oracle.com | |
39 | Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> | |
40 | Reported-by: Dmitry Vyukov <dvyukov@google.com> | |
41 | Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com> | |
42 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
43 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
44 | Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> | |
45 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
46 | --- | |
47 | mm/hugetlb.c | 4 +++- | |
48 | 1 file changed, 3 insertions(+), 1 deletion(-) | |
49 | ||
50 | --- a/mm/hugetlb.c | |
51 | +++ b/mm/hugetlb.c | |
52 | @@ -4142,7 +4142,9 @@ int hugetlb_reserve_pages(struct inode * | |
53 | return 0; | |
54 | out_err: | |
55 | if (!vma || vma->vm_flags & VM_MAYSHARE) | |
56 | - region_abort(resv_map, from, to); | |
57 | + /* Don't call region_abort if region_chg failed */ | |
58 | + if (chg >= 0) | |
59 | + region_abort(resv_map, from, to); | |
60 | if (vma && is_vma_resv_set(vma, HPAGE_RESV_OWNER)) | |
61 | kref_put(&resv_map->refs, resv_map_release); | |
62 | return ret; |