Skip to content

Commit a896527

Browse files
kirylIngo Molnar
authored andcommitted
x86/mpx: Do not set ->vm_ops on MPX VMAs
MPX setups private anonymous mapping, but uses vma->vm_ops too. This can confuse core VM, as it relies on vm->vm_ops to distinguish file VMAs from anonymous. As result we will get SIGBUS, because handle_pte_fault() thinks it's file VMA without vm_ops->fault and it doesn't know how to handle the situation properly. Let's fix that by not setting ->vm_ops. We don't really need ->vm_ops here: MPX VMA can be detected with VM_MPX flag. And vma_merge() will not merge MPX VMA with non-MPX VMA, because ->vm_flags won't match. The only thing left is name of VMA. I'm not sure if it's part of ABI, or we can just drop it. The patch keep it by providing arch_vma_name() on x86. Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Cc: <[email protected]> # Fixes: 6b7339f (mm: avoid setting up anonymous pages into file mapping) Cc: Andy Lutomirski <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent bbc0377 commit a896527

File tree

2 files changed

+10
-21
lines changed

2 files changed

+10
-21
lines changed

arch/x86/mm/mmap.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,10 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
126126
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
127127
}
128128
}
129+
130+
const char *arch_vma_name(struct vm_area_struct *vma)
131+
{
132+
if (vma->vm_flags & VM_MPX)
133+
return "[mpx]";
134+
return NULL;
135+
}

arch/x86/mm/mpx.c

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,6 @@
2020
#define CREATE_TRACE_POINTS
2121
#include <asm/trace/mpx.h>
2222

23-
static const char *mpx_mapping_name(struct vm_area_struct *vma)
24-
{
25-
return "[mpx]";
26-
}
27-
28-
static struct vm_operations_struct mpx_vma_ops = {
29-
.name = mpx_mapping_name,
30-
};
31-
32-
static int is_mpx_vma(struct vm_area_struct *vma)
33-
{
34-
return (vma->vm_ops == &mpx_vma_ops);
35-
}
36-
3723
static inline unsigned long mpx_bd_size_bytes(struct mm_struct *mm)
3824
{
3925
if (is_64bit_mm(mm))
@@ -53,9 +39,6 @@ static inline unsigned long mpx_bt_size_bytes(struct mm_struct *mm)
5339
/*
5440
* This is really a simplified "vm_mmap". it only handles MPX
5541
* bounds tables (the bounds directory is user-allocated).
56-
*
57-
* Later on, we use the vma->vm_ops to uniquely identify these
58-
* VMAs.
5942
*/
6043
static unsigned long mpx_mmap(unsigned long len)
6144
{
@@ -101,7 +84,6 @@ static unsigned long mpx_mmap(unsigned long len)
10184
ret = -ENOMEM;
10285
goto out;
10386
}
104-
vma->vm_ops = &mpx_vma_ops;
10587

10688
if (vm_flags & VM_LOCKED) {
10789
up_write(&mm->mmap_sem);
@@ -812,7 +794,7 @@ static noinline int zap_bt_entries_mapping(struct mm_struct *mm,
812794
* so stop immediately and return an error. This
813795
* probably results in a SIGSEGV.
814796
*/
815-
if (!is_mpx_vma(vma))
797+
if (!(vma->vm_flags & VM_MPX))
816798
return -EINVAL;
817799

818800
len = min(vma->vm_end, end) - addr;
@@ -945,9 +927,9 @@ static int try_unmap_single_bt(struct mm_struct *mm,
945927
* lots of tables even though we have no actual table
946928
* entries in use.
947929
*/
948-
while (next && is_mpx_vma(next))
930+
while (next && (next->vm_flags & VM_MPX))
949931
next = next->vm_next;
950-
while (prev && is_mpx_vma(prev))
932+
while (prev && (prev->vm_flags & VM_MPX))
951933
prev = prev->vm_prev;
952934
/*
953935
* We know 'start' and 'end' lie within an area controlled

0 commit comments

Comments
 (0)