diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2026-06-23 22:47:02 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2026-06-30 17:00:23 +0000 |
| commit | 1491dec424e72a2f429d84d11b0d248abc6c6cda (patch) | |
| tree | d7ecca8360e4750d4347d8f75b8f7730569754c9 | |
| parent | 713747f87c85e9b961e460cb9a496c094a6aa375 (diff) | |
posixshm: Disallow truncation of largepage objects
We correctly handled ftruncate(), but not open(O_TRUNC).
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/D57831
| -rw-r--r-- | sys/kern/uipc_shm.c | 8 | ||||
| -rw-r--r-- | tests/sys/posixshm/posixshm_test.c | 38 |
2 files changed, 41 insertions, 5 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index d965576ecd9c..b1b6a8657d69 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -786,7 +786,7 @@ shm_dotruncate_largepage(struct shmfd *shmfd, off_t length, void *rl_cookie) vm_pindex_t oldobjsz __unused; int aflags, error, i, psind, try; - KASSERT(length >= 0, ("shm_dotruncate: length < 0")); + KASSERT(length >= 0, ("shm_dotruncate_largepage: length < 0")); object = shmfd->shm_object; VM_OBJECT_ASSERT_WLOCKED(object); rangelock_cookie_assert(rl_cookie, RA_WLOCKED); @@ -1334,15 +1334,13 @@ kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, if (error == 0 && (flags & (O_ACCMODE | O_TRUNC)) == (O_RDWR | O_TRUNC)) { - VM_OBJECT_WLOCK(shmfd->shm_object); #ifdef MAC error = mac_posixshm_check_truncate( - td->td_ucred, fp->f_cred, shmfd); + td->td_ucred, fp->f_cred, shmfd); if (error == 0) #endif - error = shm_dotruncate_locked(shmfd, 0, + error = shm_dotruncate_cookie(shmfd, 0, rl_cookie); - VM_OBJECT_WUNLOCK(shmfd->shm_object); } if (error == 0) { /* diff --git a/tests/sys/posixshm/posixshm_test.c b/tests/sys/posixshm/posixshm_test.c index 6729c33a789d..e816e2d1efa7 100644 --- a/tests/sys/posixshm/posixshm_test.c +++ b/tests/sys/posixshm/posixshm_test.c @@ -2148,6 +2148,43 @@ ATF_TC_BODY(largepage_reopen, tc) "close failed; errno=%d", errno); } +ATF_TC_WITHOUT_HEAD(largepage_truncate); +ATF_TC_BODY(largepage_truncate, tc) +{ + size_t ps[MAXPAGESIZES]; + int fd, psind; + + (void)pagesizes(ps, true); + psind = 1; + + gen_test_path(); + fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind, + SHM_LARGEPAGE_ALLOC_DEFAULT, 0600); + if (fd < 0 && errno == ENOTTY) + atf_tc_skip("no large page support"); + ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno); + + ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0, + "ftruncate failed; error=%d", errno); + + ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno); + + fd = shm_open(test_path, O_RDWR | O_TRUNC, 0); + ATF_REQUIRE_MSG(fd == -1, "shm_open(O_TRUNC) should have failed"); + ATF_REQUIRE_ERRNO(ENOTSUP, fd == -1); + + fd = shm_open(test_path, O_RDWR, 0); + ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); + + ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0, + "ftruncate to same size failed; error=%d", errno); + + ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, + "shm_unlink failed; errno=%d", errno); + ATF_REQUIRE_MSG(close(fd) == 0, + "close failed; errno=%d", errno); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, remap_object); @@ -2199,6 +2236,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, largepage_pkru); #endif ATF_TP_ADD_TC(tp, largepage_reopen); + ATF_TP_ADD_TC(tp, largepage_truncate); return (atf_no_error()); } |
