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 <[email protected]>
Reviewed by:	kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D57831
This commit is contained in:
Mark Johnston committed 2026-06-29 19:17:30 +00:00
1 parent 1c49551def
commit 9c06b54ab6
2 files changed
+41 -5

No files matched your search

+3 -5
View File
@@ -824,7 +824,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);
@@ -1345,15 +1345,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) {
/*
+38
View File
@@ -2151,6 +2151,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);
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);
@@ -2202,6 +2239,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());
}