Date: Tue, 30 Jun 2026 01:09:34 +0000 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: 2767a1f3686e - main - posix_spawn(3): create a guard page below the stack for rfork_thread on x86 Message-ID: <6a43174e.1cceb.286f155@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=2767a1f3686e5b1657ff4c3d57737c7f21598125 commit 2767a1f3686e5b1657ff4c3d57737c7f21598125 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-06-29 22:06:53 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-06-30 01:09:13 +0000 posix_spawn(3): create a guard page below the stack for rfork_thread on x86 Reviewed by: kevans Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D57955 --- lib/libc/gen/posix_spawn.c | 47 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c index b9d3084ef156..50eda5360767 100644 --- a/lib/libc/gen/posix_spawn.c +++ b/lib/libc/gen/posix_spawn.c @@ -28,6 +28,7 @@ #include "namespace.h" #include <sys/param.h> +#include <sys/mman.h> #include <sys/procctl.h> #include <sys/procdesc.h> #include <sys/queue.h> @@ -231,19 +232,7 @@ struct posix_spawn_args { volatile int error; }; -#define PSPAWN_STACK_ALIGNMENT 16 -#define PSPAWN_STACK_ALIGNBYTES (PSPAWN_STACK_ALIGNMENT - 1) -#define PSPAWN_STACK_ALIGN(sz) \ - (((sz) + PSPAWN_STACK_ALIGNBYTES) & ~PSPAWN_STACK_ALIGNBYTES) - -/* - * Below we'll assume that _RFORK_THREAD_STACK_SIZE is appropriately aligned for - * the posix_spawn() case where we do not end up calling execvpe and won't ever - * try to allocate space on the stack for argv[]. - */ #define _RFORK_THREAD_STACK_SIZE 4096 -_Static_assert((_RFORK_THREAD_STACK_SIZE % PSPAWN_STACK_ALIGNMENT) == 0, - "Inappropriate stack size alignment"); static int _posix_spawn_thr(void *data) @@ -285,11 +274,13 @@ do_posix_spawn(pid_t *pid, const char *path, pid_t p; int pfd; bool do_pfd; - char *stack; - size_t stacksz; + char *guard, *stack; + size_t stacksz, pagesz; #if defined(__i386__) || defined(__amd64__) stacksz = _RFORK_THREAD_STACK_SIZE; + pagesz = getpagesize(); + if (use_env_path) { size_t cnt; @@ -304,24 +295,21 @@ do_posix_spawn(pid_t *pid, const char *path, for (cnt = 0; argv[cnt] != NULL; ++cnt) ; stacksz += MAX(3, cnt + 2) * sizeof(char *); - stacksz = PSPAWN_STACK_ALIGN(stacksz); } - /* - * aligned_alloc is not safe to use here, because we can't guarantee - * that aligned_alloc and free will be provided by the same - * implementation. We've actively hit at least one application that - * will provide its own malloc/free but not aligned_alloc leading to - * a free by the wrong allocator. - */ - stack = malloc(stacksz); - if (stack == NULL) + stacksz = round_page(stacksz); + guard = mmap(NULL, stacksz + pagesz, 0, MAP_GUARD, -1, 0); + if (guard == MAP_FAILED) return (ENOMEM); - stacksz = (((uintptr_t)stack + stacksz) & ~PSPAWN_STACK_ALIGNBYTES) - - (uintptr_t)stack; + stack = mmap(guard + pagesz, stacksz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); + if (stack == MAP_FAILED) { + munmap(guard, stacksz + pagesz); + return (ENOMEM); + } #else - stack = NULL; - stacksz = 0; + guard = stack = NULL; + pagesz = stacksz = 0; #endif psa.path = path; psa.fa = fa; @@ -362,7 +350,8 @@ do_posix_spawn(pid_t *pid, const char *path, p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa); } - free(stack); + if (stack != NULL) + munmap(guard, stacksz + pagesz); /* * The above block should leave us in a state where we've eitherhome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a43174e.1cceb.286f155>
