Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Aug 2023 06:29:09 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 55be6be12cd9 - main - vm_map_protect(): handle stack protection stored in the stack guard
Message-ID:  <202308120629.37C6T9Ql024899@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202308120629.37C6T9Ql024899>