git: bd7afd9e50b3 - stable/13 - vm_map_protect(): handle stack protection stored in the stack guard
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 25 Aug 2023 01:08:33 UTC
The branch stable/13 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=bd7afd9e50b3a0939354c3e8c8ddcc9f696c92f9
commit bd7afd9e50b3a0939354c3e8c8ddcc9f696c92f9
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-07-25 13:32:28 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-08-25 01:06:44 +0000
vm_map_protect(): handle stack protection stored in the stack guard
(cherry picked from commit 55be6be12cd95552a46feccb42db984c8d3cbc36)
---
sys/vm/vm_map.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index d443c320b799..09e78b3e18f9 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2720,7 +2720,22 @@ static void
vm_map_protect_guard(vm_map_entry_t entry, vm_prot_t new_prot,
vm_prot_t new_maxprot, int flags)
{
+ vm_prot_t old_prot;
+
MPASS((entry->eflags & MAP_ENTRY_GUARD) != 0);
+ if ((entry->eflags & (MAP_ENTRY_STACK_GAP_UP |
+ MAP_ENTRY_STACK_GAP_DN)) == 0)
+ return;
+
+ old_prot = PROT_EXTRACT(entry->offset);
+ if ((flags & VM_MAP_PROTECT_SET_MAXPROT) != 0) {
+ entry->offset = PROT_MAX(new_maxprot) |
+ (new_maxprot & old_prot);
+ }
+ if ((flags & VM_MAP_PROTECT_SET_PROT) != 0) {
+ entry->offset = new_prot | PROT_MAX(
+ PROT_MAX_EXTRACT(entry->offset));
+ }
}
/*
@@ -2736,7 +2751,7 @@ vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end,
vm_map_entry_t entry, first_entry, in_tran, prev_entry;
vm_object_t obj;
struct ucred *cred;
- vm_prot_t check_prot, old_prot;
+ vm_prot_t check_prot, max_prot, old_prot;
int rv;
if (start == end)
@@ -2785,10 +2800,14 @@ again:
vm_map_unlock(map);
return (KERN_INVALID_ARGUMENT);
}
- if ((entry->eflags & MAP_ENTRY_GUARD) != 0) {
+ if ((entry->eflags & (MAP_ENTRY_GUARD |
+ MAP_ENTRY_STACK_GAP_DN | MAP_ENTRY_STACK_GAP_UP)) ==
+ MAP_ENTRY_GUARD)
continue;
- }
- if (!CONTAINS_BITS(entry->max_protection, check_prot)) {
+ max_prot = (entry->eflags & (MAP_ENTRY_STACK_GAP_DN |
+ MAP_ENTRY_STACK_GAP_UP)) != 0 ?
+ PROT_MAX_EXTRACT(entry->offset) : entry->max_protection;
+ if (!CONTAINS_BITS(max_prot, check_prot)) {
vm_map_unlock(map);
return (KERN_PROTECTION_FAILURE);
}