]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.14.33/ipc-shm.c-add-split-function-to-shm_vm_ops.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.14.33 / ipc-shm.c-add-split-function-to-shm_vm_ops.patch
CommitLineData
7e14cf98
GKH
1From 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 Mon Sep 17 00:00:00 2001
2From: Mike Kravetz <mike.kravetz@oracle.com>
3Date: Wed, 28 Mar 2018 16:01:01 -0700
4Subject: ipc/shm.c: add split function to shm_vm_ops
5
6From: Mike Kravetz <mike.kravetz@oracle.com>
7
8commit 3d942ee079b917b24e2a0c5f18d35ac8ec9fee48 upstream.
9
10If System V shmget/shmat operations are used to create a hugetlbfs
11backed mapping, it is possible to munmap part of the mapping and split
12the underlying vma such that it is not huge page aligned. This will
13untimately 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
39This bug was introduced by commit 31383c6865a5 ("mm, hugetlbfs:
40introduce ->split() to vm_operations_struct"). A split function was
41added to vm_operations_struct to determine if a mapping can be split.
42This was mostly for device-dax and hugetlbfs mappings which have
43specific alignment constraints.
44
45Mappings initiated via shmget/shmat have their original vm_ops
46overwritten with shm_vm_ops. shm_vm_ops functions will call back to the
47original vm_ops if needed. Add such a split function to shm_vm_ops.
48
49Link: http://lkml.kernel.org/r/20180321161314.7711-1-mike.kravetz@oracle.com
50Fixes: 31383c6865a5 ("mm, hugetlbfs: introduce ->split() to vm_operations_struct")
51Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
52Reported-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
53Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
54Tested-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
55Reviewed-by: Dan Williams <dan.j.williams@intel.com>
56Acked-by: Michal Hocko <mhocko@suse.com>
57Cc: Davidlohr Bueso <dave@stgolabs.net>
58Cc: Manfred Spraul <manfred@colorfullife.com>
59Cc: <stable@vger.kernel.org>
60Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
61Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
62Signed-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,