summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2021-09-16 12:10:03 -0700
committergVisor bot <gvisor-bot@google.com>2021-09-16 12:12:59 -0700
commit51b96514cd9397870b39506e3693017a355319dd (patch)
tree46f465ed03e12efdff1625886604558968d94f56 /test
parent282a4dd52b337dccfb578e9d32dd1005c864dd8d (diff)
Limit most file mmaps to the range of an int64.
In the general case, files may have offsets between MaxInt64 and MaxUint64; in Linux pgoff is consistently represented by an unsigned long, and in gVisor the offset types in memmap.MappableRange are uint64. However, regular file mmap is constrained to int64 offsets (on 64-bit systems) by mm/mmap.c:file_mmap_size_max() => MAX_LFS_FILESIZE == LLONG_MAX. As a related fix, check for chunkStart overflow in fsutil.HostFileMapper; chunk offsets are uint64s, but as noted above some file types may use uint64 offsets beyond MaxInt64. Reported-by: syzbot+71342a1585aed97ed9f7@syzkaller.appspotmail.com PiperOrigin-RevId: 397136751
Diffstat (limited to 'test')
-rw-r--r--test/syscalls/linux/mmap.cc41
1 files changed, 35 insertions, 6 deletions
diff --git a/test/syscalls/linux/mmap.cc b/test/syscalls/linux/mmap.cc
index fda176261..bb2a0cb57 100644
--- a/test/syscalls/linux/mmap.cc
+++ b/test/syscalls/linux/mmap.cc
@@ -29,6 +29,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <limits>
#include <vector>
#include "gmock/gmock.h"
@@ -913,13 +914,41 @@ TEST_F(MMapFileTest, MapOffsetBeyondEnd) {
::testing::KilledBySignal(SIGBUS), "");
}
-// Verify mmap fails when sum of length and offset overflows.
-TEST_F(MMapFileTest, MapLengthPlusOffsetOverflows) {
+TEST_F(MMapFileTest, MapSecondToLastPositivePage) {
SKIP_IF(!FSSupportsMap());
- const size_t length = static_cast<size_t>(-kPageSize);
- const off_t offset = kPageSize;
- ASSERT_THAT(Map(0, length, PROT_READ, MAP_PRIVATE, fd_.get(), offset),
- SyscallFailsWithErrno(ENOMEM));
+ EXPECT_THAT(
+ Map(0, kPageSize, PROT_READ, MAP_SHARED, fd_.get(),
+ (std::numeric_limits<off_t>::max() - kPageSize) & ~(kPageSize - 1)),
+ SyscallSucceeds());
+}
+
+TEST_F(MMapFileTest, MapLastPositivePage) {
+ SKIP_IF(!FSSupportsMap());
+ // For regular files, this should fail due to integer overflow of the end
+ // offset.
+ EXPECT_THAT(Map(0, kPageSize, PROT_READ, MAP_SHARED, fd_.get(),
+ std::numeric_limits<off_t>::max() & ~(kPageSize - 1)),
+ SyscallFailsWithErrno(EOVERFLOW));
+}
+
+TEST_F(MMapFileTest, MapFirstNegativePage) {
+ SKIP_IF(!FSSupportsMap());
+ EXPECT_THAT(Map(0, kPageSize, PROT_READ, MAP_SHARED, fd_.get(),
+ std::numeric_limits<off_t>::min()),
+ SyscallFailsWithErrno(EOVERFLOW));
+}
+
+TEST_F(MMapFileTest, MapSecondToLastNegativePage) {
+ SKIP_IF(!FSSupportsMap());
+ EXPECT_THAT(
+ Map(0, kPageSize, PROT_READ, MAP_SHARED, fd_.get(), -(2 * kPageSize)),
+ SyscallFailsWithErrno(EOVERFLOW));
+}
+
+TEST_F(MMapFileTest, MapLastNegativePage) {
+ SKIP_IF(!FSSupportsMap());
+ EXPECT_THAT(Map(0, kPageSize, PROT_READ, MAP_SHARED, fd_.get(), -kPageSize),
+ SyscallFailsWithErrno(EOVERFLOW));
}
// MAP_PRIVATE PROT_WRITE is allowed on read-only FDs.