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); }