From nobody Tue May 19 14:08:46 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gKc3L6Yz5z6fFjx for ; Tue, 19 May 2026 14:08:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gKc3L4BfYz3hMp for ; Tue, 19 May 2026 14:08:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779199726; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=aJMOd9zXIKOxWCJjm4j0JMESZBnd9lraMBtnG+gKSUQ=; b=K/wAhg9rVl3RU9tC+q0ZApNKP+5zK5uPQtHKPsiqa+oej6BYxqfcBCFuRblNDI3OuB2reu cjRDHoyIRhsOxLBSrJ89p9V/2/mU2L/lKamsJJNbZr1e+lbzi0VMdY/EJy1K4hnqoFxYPO L7KnpjRACm6YFAD3pCYGp2BOnFffMGqafz9+/1IkPvJvJ/0s/a6Xrlg5gsTvE34u+lh53b QfRUb7t38znbklJfsCvru3whSzOiWwaDFAh+PSe17s1N9jhRylVPJrdIzTyIa75YaqbpWy yoBpl8YafuiBvvmWmM9sEbKDa93bJvgPqcZenWRQHY+plxoujq6H5eVeuiVh5A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1779199726; a=rsa-sha256; cv=none; b=obB9lP2HI3Tvy6p0BJWnqMjqN2h7/P8TR68wWC1wEfnk2rGRS/ZIxGIUSnOfTaE6+2gw7i U7bkWsfrsEkOB6b0RBA2jeFxgB8bXtAbieSBKLhj93MRDx5+Ol/h7hYioRQuSGMWjrkT0t xePb2/ZIyyFbCGnQUUr0AbWT1vPoMWKL/3G1gjSS9lqKITcrO+8IVeDljwclCn80IvT1sG 9zxes145C1YKfY4XFpgtzwG/ntqUV/9mipOXUywCL2E7u0lVSmuwANItdoh77qkV94l9zb nQAMhtVrVzXME402/R4s9+fQBgYZHxpicMngRg3YcGFP1zJ4dUdUWpKp5ixk1Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1779199726; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=aJMOd9zXIKOxWCJjm4j0JMESZBnd9lraMBtnG+gKSUQ=; b=VEx3ILQEM9mNsRSzCN7AxHhYFaNVc8FIUVR7re1/SdWEGBn38/8jTe4Cqxl6MVyVaPEBqP vdrj1jioQ9o4si+yshw25U3LWF9hHA/aDJ03LnyUl+syFxjY4PBkHF7Or2W45uTInX98iw 7g/cqeOkwkBTnmB8zxFw243dJN5yrvgdknLLTMPoRUTNg/vqUt8bkGYvGWoq8JwcKlTHvk n3DbcbRA31KKHJSg3UqiaOfswtVGVAEovbTnwfy2ts1V0lsxOnlnzk9cyfIsIKVJ31z/Kw dBpXtdsnnjfmJGgqlUQYdwOfGFd9Bj/Nkibom61k2Aq27+ywuy9F6EEZ+P7ljg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gKc3L3lxxz3FF for ; Tue, 19 May 2026 14:08:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3cba4 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 19 May 2026 14:08:46 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: a1e4bc883c5d - stable/15 - execve: Add guard pages around execve KVA buffers List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: a1e4bc883c5ddcfd852e6a12be5789b63fb52196 Auto-Submitted: auto-generated Date: Tue, 19 May 2026 14:08:46 +0000 Message-Id: <6a0c6eee.3cba4.66f429f@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=a1e4bc883c5ddcfd852e6a12be5789b63fb52196 commit a1e4bc883c5ddcfd852e6a12be5789b63fb52196 Author: Mark Johnston AuthorDate: 2026-05-04 15:38:54 +0000 Commit: Mark Johnston CommitDate: 2026-05-19 14:08:32 +0000 execve: Add guard pages around execve KVA buffers This helps ensure that overflows will trigger a panic instead of silently corrupting adjacent buffers, as happened in SA-26:13.exec. Extend kmap_alloc_wait() to support allocation of guard pages on both sides of a KVA allocation. Modify the exec_map setup accordingly. Add the "vm.exec_map_guard_pages" tunable to provide control over the guard page allocations. Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D56711 (cherry picked from commit eca4dd133883c9e9aaeca68e0119a638ba0aaca7) --- sys/kern/kern_exec.c | 3 ++- sys/vm/vm_extern.h | 2 +- sys/vm/vm_init.c | 8 ++++++-- sys/vm/vm_kern.c | 39 ++++++++++++++++++++++++++++++++------- sys/vm/vm_kern.h | 1 + 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 0a9ae0aabb3e..22e18876a20c 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1435,7 +1435,8 @@ exec_prealloc_args_kva(void *arg __unused) mtx_init(&exec_args_kva_mtx, "exec args kva", NULL, MTX_DEF); for (i = 0; i < exec_map_entries; i++) { argkva = malloc(sizeof(*argkva), M_PARGS, M_WAITOK); - argkva->addr = kmap_alloc_wait(exec_map, exec_map_entry_size); + argkva->addr = kmap_alloc_wait(exec_map, exec_map_entry_size, + ptoa(exec_map_guard_pages)); argkva->gen = exec_args_gen; SLIST_INSERT_HEAD(&exec_args_kva_freelist, argkva, next); } diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index d0e005088745..9b84a741f8c7 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -51,7 +51,7 @@ vm_offset_t kva_alloc_aligned(vm_size_t, vm_size_t); void kva_free(vm_offset_t, vm_size_t); /* These operate on pageable virtual addresses. */ -vm_offset_t kmap_alloc_wait(vm_map_t, vm_size_t); +vm_offset_t kmap_alloc_wait(vm_map_t, vm_size_t, vm_size_t); void kmap_free_wakeup(vm_map_t, vm_offset_t, vm_size_t); /* These operate on virtual addresses backed by memory. */ diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c index 2764b438d27b..99eb3b4a57af 100644 --- a/sys/vm/vm_init.c +++ b/sys/vm/vm_init.c @@ -274,8 +274,12 @@ again: exec_map_entries = 2 * mp_ncpus + 4; #endif exec_map_entry_size = round_page(PATH_MAX + ARG_MAX); - kmem_subinit(exec_map, kernel_map, &minaddr, &maxaddr, - exec_map_entries * exec_map_entry_size + 64 * PAGE_SIZE, false); + exec_map_guard_pages = 1; + TUNABLE_INT_FETCH("vm.exec_map_guard_pages", &exec_map_guard_pages); + size = exec_map_entries * + (exec_map_entry_size + 2 * ptoa(exec_map_guard_pages)) + + 64 * PAGE_SIZE; + kmem_subinit(exec_map, kernel_map, &minaddr, &maxaddr, size, false); kmem_subinit(pipe_map, kernel_map, &minaddr, &maxaddr, maxpipekva, false); TSEXIT(); diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 626632b74add..d2880418a1f8 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -107,6 +107,7 @@ CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0); const u_long vm_maxuser_address = VM_MAXUSER_ADDRESS; u_int exec_map_entry_size; +u_int exec_map_guard_pages; u_int exec_map_entries; SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD, @@ -706,34 +707,52 @@ kmem_free(void *addr, vm_size_t size) vmem_free(arena, (uintptr_t)addr, size); } +static void +kmap_alloc_map(vm_map_t map, vm_offset_t addr, vm_size_t size, + vm_prot_t prot, int flags) +{ + int error __diagused; + + error = vm_map_insert(map, NULL, 0, + addr, addr + size, prot, prot, flags); + KASSERT(error == KERN_SUCCESS, + ("%s: unexpected error %d", __func__, error)); +} + /* * kmap_alloc_wait: * * Allocates pageable memory from a sub-map of the kernel. If the submap * has no room, the caller sleeps waiting for more memory in the submap. + * If "guard_size" is non-zero, then unmapped KVA is left at the beginning + * and end of the allocated range. * * This routine may block. */ vm_offset_t -kmap_alloc_wait(vm_map_t map, vm_size_t size) +kmap_alloc_wait(vm_map_t map, vm_size_t size, vm_size_t guard_size) { vm_offset_t addr; + vm_size_t total_size; + + KASSERT(size % PAGE_SIZE == 0 && guard_size % PAGE_SIZE == 0, + ("%s: size %zu guard_size %zu", __func__, size, guard_size)); - size = round_page(size); if (!swap_reserve(size)) return (0); + total_size = size + 2 * guard_size; for (;;) { /* * To make this work for more than one map, use the map's lock * to lock out sleepers/wakers. */ vm_map_lock(map); - addr = vm_map_findspace(map, vm_map_min(map), size); - if (addr + size <= vm_map_max(map)) + addr = vm_map_findspace(map, vm_map_min(map), total_size); + if (addr + total_size <= vm_map_max(map)) break; /* no space now; see if we can ever get space */ - if (vm_map_max(map) - vm_map_min(map) < size) { + if (vm_map_max(map) - vm_map_min(map) < total_size) { vm_map_unlock(map); swap_release(size); return (0); @@ -741,10 +760,16 @@ kmap_alloc_wait(vm_map_t map, vm_size_t size) vm_map_modflags(map, MAP_NEEDS_WAKEUP, 0); vm_map_unlock_and_wait(map, 0); } - vm_map_insert(map, NULL, 0, addr, addr + size, VM_PROT_RW, VM_PROT_RW, + if (guard_size != 0) { + kmap_alloc_map(map, addr, guard_size, + VM_PROT_NONE, MAP_CREATE_GUARD); + kmap_alloc_map(map, addr + guard_size + size, guard_size, + VM_PROT_NONE, MAP_CREATE_GUARD); + } + kmap_alloc_map(map, addr + guard_size, size, VM_PROT_RW, MAP_ACC_CHARGED); vm_map_unlock(map); - return (addr); + return (addr + guard_size); } /* diff --git a/sys/vm/vm_kern.h b/sys/vm/vm_kern.h index 942c03480364..296a50ae0058 100644 --- a/sys/vm/vm_kern.h +++ b/sys/vm/vm_kern.h @@ -75,4 +75,5 @@ extern struct vmem *memguard_arena; extern u_long vm_kmem_size; extern u_int exec_map_entries; extern u_int exec_map_entry_size; +extern u_int exec_map_guard_pages; #endif /* _VM_VM_KERN_H_ */