]>
Commit | Line | Data |
---|---|---|
7e14cf98 GKH |
1 | From 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 Mon Sep 17 00:00:00 2001 |
2 | From: Mike Kravetz <mike.kravetz@oracle.com> | |
3 | Date: Wed, 28 Mar 2018 16:01:01 -0700 | |
4 | Subject: ipc/shm.c: add split function to shm_vm_ops | |
5 | ||
6 | From: Mike Kravetz <mike.kravetz@oracle.com> | |
7 | ||
8 | commit 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 upstream. | |
9 | ||
10 | If System V shmget/shmat operations are used to create a hugetlbfs | |
11 | backed mapping, it is possible to munmap part of the mapping and split | |
12 | the underlying vma such that it is not huge page aligned. This will | |
13 | untimately result in the following BUG: | |
14 | ||
15 | kernel BUG at /build/linux-jWa1Fv/linux-4.15.0/mm/hugetlb.c:3310! | |
16 | Oops: Exception in kernel mode, sig: 5 [#1] | |
17 | LE SMP NR_CPUS=2048 NUMA PowerNV | |
18 | Modules linked in: kcm nfc af_alg caif_socket caif phonet fcrypt | |
19 | CPU: 18 PID: 43243 Comm: trinity-subchil Tainted: G C E 4.15.0-10-generic #11-Ubuntu | |
20 | NIP: c00000000036e764 LR: c00000000036ee48 CTR: 0000000000000009 | |
21 | REGS: c000003fbcdcf810 TRAP: 0700 Tainted: G C E (4.15.0-10-generic) | |
22 | MSR: 9000000000029033 <SF,HV,EE,ME,IR,DR,RI,LE> CR: 24002222 XER: 20040000 | |
23 | CFAR: c00000000036ee44 SOFTE: 1 | |
24 | NIP __unmap_hugepage_range+0xa4/0x760 | |
25 | LR __unmap_hugepage_range_final+0x28/0x50 | |
26 | Call Trace: | |
27 | 0x7115e4e00000 (unreliable) | |
28 | __unmap_hugepage_range_final+0x28/0x50 | |
29 | unmap_single_vma+0x11c/0x190 | |
30 | unmap_vmas+0x94/0x140 | |
31 | exit_mmap+0x9c/0x1d0 | |
32 | mmput+0xa8/0x1d0 | |
33 | do_exit+0x360/0xc80 | |
34 | do_group_exit+0x60/0x100 | |
35 | SyS_exit_group+0x24/0x30 | |
36 | system_call+0x58/0x6c | |
37 | ---[ end trace ee88f958a1c62605 ]--- | |
38 | ||
39 | This bug was introduced by commit 31383c6865a5 ("mm, hugetlbfs: | |
40 | introduce ->split() to vm_operations_struct"). A split function was | |
41 | added to vm_operations_struct to determine if a mapping can be split. | |
42 | This was mostly for device-dax and hugetlbfs mappings which have | |
43 | specific alignment constraints. | |
44 | ||
45 | Mappings initiated via shmget/shmat have their original vm_ops | |
46 | overwritten with shm_vm_ops. shm_vm_ops functions will call back to the | |
47 | original vm_ops if needed. Add such a split function to shm_vm_ops. | |
48 | ||
49 | Link: http://lkml.kernel.org/r/20180321161314.7711-1-mike.kravetz@oracle.com | |
50 | Fixes: 31383c6865a5 ("mm, hugetlbfs: introduce ->split() to vm_operations_struct") | |
51 | Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> | |
52 | Reported-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> | |
53 | Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> | |
54 | Tested-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> | |
55 | Reviewed-by: Dan Williams <dan.j.williams@intel.com> | |
56 | Acked-by: Michal Hocko <mhocko@suse.com> | |
57 | Cc: Davidlohr Bueso <dave@stgolabs.net> | |
58 | Cc: Manfred Spraul <manfred@colorfullife.com> | |
59 | Cc: <stable@vger.kernel.org> | |
60 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
61 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
62 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
63 | ||
64 | --- | |
65 | ipc/shm.c | 12 ++++++++++++ | |
66 | 1 file changed, 12 insertions(+) | |
67 | ||
68 | --- a/ipc/shm.c | |
69 | +++ b/ipc/shm.c | |
70 | @@ -386,6 +386,17 @@ static int shm_fault(struct vm_fault *vm | |
71 | return sfd->vm_ops->fault(vmf); | |
72 | } | |
73 | ||
74 | +static int shm_split(struct vm_area_struct *vma, unsigned long addr) | |
75 | +{ | |
76 | + struct file *file = vma->vm_file; | |
77 | + struct shm_file_data *sfd = shm_file_data(file); | |
78 | + | |
79 | + if (sfd->vm_ops && sfd->vm_ops->split) | |
80 | + return sfd->vm_ops->split(vma, addr); | |
81 | + | |
82 | + return 0; | |
83 | +} | |
84 | + | |
85 | #ifdef CONFIG_NUMA | |
86 | static int shm_set_policy(struct vm_area_struct *vma, struct mempolicy *new) | |
87 | { | |
88 | @@ -510,6 +521,7 @@ static const struct vm_operations_struct | |
89 | .open = shm_open, /* callback for a new vm-area open */ | |
90 | .close = shm_close, /* callback for when the vm-area is released */ | |
91 | .fault = shm_fault, | |
92 | + .split = shm_split, | |
93 | #if defined(CONFIG_NUMA) | |
94 | .set_policy = shm_set_policy, | |
95 | .get_policy = shm_get_policy, |