diff options
author | Jamie Liu <jamieliu@google.com> | 2019-03-28 11:42:38 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-03-28 11:43:51 -0700 |
commit | f005350c93cb9e2a247b0d8a061e52f3160d36d4 (patch) | |
tree | ff60d4ebf0d329fba52198ff284787b35e0365ac /test/syscalls | |
parent | 1d7e2bc3776f90e1b2b31346e1bec47da6e568ff (diff) |
Clean up gofer handle caching.
- Document fsutil.CachedFileObject.FD() requirements on access
permissions, and change gofer.inodeFileState.FD() to honor them.
Fixes #147.
- Combine gofer.inodeFileState.readonly and
gofer.inodeFileState.readthrough, and simplify handle caching logic.
- Inline gofer.cachePolicy.cacheHandles into
gofer.inodeFileState.setSharedHandles, because users with access to
gofer.inodeFileState don't necessarily have access to the fs.Inode
(predictably, this is a save/restore problem).
Before this CL:
$ docker run --runtime=runsc-d -v $(pwd)/gvisor/repro:/root/repro -it ubuntu bash
root@34d51017ed67:/# /root/repro/runsc-b147
mmap: 0x7f3c01e45000
Segmentation fault
After this CL:
$ docker run --runtime=runsc-d -v $(pwd)/gvisor/repro:/root/repro -it ubuntu bash
root@d3c3cb56bbf9:/# /root/repro/runsc-b147
mmap: 0x7f78987ec000
o
PiperOrigin-RevId: 240818413
Change-Id: I49e1d4a81a0cb9177832b0a9f31a10da722a896b
Diffstat (limited to 'test/syscalls')
-rw-r--r-- | test/syscalls/linux/mmap.cc | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/test/syscalls/linux/mmap.cc b/test/syscalls/linux/mmap.cc index afe060d33..b500e79a4 100644 --- a/test/syscalls/linux/mmap.cc +++ b/test/syscalls/linux/mmap.cc @@ -1696,6 +1696,29 @@ TEST(MMapDeathTest, TruncateAfterCOWBreak) { ::testing::KilledBySignal(SIGBUS), ""); } +// Regression test for #147. +TEST(MMapNoFixtureTest, MapReadOnlyAfterCreateWriteOnly) { + std::string filename = NewTempAbsPath(); + + // We have to create the file O_RDONLY to reproduce the bug because + // fsgofer.localFile.Create() silently upgrades O_WRONLY to O_RDWR, causing + // the cached "write-only" FD to be read/write and therefore usable by mmap(). + auto const ro_fd = ASSERT_NO_ERRNO_AND_VALUE( + Open(filename, O_RDONLY | O_CREAT | O_EXCL, 0666)); + + // Get a write-only FD for the same file, which should be ignored by mmap() + // (but isn't in #147). + auto const wo_fd = ASSERT_NO_ERRNO_AND_VALUE(Open(filename, O_WRONLY)); + ASSERT_THAT(ftruncate(wo_fd.get(), kPageSize), SyscallSucceeds()); + + auto const mapping = ASSERT_NO_ERRNO_AND_VALUE( + Mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, ro_fd.get(), 0)); + std::vector<char> buf(kPageSize); + // The test passes if this survives. + std::copy(static_cast<char*>(mapping.ptr()), + static_cast<char*>(mapping.endptr()), buf.data()); +} + // Conditional on MAP_32BIT. #ifdef __x86_64__ |