From nobody Tue Jun 30 13:13:27 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 4gqNrD4mlSz6kB7n for ; Tue, 30 Jun 2026 13:13:32 +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 4gqNrD1yKXz3HBC for ; Tue, 30 Jun 2026 13:13:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782825212; 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=ko3y6VaoP1wCUb5cogwNdZOs5llN6ZNgECo7xG2KGR32zPtTiFobYoyO3PHHfhuUUlyrgc xeNdKEa+ztN9Hd4srvxvT0jc99ymKHK1tIM3q6tMTJIn5RGPJ9LL6b+u3yRVXDvYZOB+0W AcvZe1Q1DZ5aG2wObclwfgeTGOYNTG8liEay7VqcBX1edKK8MFnVR50jXtNmK+bXkvnkVp N/EEXAowQt+Y6FR+dy9SE/nUYBBNpNi0QashyZ6+85Cfwe5Ze/MdLcqMdq0d9ZmdinhN0O a9vwOOd94cR1WJSaK1rQtXHBEjkAYepL8CDeJMYXJkCtB75VQ/4zLD/ogyT8rw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782825212; a=rsa-sha256; cv=none; b=bWMyKC9dfs5P73k33BcDYkz41KGr1IemCGPgsUc3NfXpyZZxs6o5KSeyfhtXr/pGJLlYgO yUmu+9nu+krZa9jvH2HttOTCPOInIv/2TLgGC1cTIANUwFFAluS2X4AeBDsyKa8TmFjRft AJn1veOQFU1xYJ/oOhkjLa/uv+51jwVEwB91Zmg+kkvMN5g6WAkzO+N2mTZcnZ7BwSbDRx 0MbA7skdySmzuDFC2Kytius5RBod3eaFk0OSkOcAGYm0TSQhVIhj8sevaJr44MkI4T6dDH t89Ir1//p0hq7sm0jEXCVNsbiI4dLTuReIeWtPJBgvoldlDyqIWXZNty35VEcw== 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=1782825212; 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=i8cZUmu8Ta1L5JnjxK+RIMeRDSHPclGtLnQIg6gEDUU0BmqHGxQfXpy/2H0rpubIUPtl8U az9NVB08VyHiqoFtV6nh3D/oUNl6rHQfQygr9jxzgiLLRYUfoHG3eTRLY7ijo0Yt8aj3Gs iksDqGOQZgwn1pnStOOATb1i43fSSeo9q5YVR2RrRwp87c3h4hrRwYAXxMak9NVhovkj22 I7H08fuBgu9SEnrEMLT0kzi14+NxOC0S18003vxdacGEoKaI1QHPyX3q8h15/SgcVY3jr7 mKnWIOA/m+TevLRR9/Xc7frMe5oWFTStGeKGy8Zn8msqDK0R6LGMr50+XmWZcA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gqNrD0QJwzlmd for ; Tue, 30 Jun 2026 13:13:32 +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 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: 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()); }