git: 55be6be12cd9 - main - vm_map_protect(): handle stack protection stored in the stack guard
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 12 Aug 2023 06:29:09 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=55be6be12cd95552a46feccb42db984c8d3cbc36 commit 55be6be12cd95552a46feccb42db984c8d3cbc36 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-07-25 13:32:28 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-08-12 06:28:13 +0000 vm_map_protect(): handle stack protection stored in the stack guard mprotect(2) on the stack region needs to adjust guard stored protection, so that e.g. enable executing on stack worked properly on stack growth. Reported by: dchagin Reviewed by: alc, markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D41099 --- 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 dd342752bf6c..e63fcdc7c6f1 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2726,7 +2726,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)); + } } /* @@ -2742,7 +2757,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) @@ -2791,10 +2806,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); }