git: 713747f87c85 - main - posixshm: Disallow fspacectl() on largepage objects

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 30 Jun 2026 17:19:12 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=713747f87c85e9b961e460cb9a496c094a6aa375

commit 713747f87c85e9b961e460cb9a496c094a6aa375
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-06-24 19:56:07 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-06-30 17:00:23 +0000

    posixshm: Disallow fspacectl() on largepage objects
    
    As with truncation, the operation isn't supported, but nothing prevented
    it.
    
    Add a regression test.
    
    Approved by:    so
    Security:       FreeBSD-SA-26:44.posixshm
    Security:       CVE-2026-49428
    Reported by:    Chris Jarrett-Davies <chrisjd@openai.com>
    Reviewed by:    kib
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D57830
---
 sys/kern/uipc_shm.c                |  5 ++++-
 tests/sys/posixshm/posixshm_test.c | 22 ++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 197409d97f0c..d965576ecd9c 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -2096,11 +2096,14 @@ shm_fspacectl(struct file *fp, int cmd, off_t *offset, off_t *length, int flags,
 	    ("shm_fspacectl: non-zero flags"));
 	KASSERT(*offset >= 0 && *length > 0 && *length <= OFF_MAX - *offset,
 	    ("shm_fspacectl: offset/length overflow or underflow"));
-	error = EINVAL;
+
 	shmfd = fp->f_data;
 	off = *offset;
 	len = *length;
 
+	if (shm_largepage(shmfd))
+		return (ENOTSUP);
+
 	rl_cookie = shm_rangelock_wlock(shmfd, off, off + len);
 	switch (cmd) {
 	case SPACECTL_DEALLOC:
diff --git a/tests/sys/posixshm/posixshm_test.c b/tests/sys/posixshm/posixshm_test.c
index fe6386c6aa4b..6729c33a789d 100644
--- a/tests/sys/posixshm/posixshm_test.c
+++ b/tests/sys/posixshm/posixshm_test.c
@@ -1369,6 +1369,27 @@ ATF_TC_BODY(largepage_config, tc)
 	ATF_REQUIRE(close(fd) == 0);
 }
 
+ATF_TC_WITHOUT_HEAD(largepage_fspacectl);
+ATF_TC_BODY(largepage_fspacectl, tc)
+{
+	struct spacectl_range range;
+	size_t ps[MAXPAGESIZES];
+	int fd, pscnt;
+
+	pscnt = pagesizes(ps, true);
+
+	for (int i = 1; i < pscnt; i++) {
+		fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+
+		range.r_offset = 0;
+		range.r_len = ps[i];
+		ATF_REQUIRE_ERRNO(ENOTSUP,
+		    fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == -1);
+
+		ATF_REQUIRE(close(fd) == 0);
+	}
+}
+
 ATF_TC_WITHOUT_HEAD(largepage_mmap);
 ATF_TC_BODY(largepage_mmap, tc)
 {
@@ -2165,6 +2186,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, mmap_prot);
 	ATF_TP_ADD_TC(tp, largepage_basic);
 	ATF_TP_ADD_TC(tp, largepage_config);
+	ATF_TP_ADD_TC(tp, largepage_fspacectl);
 	ATF_TP_ADD_TC(tp, largepage_mmap);
 	ATF_TP_ADD_TC(tp, largepage_munmap);
 	ATF_TP_ADD_TC(tp, largepage_madvise);