diff options
author | Kirill A. Shutemov <kirill.shutemov@linux.intel.com> | 2013-11-19 08:17:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-11-19 08:24:50 -0500 |
commit | fd8526ad14c182605e42b64646344b95befd9f94 (patch) | |
tree | e27277373aa64ed7d7d45f68c86eefdd07f14510 /arch/x86/mm | |
parent | 5305ca10e7f44333e46c1ce57fb87306cb437891 (diff) |
x86/mm: Implement ASLR for hugetlb mappings
Matthew noticed that hugetlb mappings don't participate in ASLR on x86-64:
% for i in `seq 3`; do
> tools/testing/selftests/vm/map_hugetlb | grep address
> done
Returned address is 0x2aaaaac00000
Returned address is 0x2aaaaac00000
Returned address is 0x2aaaaac00000
/proc/PID/maps entries for the mapping are always the same
(except inode number):
2aaaaac00000-2aaabac00000 rw-p 00000000 00:0c 8200 /anon_hugepage (deleted)
2aaaaac00000-2aaabac00000 rw-p 00000000 00:0c 256 /anon_hugepage (deleted)
2aaaaac00000-2aaabac00000 rw-p 00000000 00:0c 7180 /anon_hugepage (deleted)
The reason is the generic hugetlb_get_unmapped_area() function
which is used on x86-64. It doesn't support randomization and
use bottom-up unmapped area lookup, instead of usual top-down
on x86-64.
x86 has arch-specific hugetlb_get_unmapped_area(), but it's used
only on x86-32.
Let's use arch-specific hugetlb_get_unmapped_area() on x86-64
too. That adds ASLR and switches hugetlb mappings to use top-down
unmapped area lookup:
% for i in `seq 3`; do
> tools/testing/selftests/vm/map_hugetlb | grep address
> done
Returned address is 0x7f4f08a00000
Returned address is 0x7fdda4200000
Returned address is 0x7febe0000000
/proc/PID/maps entries:
7f4f08a00000-7f4f18a00000 rw-p 00000000 00:0c 1168 /anon_hugepage (deleted)
7fdda4200000-7fddb4200000 rw-p 00000000 00:0c 7092 /anon_hugepage (deleted)
7febe0000000-7febf0000000 rw-p 00000000 00:0c 7183 /anon_hugepage (deleted)
Unmapped area lookup policy for hugetlb mappings is consistent
with normal mappings now -- the only difference is alignment
requirements for huge pages.
libhugetlbfs test-suite didn't detect any regressions with the
patch applied (although it shows few failures on my machine
regardless the patch).
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mel Gorman <mgorman@suse.de>
Link: http://lkml.kernel.org/r/20131119131750.EA45CE0090@blue.fi.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/hugetlbpage.c | 9 |
1 files changed, 3 insertions, 6 deletions
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index 9d980d88b747..8c9f647ff9e1 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c | |||
@@ -87,9 +87,7 @@ int pmd_huge_support(void) | |||
87 | } | 87 | } |
88 | #endif | 88 | #endif |
89 | 89 | ||
90 | /* x86_64 also uses this file */ | 90 | #ifdef CONFIG_HUGETLB_PAGE |
91 | |||
92 | #ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
93 | static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, | 91 | static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, |
94 | unsigned long addr, unsigned long len, | 92 | unsigned long addr, unsigned long len, |
95 | unsigned long pgoff, unsigned long flags) | 93 | unsigned long pgoff, unsigned long flags) |
@@ -99,7 +97,7 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, | |||
99 | 97 | ||
100 | info.flags = 0; | 98 | info.flags = 0; |
101 | info.length = len; | 99 | info.length = len; |
102 | info.low_limit = TASK_UNMAPPED_BASE; | 100 | info.low_limit = current->mm->mmap_legacy_base; |
103 | info.high_limit = TASK_SIZE; | 101 | info.high_limit = TASK_SIZE; |
104 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); | 102 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); |
105 | info.align_offset = 0; | 103 | info.align_offset = 0; |
@@ -172,8 +170,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
172 | return hugetlb_get_unmapped_area_topdown(file, addr, len, | 170 | return hugetlb_get_unmapped_area_topdown(file, addr, len, |
173 | pgoff, flags); | 171 | pgoff, flags); |
174 | } | 172 | } |
175 | 173 | #endif /* CONFIG_HUGETLB_PAGE */ | |
176 | #endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/ | ||
177 | 174 | ||
178 | #ifdef CONFIG_X86_64 | 175 | #ifdef CONFIG_X86_64 |
179 | static __init int setup_hugepagesz(char *opt) | 176 | static __init int setup_hugepagesz(char *opt) |