mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
Merge: Enable shadow stack
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5798 # Merge Request Required Information ## Summary of Changes Backport a few missing shadow stack patches and enable shadow stack. Checked using the kernel selftests: ``` [root@intel-alderlake-m-01 ~]# lscpu | grep shstk [root@intel-alderlake-m-01 ~]# reboot now ... [root@intel-alderlake-m-01 ~]# uname -a Linux intel-alderlake-m-01.khw.eng.bos2.dc.redhat.com 5.14.0-527.SHSTK_UPDATE_WITH_GUARD_GAP.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Nov 24 14:21:55 EST 2024 x86_64 x86_64 x86_64 GNU/Linux [root@intel-alderlake-m-01 ~]# lscpu | grep shstk Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb intel_pt sha_ni xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk avx_vnni dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req hfi vnmi umip pku ospke waitpkg gfni vaes vpclmulqdq tme rdpid movdiri movdir64b fsrm md_clear serialize pconfig arch_lbr ibt flush_l1d arch_capabilities [root@intel-alderlake-m-01 ~]# ./tools/testing/selftests/x86/test_shadow_stack [INFO] new_ssp = 7fec4a3ffff8, *new_ssp = 7fec4a400001 [INFO] changing ssp from 7fec4adffff0 to 7fec4a3ffff8 [INFO] ssp is now 7fec4a400000 [OK] Shadow stack pivot [OK] Shadow stack faults [INFO] Corrupting shadow stack [INFO] Generated shadow stack violation successfully [OK] Shadow stack violation test [INFO] Gup read -> shstk access success [INFO] Gup write -> shstk access success [INFO] Violation from normal write [INFO] Gup read -> write access success [INFO] Violation from normal write [INFO] Gup write -> write access success [INFO] Cow gup write -> write access success [OK] Shadow gup test [INFO] Violation from shstk access [OK] mprotect() test [OK] Userfaultfd test [OK] Guard gap test, other mapping's gaps [OK] Guard gap test, placement mapping's gaps [OK] Ptrace test [OK] 32 bit test [OK] Uretprobe test ``` Leaving out da42b5229b since the relevant part is a follow-up of f7875966dc, which is not included. Omitted-fix: da42b5229b27bb5c0eff3408c92f025e6041dad3 Omitted-fix: 249608ee47132cab3b1adacd9e463548f57bd316 ## Approved Development Ticket(s) JIRA: https://issues.redhat.com/browse/RHEL-15599 Signed-off-by: Štěpán Horáček <shoracek@redhat.com> Approved-by: David Arcari <darcari@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
This commit is contained in:
@@ -75,6 +75,15 @@ arch_prctl(ARCH_SHSTK_LOCK, unsigned long features)
|
||||
are ignored. The mask is ORed with the existing value. So any feature bits
|
||||
set here cannot be enabled or disabled afterwards.
|
||||
|
||||
arch_prctl(ARCH_SHSTK_UNLOCK, unsigned long features)
|
||||
Unlock features. 'features' is a mask of all features to unlock. All
|
||||
bits set are processed, unset bits are ignored. Only works via ptrace.
|
||||
|
||||
arch_prctl(ARCH_SHSTK_STATUS, unsigned long addr)
|
||||
Copy the currently enabled features to the address passed in addr. The
|
||||
features are described using the bits passed into the others in
|
||||
'features'.
|
||||
|
||||
The return values are as follows. On success, return 0. On error, errno can
|
||||
be::
|
||||
|
||||
@@ -82,6 +91,7 @@ be::
|
||||
-ENOTSUPP if the feature is not supported by the hardware or
|
||||
kernel.
|
||||
-EINVAL arguments (non existing feature, etc)
|
||||
-EFAULT if could not copy information back to userspace
|
||||
|
||||
The feature's bits supported are::
|
||||
|
||||
|
||||
@@ -1219,21 +1219,18 @@ static unsigned long
|
||||
arch_get_unmapped_area_1(unsigned long addr, unsigned long len,
|
||||
unsigned long limit)
|
||||
{
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = addr;
|
||||
info.high_limit = limit;
|
||||
info.align_mask = 0;
|
||||
info.align_offset = 0;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
unsigned long limit;
|
||||
|
||||
|
||||
@@ -492,6 +492,7 @@
|
||||
560 common set_mempolicy_home_node sys_ni_syscall
|
||||
561 common cachestat sys_cachestat
|
||||
562 common fchmodat2 sys_fchmodat2
|
||||
563 common futex_wake sys_futex_wake
|
||||
564 common futex_wait sys_futex_wait
|
||||
565 common futex_requeue sys_futex_requeue
|
||||
563 common map_shadow_stack sys_map_shadow_stack
|
||||
564 common futex_wake sys_futex_wake
|
||||
565 common futex_wait sys_futex_wait
|
||||
566 common futex_requeue sys_futex_requeue
|
||||
|
||||
+3
-3
@@ -27,13 +27,14 @@
|
||||
*/
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
int do_align = 0;
|
||||
int aliasing = cache_is_vipt_aliasing();
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/*
|
||||
* We only need to do colour alignment if D cache aliases.
|
||||
@@ -66,7 +67,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
|
||||
+6
-6
@@ -28,13 +28,14 @@
|
||||
*/
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
int do_align = 0;
|
||||
int aliasing = cache_is_vipt_aliasing();
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/*
|
||||
* We only need to do colour alignment if either the I or D
|
||||
@@ -68,7 +69,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
@@ -79,15 +79,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
int do_align = 0;
|
||||
int aliasing = cache_is_vipt_aliasing();
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/*
|
||||
* We only need to do colour alignment if either the I or D
|
||||
|
||||
@@ -466,6 +466,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -911,6 +911,8 @@ __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
|
||||
__SYSCALL(__NR_cachestat, sys_cachestat)
|
||||
#define __NR_fchmodat2 452
|
||||
__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
|
||||
#define __NR_map_shadow_stack 453
|
||||
__SYSCALL(__NR_map_shadow_stack, sys_map_shadow_stack)
|
||||
#define __NR_futex_wake 454
|
||||
__SYSCALL(__NR_futex_wake, sys_futex_wake)
|
||||
#define __NR_futex_wait 455
|
||||
|
||||
@@ -23,12 +23,18 @@
|
||||
*/
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
int do_align = 0;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {
|
||||
.length = len,
|
||||
.low_limit = mm->mmap_base,
|
||||
.high_limit = TASK_SIZE,
|
||||
.align_offset = pgoff << PAGE_SHIFT
|
||||
};
|
||||
|
||||
/*
|
||||
* We only need to do colour alignment if either the I or D
|
||||
@@ -61,11 +67,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
|
||||
info.align_offset = pgoff << PAGE_SHIFT;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -452,6 +452,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -458,6 +458,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -391,6 +391,7 @@
|
||||
450 n32 set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 n32 cachestat sys_cachestat
|
||||
452 n32 fchmodat2 sys_fchmodat2
|
||||
453 n32 map_shadow_stack sys_map_shadow_stack
|
||||
454 n32 futex_wake sys_futex_wake
|
||||
455 n32 futex_wait sys_futex_wait
|
||||
456 n32 futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -367,6 +367,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 n64 cachestat sys_cachestat
|
||||
452 n64 fchmodat2 sys_fchmodat2
|
||||
453 n64 map_shadow_stack sys_map_shadow_stack
|
||||
454 n64 futex_wake sys_futex_wake
|
||||
455 n64 futex_wait sys_futex_wait
|
||||
456 n64 futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -440,6 +440,7 @@
|
||||
450 o32 set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 o32 cachestat sys_cachestat
|
||||
452 o32 fchmodat2 sys_fchmodat2
|
||||
453 o32 map_shadow_stack sys_map_shadow_stack
|
||||
454 o32 futex_wake sys_futex_wake
|
||||
455 o32 futex_wait sys_futex_wait
|
||||
456 o32 futex_requeue sys_futex_requeue
|
||||
|
||||
+4
-4
@@ -34,7 +34,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
|
||||
struct vm_area_struct *vma;
|
||||
unsigned long addr = addr0;
|
||||
int do_color_align;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (unlikely(len > TASK_SIZE))
|
||||
return -ENOMEM;
|
||||
@@ -92,14 +92,14 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
|
||||
*/
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
return arch_get_unmapped_area_common(filp,
|
||||
addr0, len, pgoff, flags, UP);
|
||||
@@ -111,7 +111,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr0,
|
||||
*/
|
||||
unsigned long arch_get_unmapped_area_topdown(struct file *filp,
|
||||
unsigned long addr0, unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
return arch_get_unmapped_area_common(filp,
|
||||
addr0, len, pgoff, flags, DOWN);
|
||||
|
||||
@@ -100,13 +100,16 @@ static unsigned long mmap_upper_limit(struct rlimit *rlim_stack)
|
||||
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma, *prev;
|
||||
unsigned long task_size = TASK_SIZE;
|
||||
int do_color_align, last_mmap;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {
|
||||
.length = len
|
||||
};
|
||||
|
||||
if (len > task_size)
|
||||
return -ENOMEM;
|
||||
@@ -137,8 +140,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
goto found_addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_legacy_base;
|
||||
info.high_limit = mmap_upper_limit(NULL);
|
||||
info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
|
||||
@@ -155,13 +156,15 @@ found_addr:
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
const unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma, *prev;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
int do_color_align, last_mmap;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {
|
||||
.length = len
|
||||
};
|
||||
|
||||
/* requested length too big for entire address space */
|
||||
if (len > TASK_SIZE)
|
||||
@@ -195,7 +198,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
}
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
info.low_limit = PAGE_SIZE;
|
||||
info.high_limit = mm->mmap_base;
|
||||
info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0;
|
||||
@@ -211,7 +213,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
* can happen with large stack limits and large mmap()
|
||||
* allocations.
|
||||
*/
|
||||
return arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
|
||||
return arch_get_unmapped_area(filp, addr0, len, pgoff, flags, vm_flags);
|
||||
|
||||
found_addr:
|
||||
if (do_color_align && !last_mmap && !(addr & ~PAGE_MASK))
|
||||
|
||||
@@ -450,6 +450,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -40,7 +40,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
addr = ALIGN(addr, huge_page_size(h));
|
||||
|
||||
/* we need to make sure the colouring is OK */
|
||||
return arch_get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
return arch_get_unmapped_area(file, addr, len, pgoff, flags, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -532,6 +532,7 @@
|
||||
450 nospu set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_ni_syscall
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -282,12 +282,10 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
|
||||
{
|
||||
int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
|
||||
unsigned long found, next_end;
|
||||
struct vm_unmapped_area_info info;
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
|
||||
info.align_offset = 0;
|
||||
struct vm_unmapped_area_info info = {
|
||||
.length = len,
|
||||
.align_mask = PAGE_MASK & ((1ul << pshift) - 1),
|
||||
};
|
||||
/*
|
||||
* Check till the allow max value for this mmap request
|
||||
*/
|
||||
@@ -326,13 +324,13 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
|
||||
{
|
||||
int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
|
||||
unsigned long found, prev;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {
|
||||
.flags = VM_UNMAPPED_AREA_TOPDOWN,
|
||||
.length = len,
|
||||
.align_mask = PAGE_MASK & ((1ul << pshift) - 1),
|
||||
};
|
||||
unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr);
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
|
||||
info.align_offset = 0;
|
||||
/*
|
||||
* If we are trying to allocate above DEFAULT_MAP_WINDOW
|
||||
* Add the different to the mmap_base.
|
||||
@@ -639,10 +637,11 @@ unsigned long arch_get_unmapped_area(struct file *filp,
|
||||
unsigned long addr,
|
||||
unsigned long len,
|
||||
unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
if (radix_enabled())
|
||||
return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return generic_get_unmapped_area(filp, addr, len, pgoff, flags, vm_flags);
|
||||
|
||||
return slice_get_unmapped_area(addr, len, flags,
|
||||
mm_ctx_user_psize(¤t->mm->context), 0);
|
||||
@@ -652,10 +651,11 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
|
||||
const unsigned long addr0,
|
||||
const unsigned long len,
|
||||
const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
const unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
if (radix_enabled())
|
||||
return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags);
|
||||
return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags, vm_flags);
|
||||
|
||||
return slice_get_unmapped_area(addr0, len, flags,
|
||||
mm_ctx_user_psize(¤t->mm->context), 1);
|
||||
|
||||
@@ -455,6 +455,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -271,14 +271,12 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = current->mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -287,7 +285,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
unsigned long addr;
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
@@ -295,7 +293,6 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
|
||||
info.low_limit = PAGE_SIZE;
|
||||
info.high_limit = current->mm->mmap_base;
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
/*
|
||||
@@ -341,7 +338,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
goto check_asce_limit;
|
||||
}
|
||||
|
||||
if (mm->get_unmapped_area == arch_get_unmapped_area)
|
||||
if (!test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
addr = hugetlb_get_unmapped_area_bottomup(file, addr, len,
|
||||
pgoff, flags);
|
||||
else
|
||||
|
||||
+6
-7
@@ -73,11 +73,11 @@ static inline unsigned long mmap_base(unsigned long rnd,
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (len > TASK_SIZE - mmap_min_addr)
|
||||
return -ENOMEM;
|
||||
@@ -93,7 +93,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
goto check_asce_limit;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = TASK_SIZE;
|
||||
@@ -112,11 +111,11 @@ check_asce_limit:
|
||||
|
||||
unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/* requested length too big for entire address space */
|
||||
if (len > TASK_SIZE - mmap_min_addr)
|
||||
@@ -182,10 +181,10 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
*/
|
||||
if (mmap_is_legacy(rlim_stack)) {
|
||||
mm->mmap_base = mmap_base_legacy(random_factor);
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
clear_bit(MMF_TOPDOWN, &mm->flags);
|
||||
} else {
|
||||
mm->mmap_base = mmap_base(random_factor, rlim_stack);
|
||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||
set_bit(MMF_TOPDOWN, &mm->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -455,6 +455,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
+5
-5
@@ -32,12 +32,13 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr,
|
||||
}
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
int do_colour_align;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
/* We do not accept a shared mapping if it would violate
|
||||
@@ -68,7 +69,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = TASK_UNMAPPED_BASE;
|
||||
info.high_limit = TASK_SIZE;
|
||||
@@ -80,13 +80,13 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
const unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
int do_colour_align;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
/* We do not accept a shared mapping if it would violate
|
||||
|
||||
@@ -39,9 +39,9 @@ SYSCALL_DEFINE0(getpagesize)
|
||||
return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
|
||||
}
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
/* We do not accept a shared mapping if it would violate
|
||||
@@ -59,7 +59,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
|
||||
if (!addr)
|
||||
addr = TASK_UNMAPPED_BASE;
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = addr;
|
||||
info.high_limit = TASK_SIZE;
|
||||
|
||||
@@ -87,13 +87,13 @@ static inline unsigned long COLOR_ALIGN(unsigned long addr,
|
||||
return base + off;
|
||||
}
|
||||
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct * vma;
|
||||
unsigned long task_size = TASK_SIZE;
|
||||
int do_color_align;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
/* We do not accept a shared mapping if it would violate
|
||||
@@ -126,7 +126,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = TASK_UNMAPPED_BASE;
|
||||
info.high_limit = min(task_size, VA_EXCLUDE_START);
|
||||
@@ -147,14 +146,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
const unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long task_size = STACK_TOP32;
|
||||
unsigned long addr = addr0;
|
||||
int do_color_align;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/* This should only ever run for 32-bit processes. */
|
||||
BUG_ON(!test_thread_flag(TIF_32BIT));
|
||||
@@ -218,14 +217,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
unsigned long align_goal, addr = -ENOMEM;
|
||||
unsigned long (*get_area)(struct file *, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long);
|
||||
|
||||
get_area = current->mm->get_unmapped_area;
|
||||
|
||||
if (flags & MAP_FIXED) {
|
||||
/* Ok, don't mess with it. */
|
||||
return get_area(NULL, orig_addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags);
|
||||
}
|
||||
flags &= ~MAP_SHARED;
|
||||
|
||||
@@ -238,7 +233,8 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
|
||||
align_goal = (64UL * 1024);
|
||||
|
||||
do {
|
||||
addr = get_area(NULL, orig_addr, len + (align_goal - PAGE_SIZE), pgoff, flags);
|
||||
addr = mm_get_unmapped_area(current->mm, NULL, orig_addr,
|
||||
len + (align_goal - PAGE_SIZE), pgoff, flags);
|
||||
if (!(addr & ~PAGE_MASK)) {
|
||||
addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL);
|
||||
break;
|
||||
@@ -256,7 +252,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
|
||||
* be obtained.
|
||||
*/
|
||||
if (addr & ~PAGE_MASK)
|
||||
addr = get_area(NULL, orig_addr, len, pgoff, flags);
|
||||
addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags);
|
||||
|
||||
return addr;
|
||||
}
|
||||
@@ -292,7 +288,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
gap == RLIM_INFINITY ||
|
||||
sysctl_legacy_va_layout) {
|
||||
mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
clear_bit(MMF_TOPDOWN, &mm->flags);
|
||||
} else {
|
||||
/* We know it's 32-bit */
|
||||
unsigned long task_size = STACK_TOP32;
|
||||
@@ -303,7 +299,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
gap = (task_size / 6 * 5);
|
||||
|
||||
mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
|
||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||
set_bit(MMF_TOPDOWN, &mm->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -498,6 +498,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -31,17 +31,15 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *filp,
|
||||
{
|
||||
struct hstate *h = hstate_file(filp);
|
||||
unsigned long task_size = TASK_SIZE;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
task_size = STACK_TOP32;
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = TASK_UNMAPPED_BASE;
|
||||
info.high_limit = min(task_size, VA_EXCLUDE_START);
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) {
|
||||
@@ -63,7 +61,7 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
struct hstate *h = hstate_file(filp);
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/* This should only ever run for 32-bit processes. */
|
||||
BUG_ON(!test_thread_flag(TIF_32BIT));
|
||||
@@ -73,7 +71,6 @@ hugetlb_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
info.low_limit = PAGE_SIZE;
|
||||
info.high_limit = mm->mmap_base;
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
/*
|
||||
@@ -123,7 +120,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
(!vma || addr + len <= vm_start_gap(vma)))
|
||||
return addr;
|
||||
}
|
||||
if (mm->get_unmapped_area == arch_get_unmapped_area)
|
||||
if (!test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
return hugetlb_get_unmapped_area_bottomup(file, addr, len,
|
||||
pgoff, flags);
|
||||
else
|
||||
|
||||
@@ -457,6 +457,7 @@
|
||||
450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 i386 cachestat sys_cachestat
|
||||
452 i386 fchmodat2 sys_fchmodat2
|
||||
453 i386 map_shadow_stack sys_map_shadow_stack
|
||||
454 i386 futex_wake sys_futex_wake
|
||||
455 i386 futex_wait sys_futex_wait
|
||||
456 i386 futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -374,7 +374,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 64 map_shadow_stack sys_map_shadow_stack
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
@@ -14,7 +14,7 @@ struct thread_shstk {
|
||||
u64 size;
|
||||
};
|
||||
|
||||
long shstk_prctl(struct task_struct *task, int option, unsigned long features);
|
||||
long shstk_prctl(struct task_struct *task, int option, unsigned long arg2);
|
||||
void reset_thread_features(void);
|
||||
unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clone_flags,
|
||||
unsigned long stack_size);
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define ARCH_SHSTK_ENABLE 0x5001
|
||||
#define ARCH_SHSTK_DISABLE 0x5002
|
||||
#define ARCH_SHSTK_LOCK 0x5003
|
||||
#define ARCH_SHSTK_UNLOCK 0x5004
|
||||
#define ARCH_SHSTK_STATUS 0x5005
|
||||
|
||||
/* ARCH_SHSTK_ features bits */
|
||||
#define ARCH_SHSTK_SHSTK (1ULL << 0)
|
||||
|
||||
@@ -113,7 +113,7 @@ static unsigned long sgx_get_unmapped_area(struct file *file,
|
||||
if (flags & MAP_FIXED)
|
||||
return addr;
|
||||
|
||||
return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
@@ -921,6 +921,8 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
|
||||
case ARCH_SHSTK_ENABLE:
|
||||
case ARCH_SHSTK_DISABLE:
|
||||
case ARCH_SHSTK_LOCK:
|
||||
case ARCH_SHSTK_UNLOCK:
|
||||
case ARCH_SHSTK_STATUS:
|
||||
return shstk_prctl(task, option, arg2);
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
+43
-25
@@ -134,28 +134,24 @@ static unsigned long adjust_shstk_size(unsigned long size)
|
||||
|
||||
static void unmap_shadow_stack(u64 base, u64 size)
|
||||
{
|
||||
while (1) {
|
||||
int r;
|
||||
int r;
|
||||
|
||||
r = vm_munmap(base, size);
|
||||
r = vm_munmap(base, size);
|
||||
|
||||
/*
|
||||
* vm_munmap() returns -EINTR when mmap_lock is held by
|
||||
* something else, and that lock should not be held for a
|
||||
* long time. Retry it for the case.
|
||||
*/
|
||||
if (r == -EINTR) {
|
||||
cond_resched();
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* mmap_write_lock_killable() failed with -EINTR. This means
|
||||
* the process is about to die and have it's MM cleaned up.
|
||||
* This task shouldn't ever make it back to userspace. In this
|
||||
* case it is ok to leak a shadow stack, so just exit out.
|
||||
*/
|
||||
if (r == -EINTR)
|
||||
return;
|
||||
|
||||
/*
|
||||
* For all other types of vm_munmap() failure, either the
|
||||
* system is out of memory or there is bug.
|
||||
*/
|
||||
WARN_ON_ONCE(r);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* For all other types of vm_munmap() failure, either the
|
||||
* system is out of memory or there is bug.
|
||||
*/
|
||||
WARN_ON_ONCE(r);
|
||||
}
|
||||
|
||||
static int shstk_setup(void)
|
||||
@@ -167,8 +163,8 @@ static int shstk_setup(void)
|
||||
if (features_enabled(ARCH_SHSTK_SHSTK))
|
||||
return 0;
|
||||
|
||||
/* Also not supported for 32 bit and x32 */
|
||||
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) || in_32bit_syscall())
|
||||
/* Also not supported for 32 bit */
|
||||
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) || in_ia32_syscall())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
size = adjust_shstk_size(0);
|
||||
@@ -290,7 +286,7 @@ static int shstk_push_sigframe(unsigned long *ssp)
|
||||
return -EINVAL;
|
||||
|
||||
*ssp -= SS_FRAME_SIZE;
|
||||
if (put_shstk_data((void *__user)*ssp, target_ssp))
|
||||
if (put_shstk_data((void __user *)*ssp, target_ssp))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
@@ -430,7 +426,18 @@ void shstk_free(struct task_struct *tsk)
|
||||
if (!shstk->base)
|
||||
return;
|
||||
|
||||
/*
|
||||
* shstk->base is NULL for CLONE_VFORK child tasks, and so is
|
||||
* normal. But size = 0 on a shstk->base is not normal and
|
||||
* indicated an attempt to free the thread shadow stack twice.
|
||||
* Warn about it.
|
||||
*/
|
||||
if (WARN_ON(!shstk->size))
|
||||
return;
|
||||
|
||||
unmap_shadow_stack(shstk->base, shstk->size);
|
||||
|
||||
shstk->size = 0;
|
||||
}
|
||||
|
||||
static int wrss_control(bool enable)
|
||||
@@ -525,16 +532,27 @@ SYSCALL_DEFINE3(map_shadow_stack, unsigned long, addr, unsigned long, size, unsi
|
||||
return alloc_shstk(addr, aligned_size, size, set_tok);
|
||||
}
|
||||
|
||||
long shstk_prctl(struct task_struct *task, int option, unsigned long features)
|
||||
long shstk_prctl(struct task_struct *task, int option, unsigned long arg2)
|
||||
{
|
||||
unsigned long features = arg2;
|
||||
|
||||
if (option == ARCH_SHSTK_STATUS) {
|
||||
return put_user(task->thread.features, (unsigned long __user *)arg2);
|
||||
}
|
||||
|
||||
if (option == ARCH_SHSTK_LOCK) {
|
||||
task->thread.features_locked |= features;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't allow via ptrace */
|
||||
if (task != current)
|
||||
/* Only allow via ptrace */
|
||||
if (task != current) {
|
||||
if (option == ARCH_SHSTK_UNLOCK && IS_ENABLED(CONFIG_CHECKPOINT_RESTORE)) {
|
||||
task->thread.features_locked &= ~features;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do not allow to change locked features */
|
||||
if (features & task->thread.features_locked)
|
||||
|
||||
@@ -315,6 +315,9 @@ int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
|
||||
|
||||
uc_flags = frame_uc_flags(regs);
|
||||
|
||||
if (setup_signal_shadow_stack(ksig))
|
||||
return -EFAULT;
|
||||
|
||||
if (!user_access_begin(frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -377,6 +380,9 @@ COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn)
|
||||
if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
|
||||
goto badframe;
|
||||
|
||||
if (restore_signal_shadow_stack())
|
||||
goto badframe;
|
||||
|
||||
if (compat_restore_altstack(&frame->uc.uc_stack))
|
||||
goto badframe;
|
||||
|
||||
|
||||
@@ -119,13 +119,21 @@ static void find_start_end(unsigned long addr, unsigned long flags,
|
||||
*end = task_size_64bit(addr > DEFAULT_MAP_WINDOW);
|
||||
}
|
||||
|
||||
static inline unsigned long stack_guard_placement(vm_flags_t vm_flags)
|
||||
{
|
||||
if (vm_flags & VM_SHADOW_STACK)
|
||||
return PAGE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
unsigned long begin, end;
|
||||
|
||||
if (flags & MAP_FIXED)
|
||||
@@ -144,12 +152,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = begin;
|
||||
info.high_limit = end;
|
||||
info.align_mask = 0;
|
||||
info.align_offset = pgoff << PAGE_SHIFT;
|
||||
info.start_gap = stack_guard_placement(vm_flags);
|
||||
if (filp) {
|
||||
info.align_mask = get_align_mask();
|
||||
info.align_offset += get_align_bits();
|
||||
@@ -158,14 +165,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
}
|
||||
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr0,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
/* requested length too big for entire address space */
|
||||
if (len > TASK_SIZE)
|
||||
@@ -199,6 +206,7 @@ get_unmapped_area:
|
||||
info.low_limit = PAGE_SIZE;
|
||||
|
||||
info.high_limit = get_mmap_base(0);
|
||||
info.start_gap = stack_guard_placement(vm_flags);
|
||||
|
||||
/*
|
||||
* If hint address is above DEFAULT_MAP_WINDOW, look for unmapped area
|
||||
@@ -210,7 +218,6 @@ get_unmapped_area:
|
||||
if (addr > DEFAULT_MAP_WINDOW && !in_32bit_syscall())
|
||||
info.high_limit += TASK_SIZE_MAX - DEFAULT_MAP_WINDOW;
|
||||
|
||||
info.align_mask = 0;
|
||||
info.align_offset = pgoff << PAGE_SHIFT;
|
||||
if (filp) {
|
||||
info.align_mask = get_align_mask();
|
||||
@@ -228,5 +235,5 @@ bottomup:
|
||||
* can happen with large stack limits and large mmap()
|
||||
* allocations.
|
||||
*/
|
||||
return arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
|
||||
return arch_get_unmapped_area(filp, addr0, len, pgoff, flags, 0);
|
||||
}
|
||||
|
||||
@@ -51,9 +51,8 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = get_mmap_base(1);
|
||||
|
||||
@@ -65,7 +64,6 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
|
||||
task_size_32bit() : task_size_64bit(addr > DEFAULT_MAP_WINDOW);
|
||||
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -74,7 +72,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
@@ -89,7 +87,6 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
|
||||
info.high_limit += TASK_SIZE_MAX - DEFAULT_MAP_WINDOW;
|
||||
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
/*
|
||||
@@ -141,7 +138,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
}
|
||||
|
||||
get_unmapped_area:
|
||||
if (mm->get_unmapped_area == arch_get_unmapped_area)
|
||||
if (!test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
return hugetlb_get_unmapped_area_bottomup(file, addr, len,
|
||||
pgoff, flags);
|
||||
else
|
||||
|
||||
+2
-2
@@ -129,9 +129,9 @@ static void arch_pick_mmap_base(unsigned long *base, unsigned long *legacy_base,
|
||||
void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
{
|
||||
if (mmap_is_legacy())
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
clear_bit(MMF_TOPDOWN, &mm->flags);
|
||||
else
|
||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||
set_bit(MMF_TOPDOWN, &mm->flags);
|
||||
|
||||
arch_pick_mmap_base(&mm->mmap_base, &mm->mmap_legacy_base,
|
||||
arch_rnd(mmap64_rnd_bits), task_size_64bit(0),
|
||||
|
||||
@@ -55,7 +55,8 @@ asmlinkage long xtensa_fadvise64_64(int fd, int advice,
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vmm;
|
||||
|
||||
|
||||
@@ -423,6 +423,7 @@
|
||||
450 common set_mempolicy_home_node sys_set_mempolicy_home_node
|
||||
451 common cachestat sys_cachestat
|
||||
452 common fchmodat2 sys_fchmodat2
|
||||
453 common map_shadow_stack sys_map_shadow_stack
|
||||
454 common futex_wake sys_futex_wake
|
||||
455 common futex_wait sys_futex_wait
|
||||
456 common futex_requeue sys_futex_requeue
|
||||
|
||||
+1
-1
@@ -587,7 +587,7 @@ static unsigned long get_unmapped_area_zero(struct file *file,
|
||||
}
|
||||
|
||||
/* Otherwise flags & MAP_PRIVATE: with no shmem object beneath it */
|
||||
return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags);
|
||||
#else
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
|
||||
@@ -329,14 +329,14 @@ static unsigned long dax_get_unmapped_area(struct file *filp,
|
||||
if ((off + len_align) < off)
|
||||
goto out;
|
||||
|
||||
addr_align = current->mm->get_unmapped_area(filp, addr, len_align,
|
||||
pgoff, flags);
|
||||
addr_align = mm_get_unmapped_area(current->mm, filp, addr, len_align,
|
||||
pgoff, flags);
|
||||
if (!IS_ERR_VALUE(addr_align)) {
|
||||
addr_align += (off - addr_align) & (align - 1);
|
||||
return addr_align;
|
||||
}
|
||||
out:
|
||||
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags);
|
||||
}
|
||||
|
||||
static const struct address_space_operations dev_dax_aops = {
|
||||
|
||||
@@ -167,14 +167,12 @@ hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = current->mm->mmap_base;
|
||||
info.high_limit = arch_get_mmap_end(addr, len, flags);
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -183,14 +181,13 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct hstate *h = hstate_file(file);
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
info.low_limit = PAGE_SIZE;
|
||||
info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
/*
|
||||
@@ -241,11 +238,11 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
}
|
||||
|
||||
/*
|
||||
* Use mm->get_unmapped_area value as a hint to use topdown routine.
|
||||
* Use MMF_TOPDOWN flag as a hint to use topdown routine.
|
||||
* If architectures have special needs, they should define their own
|
||||
* version of hugetlb_get_unmapped_area.
|
||||
*/
|
||||
if (mm->get_unmapped_area == arch_get_unmapped_area_topdown)
|
||||
if (test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
return hugetlb_get_unmapped_area_topdown(file, addr, len,
|
||||
pgoff, flags);
|
||||
return hugetlb_get_unmapped_area_bottomup(file, addr, len,
|
||||
|
||||
+4
-6
@@ -452,15 +452,13 @@ pde_get_unmapped_area(struct proc_dir_entry *pde, struct file *file, unsigned lo
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
{
|
||||
typeof_member(struct proc_ops, proc_get_unmapped_area) get_area;
|
||||
if (pde->proc_ops->proc_get_unmapped_area)
|
||||
return pde->proc_ops->proc_get_unmapped_area(file, orig_addr, len, pgoff, flags);
|
||||
|
||||
get_area = pde->proc_ops->proc_get_unmapped_area;
|
||||
#ifdef CONFIG_MMU
|
||||
if (!get_area)
|
||||
get_area = current->mm->get_unmapped_area;
|
||||
return mm_get_unmapped_area(current->mm, file, orig_addr, len, pgoff, flags);
|
||||
#endif
|
||||
if (get_area)
|
||||
return get_area(file, orig_addr, len, pgoff, flags);
|
||||
|
||||
return orig_addr;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ static unsigned long ramfs_mmu_get_unmapped_area(struct file *file,
|
||||
unsigned long addr, unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
{
|
||||
return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags);
|
||||
}
|
||||
|
||||
const struct file_operations ramfs_file_operations = {
|
||||
|
||||
@@ -157,6 +157,9 @@ static inline bool thp_disabled_by_hw(void)
|
||||
|
||||
unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags);
|
||||
unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags);
|
||||
|
||||
void folio_prep_large_rmappable(struct folio *folio);
|
||||
bool can_split_folio(struct folio *folio, int *pextra_pins);
|
||||
@@ -299,6 +302,14 @@ static inline void folio_prep_large_rmappable(struct folio *folio) {}
|
||||
|
||||
#define thp_get_unmapped_area NULL
|
||||
|
||||
static inline unsigned long
|
||||
thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
can_split_folio(struct folio *folio, int *pextra_pins)
|
||||
{
|
||||
|
||||
+11
-1
@@ -3403,7 +3403,16 @@ extern int install_special_mapping(struct mm_struct *mm,
|
||||
unsigned long randomize_stack_top(unsigned long stack_top);
|
||||
unsigned long randomize_page(unsigned long start, unsigned long range);
|
||||
|
||||
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
|
||||
unsigned long
|
||||
__get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags);
|
||||
|
||||
static inline unsigned long
|
||||
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
return __get_unmapped_area(file, addr, len, pgoff, flags, 0);
|
||||
}
|
||||
|
||||
extern unsigned long mmap_region(struct file *file, unsigned long addr,
|
||||
unsigned long len, vm_flags_t vm_flags, unsigned long pgoff,
|
||||
@@ -3450,6 +3459,7 @@ struct vm_unmapped_area_info {
|
||||
unsigned long high_limit;
|
||||
unsigned long align_mask;
|
||||
unsigned long align_offset;
|
||||
unsigned long start_gap;
|
||||
};
|
||||
|
||||
extern unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info);
|
||||
|
||||
@@ -719,11 +719,7 @@ struct iommu_mm_data;
|
||||
struct mm_struct {
|
||||
struct {
|
||||
struct maple_tree mm_mt;
|
||||
#ifdef CONFIG_MMU
|
||||
unsigned long (*get_unmapped_area) (struct file *filp,
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags);
|
||||
#endif
|
||||
|
||||
unsigned long mmap_base; /* base of mmap area */
|
||||
unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */
|
||||
#ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
|
||||
|
||||
@@ -157,6 +157,7 @@ calc_vm_flag_bits(struct file *file, unsigned long flags)
|
||||
return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
|
||||
_calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ) |
|
||||
_calc_vm_trans(flags, MAP_SYNC, VM_SYNC ) |
|
||||
_calc_vm_trans(flags, MAP_STACK, VM_NOHUGEPAGE) |
|
||||
arch_calc_vm_flag_bits(file, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,9 +91,12 @@ static inline int get_dumpable(struct mm_struct *mm)
|
||||
#define MMF_VM_MERGE_ANY 30
|
||||
#define MMF_VM_MERGE_ANY_MASK (1 << MMF_VM_MERGE_ANY)
|
||||
|
||||
#define MMF_TOPDOWN 31 /* mm searches top down by default */
|
||||
#define MMF_TOPDOWN_MASK (1 << MMF_TOPDOWN)
|
||||
|
||||
#define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
|
||||
MMF_DISABLE_THP_MASK | MMF_HAS_MDWE_MASK |\
|
||||
MMF_VM_MERGE_ANY_MASK)
|
||||
MMF_VM_MERGE_ANY_MASK | MMF_TOPDOWN_MASK)
|
||||
|
||||
static inline unsigned long mmf_init_flags(unsigned long flags)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/sync_core.h>
|
||||
#include <linux/sched/coredump.h>
|
||||
|
||||
/*
|
||||
* Routines for handling mm_structs
|
||||
@@ -173,22 +174,36 @@ static inline void mm_update_next_owner(struct mm_struct *mm)
|
||||
|
||||
extern void arch_pick_mmap_layout(struct mm_struct *mm,
|
||||
struct rlimit *rlim_stack);
|
||||
extern unsigned long
|
||||
arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
|
||||
unsigned long, unsigned long);
|
||||
extern unsigned long
|
||||
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t vm_flags);
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags);
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags, vm_flags_t);
|
||||
|
||||
unsigned long mm_get_unmapped_area(struct mm_struct *mm, struct file *filp,
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags);
|
||||
|
||||
unsigned long mm_get_unmapped_area_vmflags(struct mm_struct *mm,
|
||||
struct file *filp,
|
||||
unsigned long addr,
|
||||
unsigned long len,
|
||||
unsigned long pgoff,
|
||||
unsigned long flags,
|
||||
vm_flags_t vm_flags);
|
||||
|
||||
unsigned long
|
||||
generic_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags);
|
||||
unsigned long flags, vm_flags_t vm_flags);
|
||||
unsigned long
|
||||
generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags);
|
||||
unsigned long flags, vm_flags_t vm_flags);
|
||||
#else
|
||||
static inline void arch_pick_mmap_layout(struct mm_struct *mm,
|
||||
struct rlimit *rlim_stack) {}
|
||||
|
||||
@@ -822,6 +822,10 @@ __SYSCALL(__NR_cachestat, sys_cachestat)
|
||||
|
||||
#define __NR_fchmodat2 452
|
||||
__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
|
||||
|
||||
#define __NR_map_shadow_stack 453
|
||||
__SYSCALL(__NR_map_shadow_stack, sys_map_shadow_stack)
|
||||
|
||||
#define __NR_futex_wake 454
|
||||
__SYSCALL(__NR_futex_wake, sys_futex_wake)
|
||||
#define __NR_futex_wait 455
|
||||
|
||||
+1
-1
@@ -308,7 +308,7 @@ unsigned long io_uring_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
#else
|
||||
addr = 0UL;
|
||||
#endif
|
||||
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_MMU */
|
||||
|
||||
+1
-1
@@ -330,7 +330,7 @@ static unsigned long arena_get_unmapped_area(struct file *filp, unsigned long ad
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = current->mm->get_unmapped_area(filp, addr, len * 2, 0, flags);
|
||||
ret = mm_get_unmapped_area(current->mm, filp, addr, len * 2, 0, flags);
|
||||
if (IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
if ((ret >> 32) == ((ret + len - 1) >> 32))
|
||||
|
||||
@@ -1017,7 +1017,7 @@ static unsigned long bpf_get_unmapped_area(struct file *filp, unsigned long addr
|
||||
if (map->ops->map_get_unmapped_area)
|
||||
return map->ops->map_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
#ifdef CONFIG_MMU
|
||||
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, filp, addr, len, pgoff, flags);
|
||||
#else
|
||||
return addr;
|
||||
#endif
|
||||
|
||||
@@ -183,9 +183,6 @@ EXPORT_SYMBOL(dump_vma);
|
||||
void dump_mm(const struct mm_struct *mm)
|
||||
{
|
||||
pr_emerg("mm %px task_size %lu\n"
|
||||
#ifdef CONFIG_MMU
|
||||
"get_unmapped_area %px\n"
|
||||
#endif
|
||||
"mmap_base %lu mmap_legacy_base %lu\n"
|
||||
"pgd %px mm_users %d mm_count %d pgtables_bytes %lu map_count %d\n"
|
||||
"hiwater_rss %lx hiwater_vm %lx total_vm %lx locked_vm %lx\n"
|
||||
@@ -211,9 +208,6 @@ void dump_mm(const struct mm_struct *mm)
|
||||
"def_flags: %#lx(%pGv)\n",
|
||||
|
||||
mm, mm->task_size,
|
||||
#ifdef CONFIG_MMU
|
||||
mm->get_unmapped_area,
|
||||
#endif
|
||||
mm->mmap_base, mm->mmap_legacy_base,
|
||||
mm->pgd, atomic_read(&mm->mm_users),
|
||||
atomic_read(&mm->mm_count),
|
||||
|
||||
+27
-13
@@ -593,11 +593,12 @@ static inline bool is_transparent_hugepage(struct folio *folio)
|
||||
|
||||
static unsigned long __thp_get_unmapped_area(struct file *filp,
|
||||
unsigned long addr, unsigned long len,
|
||||
loff_t off, unsigned long flags, unsigned long size)
|
||||
loff_t off, unsigned long flags, unsigned long size,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
loff_t off_end = off + len;
|
||||
loff_t off_align = round_up(off, size);
|
||||
unsigned long len_pad, ret;
|
||||
unsigned long len_pad, ret, off_sub;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_64BIT) || in_compat_syscall())
|
||||
return 0;
|
||||
@@ -609,8 +610,8 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
|
||||
if (len_pad < len || (off + len_pad) < off)
|
||||
return 0;
|
||||
|
||||
ret = current->mm->get_unmapped_area(filp, addr, len_pad,
|
||||
off >> PAGE_SHIFT, flags);
|
||||
ret = mm_get_unmapped_area_vmflags(current->mm, filp, addr, len_pad,
|
||||
off >> PAGE_SHIFT, flags, vm_flags);
|
||||
|
||||
/*
|
||||
* The failure might be due to length padding. The caller will retry
|
||||
@@ -626,21 +627,34 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
|
||||
if (ret == addr)
|
||||
return addr;
|
||||
|
||||
ret += (off - ret) & (size - 1);
|
||||
off_sub = (off - ret) & (size - 1);
|
||||
|
||||
if (test_bit(MMF_TOPDOWN, ¤t->mm->flags) && !off_sub)
|
||||
return ret + size;
|
||||
|
||||
ret += off_sub;
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned long thp_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
unsigned long ret;
|
||||
loff_t off = (loff_t)pgoff << PAGE_SHIFT;
|
||||
|
||||
ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE, vm_flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mm_get_unmapped_area_vmflags(current->mm, filp, addr, len, pgoff, flags,
|
||||
vm_flags);
|
||||
}
|
||||
|
||||
unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
unsigned long ret;
|
||||
loff_t off = (loff_t)pgoff << PAGE_SHIFT;
|
||||
|
||||
ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return thp_get_unmapped_area_vmflags(filp, addr, len, pgoff, flags, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thp_get_unmapped_area);
|
||||
|
||||
|
||||
@@ -1251,18 +1251,6 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
|
||||
if (mm->map_count > sysctl_max_map_count)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Obtain the address to map to. we verify (or select) it and ensure
|
||||
* that it represents a valid section of the address space.
|
||||
*/
|
||||
addr = get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
|
||||
if (flags & MAP_FIXED_NOREPLACE) {
|
||||
if (find_vma_intersection(mm, addr, addr + len))
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (prot == PROT_EXEC) {
|
||||
pkey = execute_only_pkey(mm);
|
||||
if (pkey < 0)
|
||||
@@ -1276,6 +1264,18 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
|
||||
vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(file, flags) |
|
||||
mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
|
||||
|
||||
/* Obtain the address to map to. we verify (or select) it and ensure
|
||||
* that it represents a valid section of the address space.
|
||||
*/
|
||||
addr = __get_unmapped_area(file, addr, len, pgoff, flags, vm_flags);
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
|
||||
if (flags & MAP_FIXED_NOREPLACE) {
|
||||
if (find_vma_intersection(mm, addr, addr + len))
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (flags & MAP_LOCKED)
|
||||
if (!can_do_mlock())
|
||||
return -EPERM;
|
||||
@@ -1576,7 +1576,7 @@ static unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
||||
MA_STATE(mas, ¤t->mm->mm_mt, 0, 0);
|
||||
|
||||
/* Adjust search length to account for worst case alignment overhead */
|
||||
length = info->length + info->align_mask;
|
||||
length = info->length + info->align_mask + info->start_gap;
|
||||
if (length < info->length)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1588,7 +1588,13 @@ retry:
|
||||
if (mas_empty_area(&mas, low_limit, high_limit - 1, length))
|
||||
return -ENOMEM;
|
||||
|
||||
gap = mas.index;
|
||||
/*
|
||||
* Adjust for the gap first so it doesn't interfere with the
|
||||
* later alignment. The first step is the minimum needed to
|
||||
* fulill the start gap, the next steps is the minimum to align
|
||||
* that. It is the minimum needed to fulill both.
|
||||
*/
|
||||
gap = mas.index + info->start_gap;
|
||||
gap += (info->align_offset - gap) & info->align_mask;
|
||||
tmp = mas_next(&mas, ULONG_MAX);
|
||||
if (tmp && (tmp->vm_flags & VM_STARTGAP_FLAGS)) { /* Avoid prev check if possible */
|
||||
@@ -1627,7 +1633,7 @@ static unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
||||
|
||||
MA_STATE(mas, ¤t->mm->mm_mt, 0, 0);
|
||||
/* Adjust search length to account for worst case alignment overhead */
|
||||
length = info->length + info->align_mask;
|
||||
length = info->length + info->align_mask + info->start_gap;
|
||||
if (length < info->length)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1661,6 +1667,18 @@ retry:
|
||||
return gap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the allocation needs to ensure that there is no
|
||||
* existing mapping within it's guard gaps, for use as start_gap.
|
||||
*/
|
||||
static inline unsigned long stack_guard_placement(vm_flags_t vm_flags)
|
||||
{
|
||||
if (vm_flags & VM_SHADOW_STACK)
|
||||
return PAGE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for an unmapped address range.
|
||||
*
|
||||
@@ -1697,11 +1715,11 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
|
||||
unsigned long
|
||||
generic_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma, *prev;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
|
||||
|
||||
if (len > mmap_end - mmap_min_addr)
|
||||
@@ -1719,12 +1737,10 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
info.high_limit = mmap_end;
|
||||
info.align_mask = 0;
|
||||
info.align_offset = 0;
|
||||
info.start_gap = stack_guard_placement(vm_flags);
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -1732,9 +1748,10 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long
|
||||
arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
return generic_get_unmapped_area(filp, addr, len, pgoff, flags,
|
||||
vm_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1745,11 +1762,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long
|
||||
generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
struct vm_area_struct *vma, *prev;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_unmapped_area_info info;
|
||||
struct vm_unmapped_area_info info = {};
|
||||
const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
|
||||
|
||||
/* requested length too big for entire address space */
|
||||
@@ -1773,8 +1790,7 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
info.length = len;
|
||||
info.low_limit = PAGE_SIZE;
|
||||
info.high_limit = arch_get_mmap_base(addr, mm->mmap_base);
|
||||
info.align_mask = 0;
|
||||
info.align_offset = 0;
|
||||
info.start_gap = stack_guard_placement(vm_flags);
|
||||
addr = vm_unmapped_area(&info);
|
||||
|
||||
/*
|
||||
@@ -1798,18 +1814,31 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long
|
||||
arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
return generic_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
||||
return generic_get_unmapped_area_topdown(filp, addr, len, pgoff, flags,
|
||||
vm_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long mm_get_unmapped_area_vmflags(struct mm_struct *mm, struct file *filp,
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags,
|
||||
vm_flags_t vm_flags)
|
||||
{
|
||||
if (test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
return arch_get_unmapped_area_topdown(filp, addr, len, pgoff,
|
||||
flags, vm_flags);
|
||||
return arch_get_unmapped_area(filp, addr, len, pgoff, flags, vm_flags);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
__get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags, vm_flags_t vm_flags)
|
||||
{
|
||||
unsigned long (*get_area)(struct file *, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long);
|
||||
unsigned long, unsigned long, unsigned long)
|
||||
= NULL;
|
||||
|
||||
unsigned long error = arch_mmap_check(addr, len, flags);
|
||||
if (error)
|
||||
@@ -1819,7 +1848,6 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
if (len > TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
get_area = current->mm->get_unmapped_area;
|
||||
if (file) {
|
||||
if (file->f_op->get_unmapped_area)
|
||||
get_area = file->f_op->get_unmapped_area;
|
||||
@@ -1827,13 +1855,25 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
/*
|
||||
* mmap_region() will call shmem_zero_setup() to create a file,
|
||||
* so use shmem's get_unmapped_area in case it can be huge.
|
||||
* do_mmap() will clear pgoff, so match alignment.
|
||||
*/
|
||||
pgoff = 0;
|
||||
get_area = shmem_get_unmapped_area;
|
||||
}
|
||||
|
||||
addr = get_area(file, addr, len, pgoff, flags);
|
||||
/* Always treat pgoff as zero for anonymous memory. */
|
||||
if (!file)
|
||||
pgoff = 0;
|
||||
|
||||
if (get_area) {
|
||||
addr = get_area(file, addr, len, pgoff, flags);
|
||||
} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && !file
|
||||
&& IS_ALIGNED(len, PMD_SIZE)) {
|
||||
/* Ensures that larger anonymous mappings are THP aligned. */
|
||||
addr = thp_get_unmapped_area_vmflags(file, addr, len,
|
||||
pgoff, flags, vm_flags);
|
||||
} else {
|
||||
addr = mm_get_unmapped_area_vmflags(current->mm, file, addr, len,
|
||||
pgoff, flags, vm_flags);
|
||||
}
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
|
||||
@@ -1846,7 +1886,16 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
|
||||
return error ? error : addr;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_unmapped_area);
|
||||
unsigned long
|
||||
mm_get_unmapped_area(struct mm_struct *mm, struct file *file,
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
if (test_bit(MMF_TOPDOWN, &mm->flags))
|
||||
return arch_get_unmapped_area_topdown(file, addr, len, pgoff, flags, 0);
|
||||
return arch_get_unmapped_area(file, addr, len, pgoff, flags, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(mm_get_unmapped_area);
|
||||
|
||||
/**
|
||||
* find_vma_intersection() - Look up the first VMA which intersects the interval
|
||||
|
||||
+5
-6
@@ -2244,8 +2244,6 @@ unsigned long shmem_get_unmapped_area(struct file *file,
|
||||
unsigned long uaddr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
unsigned long (*get_area)(struct file *,
|
||||
unsigned long, unsigned long, unsigned long, unsigned long);
|
||||
unsigned long addr;
|
||||
unsigned long offset;
|
||||
unsigned long inflated_len;
|
||||
@@ -2255,8 +2253,8 @@ unsigned long shmem_get_unmapped_area(struct file *file,
|
||||
if (len > TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
get_area = current->mm->get_unmapped_area;
|
||||
addr = get_area(file, uaddr, len, pgoff, flags);
|
||||
addr = mm_get_unmapped_area(current->mm, file, uaddr, len, pgoff,
|
||||
flags);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
|
||||
return addr;
|
||||
@@ -2313,7 +2311,8 @@ unsigned long shmem_get_unmapped_area(struct file *file,
|
||||
if (inflated_len < len)
|
||||
return addr;
|
||||
|
||||
inflated_addr = get_area(NULL, uaddr, inflated_len, 0, flags);
|
||||
inflated_addr = mm_get_unmapped_area(current->mm, NULL, uaddr,
|
||||
inflated_len, 0, flags);
|
||||
if (IS_ERR_VALUE(inflated_addr))
|
||||
return addr;
|
||||
if (inflated_addr & ~PAGE_MASK)
|
||||
@@ -4700,7 +4699,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
|
||||
unsigned long addr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
|
||||
return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -439,17 +439,17 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
|
||||
if (mmap_is_legacy(rlim_stack)) {
|
||||
mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
clear_bit(MMF_TOPDOWN, &mm->flags);
|
||||
} else {
|
||||
mm->mmap_base = mmap_base(random_factor, rlim_stack);
|
||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||
set_bit(MMF_TOPDOWN, &mm->flags);
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
|
||||
void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
|
||||
{
|
||||
mm->mmap_base = TASK_UNMAPPED_BASE;
|
||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||
clear_bit(MMF_TOPDOWN, &mm->flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
# CONFIG_X86_USER_SHADOW_STACK is not set
|
||||
CONFIG_X86_USER_SHADOW_STACK=y
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* without building the headers.
|
||||
*/
|
||||
#ifndef __NR_map_shadow_stack
|
||||
#define __NR_map_shadow_stack 452
|
||||
#define __NR_map_shadow_stack 453
|
||||
|
||||
#define SHADOW_STACK_SET_TOKEN (1ULL << 0)
|
||||
|
||||
@@ -556,7 +556,7 @@ struct node {
|
||||
* looked at the shadow stack gaps.
|
||||
* 5. See if it landed in the gap.
|
||||
*/
|
||||
int test_guard_gap(void)
|
||||
int test_guard_gap_other_gaps(void)
|
||||
{
|
||||
void *free_area, *shstk, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
|
||||
struct node *head = NULL, *cur;
|
||||
@@ -593,11 +593,64 @@ int test_guard_gap(void)
|
||||
if (shstk - test_map - PAGE_SIZE != PAGE_SIZE)
|
||||
return 1;
|
||||
|
||||
printf("[OK]\tGuard gap test\n");
|
||||
printf("[OK]\tGuard gap test, other mapping's gaps\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tests respecting the guard gap of the mapping getting placed */
|
||||
int test_guard_gap_new_mappings_gaps(void)
|
||||
{
|
||||
void *free_area, *shstk_start, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
|
||||
struct node *head = NULL, *cur;
|
||||
int ret = 0;
|
||||
|
||||
free_area = mmap(0, PAGE_SIZE * 4, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
munmap(free_area, PAGE_SIZE * 4);
|
||||
|
||||
/* Test letting map_shadow_stack find a free space */
|
||||
shstk_start = mmap(free_area, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (shstk_start == MAP_FAILED || shstk_start != free_area)
|
||||
return 1;
|
||||
|
||||
while (test_map > shstk_start) {
|
||||
test_map = (void *)syscall(__NR_map_shadow_stack, 0, PAGE_SIZE, 0);
|
||||
if (test_map == MAP_FAILED) {
|
||||
printf("[INFO]\tmap_shadow_stack MAP_FAILED\n");
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
cur = malloc(sizeof(*cur));
|
||||
cur->mapping = test_map;
|
||||
|
||||
cur->next = head;
|
||||
head = cur;
|
||||
|
||||
if (test_map == free_area + PAGE_SIZE) {
|
||||
printf("[INFO]\tNew mapping has other mapping in guard gap!\n");
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (head) {
|
||||
cur = head;
|
||||
head = cur->next;
|
||||
munmap(cur->mapping, PAGE_SIZE);
|
||||
free(cur);
|
||||
}
|
||||
|
||||
munmap(shstk_start, PAGE_SIZE);
|
||||
|
||||
if (!ret)
|
||||
printf("[OK]\tGuard gap test, placement mapping's gaps\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Too complicated to pull it out of the 32 bit header, but also get the
|
||||
* 64 bit one needed above. Just define a copy here.
|
||||
@@ -850,9 +903,15 @@ int main(int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (test_guard_gap()) {
|
||||
if (test_guard_gap_other_gaps()) {
|
||||
ret = 1;
|
||||
printf("[FAIL]\tGuard gap test\n");
|
||||
printf("[FAIL]\tGuard gap test, other mappings' gaps\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (test_guard_gap_new_mappings_gaps()) {
|
||||
ret = 1;
|
||||
printf("[FAIL]\tGuard gap test, placement mapping's gaps\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user