From nobody Tue Jun 30 13:13:27 2026 X-Original-To: dev-commits-src-main@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 4gqNr72Sm2z6kBTs for ; Tue, 30 Jun 2026 13:13:27 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gqNr71hf7z3Gxr for ; Tue, 30 Jun 2026 13:13:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782825207; 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=4qhn2OaIoT7OQ2xjmflPV846jzMiJdlUHyG0911as5o=; b=Pe5H3oscN5N3lTdt+3ku1j3HHftLnjRrEWNMqvn+5jLHh8RE1rGopI1sFlk+ylkvK6FQWn kBKW2yL9z4aGWT57P5T+9Qo3CA4Bjp5wij1YFaTPgmF80RAPvFv48wbWyMRbl1yJJcvACi CdSqp+gkvLcFECpVqYRrdbcjpYgXNXigVgFrCiAVbgixSldeoiog5nn5RsNFwnNT1IPiOk /G9OBYlpjbdxPV1z7v802fRGaLuJgHtez8SzkvcxW049ffgN+Sx7aD26coBYuMIcIO8Adg AtJ5WPjvZ6//GLrtwycZ1smmx+of0+Vxysqy0OinVHPb/28wnTiq2e95OSisAQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782825207; a=rsa-sha256; cv=none; b=Jgcb4JSadKIIa9K0le1P42gpBInk1LXrPQYw9BDpwzn/WbC7df+ZFEbtJrMbgi/6D/msj2 qYd/hA/kHJF9pxw4TIldvkX5lf86OG3/uzvmvHlMDqwB7vbnFPwzXtmb6D+6uSiFmgcuZz Y6gPxZra3U5gbqzbY+mUZX6dgIaWnCLWgQmLLqRpT/gzGz7MbCQPkOti/7Jzvefb3gJfiq I07x3I69HN9aNK/vgbLjfhrmEUBzB8VM1BSBc3dcw9LOylH+w7cnA7R3VFVdNuzQmG7aGT SO6ce546BwBbcF2H70goF8XbzhENTH9+GeGYEiExldgLy6XdMBWdbsJzdovTwA== 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=1782825207; 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=4qhn2OaIoT7OQ2xjmflPV846jzMiJdlUHyG0911as5o=; b=Us4/wQgc5IleOc23JEMoP7kpy2Cbvs2z/nq5G1kcaw+BrKvz8MqMuGm2S39MlrQDxj6GuA 50jlH6Vm+m+NCNJeD9ebct6GJPy9RA9rWdfMjDtr77srPnNTN7B6AUv9v5g1hCIB+rFM3w PnDA5PHuM2fRYpvc5qkepra4kUTFgbaOb86hves7WzNZ/LrTgHltfhWM1Fb2Z3quo978sv gYcADjaokq0JJOv7U0/2oObqTv6jiPMPu2d+FeRc57QAw/Vj1kHogxLvnE9N4wVzkV1FFn Xv6FUxUCrh2zxdodNPzDRAWm5G5HaE52gSIHrRB2InLg1zQuF0WO6mbCM8aGBQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gqNr70MjTzmD0 for ; Tue, 30 Jun 2026 13:13:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 23b9c by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 30 Jun 2026 13:13:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kyle Evans Subject: git: 3de9dc5bf4b4 - main - libc: gen: add a test for rtld underflowing our posix_spawn thread List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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: kevans X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3de9dc5bf4b438e0d98222dc028982380d5a25d2 Auto-Submitted: auto-generated Date: Tue, 30 Jun 2026 13:13:27 +0000 Message-Id: <6a43c0f7.23b9c.7c984d1c@gitrepo.freebsd.org> The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=3de9dc5bf4b438e0d98222dc028982380d5a25d2 commit 3de9dc5bf4b438e0d98222dc028982380d5a25d2 Author: Kyle Evans AuthorDate: 2026-06-30 13:12:51 +0000 Commit: Kyle Evans CommitDate: 2026-06-30 13:12:51 +0000 libc: gen: add a test for rtld underflowing our posix_spawn thread This is a distillation of the environment described in the PR, using a dummy shlib and mapping it repeatedly. This takes advantage of the guard page added in 2767a1f3686e5b16 to reliably crash if rtld tries to scale its stack usage excessively with the # DSOs loaded. PR: 295991 Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D57954 --- lib/libc/tests/gen/Makefile | 2 + lib/libc/tests/gen/libdummy/Makefile | 9 +++++ lib/libc/tests/gen/libdummy/libdummy.c | 14 +++++++ lib/libc/tests/gen/posix_spawn_test.c | 68 ++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index f5d57275cb44..e451fbea644c 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -1,5 +1,7 @@ .include +SUBDIR+= libdummy + ATF_TESTS_C+= arc4random_test ATF_TESTS_C+= dir2_test ATF_TESTS_C+= dlopen_empty_test diff --git a/lib/libc/tests/gen/libdummy/Makefile b/lib/libc/tests/gen/libdummy/Makefile new file mode 100644 index 000000000000..58a22f1a6c32 --- /dev/null +++ b/lib/libc/tests/gen/libdummy/Makefile @@ -0,0 +1,9 @@ +SHLIB?= dummy +SHLIB_MAJOR= 0 + +LIBDIR= ${TESTSBASE}/lib/libc/gen +SHLIBDIR= ${TESTSBASE}/lib/libc/gen + +SRCS= libdummy.c + +.include diff --git a/lib/libc/tests/gen/libdummy/libdummy.c b/lib/libc/tests/gen/libdummy/libdummy.c new file mode 100644 index 000000000000..89e94c016311 --- /dev/null +++ b/lib/libc/tests/gen/libdummy/libdummy.c @@ -0,0 +1,14 @@ +/* + * + * Copyright (C) 2026 Kyle Evans + * + * SPDX-license-Identifier: BSD-2-Clause + */ + +int dummy_random(void); + +int +dummy_random(void) +{ + return (42); +} diff --git a/lib/libc/tests/gen/posix_spawn_test.c b/lib/libc/tests/gen/posix_spawn_test.c index 22133cf1d59a..9edd81b57d30 100644 --- a/lib/libc/tests/gen/posix_spawn_test.c +++ b/lib/libc/tests/gen/posix_spawn_test.c @@ -30,8 +30,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -173,6 +175,71 @@ ATF_TC_BODY(posix_spawnp_eacces, tc) } } +#define NUM_DSO 512 +ATF_TC_WITHOUT_HEAD(posix_spawnp_stackunderflow); +ATF_TC_BODY(posix_spawnp_stackunderflow, tc) +{ + struct stat sb; + char dsopath[MAXPATHLEN]; + char *myargs[] = { "true", NULL }; + void **handles; + char *dsomap; + size_t dsosz; + int error, fd, nfd, status; + pid_t pid, waitres; + + /* Make sure we have no child processes. */ + while (waitpid(-1, NULL, 0) != -1) + ; + ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno); + + (void)snprintf(dsopath, sizeof(dsopath), "%s/libdummy.so", + atf_tc_get_config_var(tc, "srcdir")); + + fd = open(dsopath, O_RDONLY); + ATF_REQUIRE(fd >= 0); + + /* + * We'll open our original shlib and fdlopen() it repeatedly until we + * have a lot of DSOs open, then we'll trigger a posix_spawnp. This + * previously unearthed suboptimal stack usage in rtld that caused + * posix_spawnp()'s effectively-vforked environment to underflow its + * stack. + * + * We only get one shot to trigger the underflow, as rtld binding the + * symbols in the exec path in the rfork-child will affect the main + * process, so we only test that we don't have a problem with a large + * number of DSOs loaded. + */ + ATF_REQUIRE(fstat(fd, &sb) == 0); + dsosz = sb.st_size; + dsomap = mmap(NULL, dsosz, PROT_READ, MAP_SHARED, fd, 0); + ATF_REQUIRE(dsomap != MAP_FAILED); + + handles = calloc(sizeof(*handles), NUM_DSO); + ATF_REQUIRE(handles != NULL); + + for (int i = 0; i < NUM_DSO; i++) { + nfd = memfd_create("dsobase", MFD_CLOEXEC); + ATF_REQUIRE(nfd >= 0); + ATF_REQUIRE(ftruncate(nfd, dsosz) == 0); + ATF_REQUIRE(write(nfd, dsomap, dsosz) == dsosz); + + handles[i] = fdlopen(nfd, RTLD_LAZY); + ATF_REQUIRE(handles[i] != NULL); + if (i > 0) + ATF_REQUIRE(handles[i] != handles[i - 1]); + + close(nfd); + } + + error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv); + ATF_REQUIRE(error == 0); + waitres = waitpid(pid, &status, 0); + ATF_REQUIRE(waitres == pid); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0); +} + ATF_TP_ADD_TCS(tp) { @@ -181,6 +248,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback); ATF_TP_ADD_TC(tp, posix_spawnp_enoexec_fallback_null_argv0); ATF_TP_ADD_TC(tp, posix_spawnp_eacces); + ATF_TP_ADD_TC(tp, posix_spawnp_stackunderflow); return (atf_no_error()); }