diff options
author | Fabricio Voznika <fvoznika@google.com> | 2021-03-18 12:14:01 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-03-18 12:19:57 -0700 |
commit | 7fac7e32f3a866134bcee499dfc64459946dfe9d (patch) | |
tree | c678f8e392949072c55d26398e2a5b1b5449c67d /test/syscalls/linux/read.cc | |
parent | 29be908ab69d2d333572f6990d331e494b1e51fd (diff) |
Translate syserror when validating partial IO errors
syserror allows packages to register translators for errors. These
translators should be called prior to checking if the error is valid,
otherwise it may not account for possible errors that can be returned
from different packages, e.g. safecopy.BusError => syserror.EFAULT.
Second attempt, it passes tests now :-)
PiperOrigin-RevId: 363714508
Diffstat (limited to 'test/syscalls/linux/read.cc')
-rw-r--r-- | test/syscalls/linux/read.cc | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/test/syscalls/linux/read.cc b/test/syscalls/linux/read.cc index 98d5e432d..087262535 100644 --- a/test/syscalls/linux/read.cc +++ b/test/syscalls/linux/read.cc @@ -13,11 +13,14 @@ // limitations under the License. #include <fcntl.h> +#include <sys/mman.h> #include <unistd.h> #include <vector> #include "gtest/gtest.h" +#include "absl/base/macros.h" +#include "test/util/cleanup.h" #include "test/util/file_descriptor.h" #include "test/util/temp_path.h" #include "test/util/test_util.h" @@ -121,6 +124,43 @@ TEST_F(ReadTest, ReadWithOpath) { EXPECT_THAT(ReadFd(fd.get(), buf.data(), 1), SyscallFailsWithErrno(EBADF)); } +// Test that partial writes that hit SIGSEGV are correctly handled and return +// partial write. +TEST_F(ReadTest, PartialReadSIGSEGV) { + // Allocate 2 pages and remove permission from the second. + const size_t size = 2 * kPageSize; + void* addr = + mmap(0, size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); + ASSERT_NE(addr, MAP_FAILED); + auto cleanup = Cleanup( + [addr, size] { EXPECT_THAT(munmap(addr, size), SyscallSucceeds()); }); + + FileDescriptor fd = + ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR, 0666)); + for (size_t i = 0; i < 2; i++) { + EXPECT_THAT(pwrite(fd.get(), addr, size, 0), + SyscallSucceedsWithValue(size)); + } + + void* badAddr = reinterpret_cast<char*>(addr) + kPageSize; + ASSERT_THAT(mprotect(badAddr, kPageSize, PROT_NONE), SyscallSucceeds()); + + // Attempt to read to both pages. Create a non-contiguous iovec pair to + // ensure operation is done in 2 steps. + struct iovec iov[] = { + { + .iov_base = addr, + .iov_len = kPageSize, + }, + { + .iov_base = addr, + .iov_len = size, + }, + }; + EXPECT_THAT(preadv(fd.get(), iov, ABSL_ARRAYSIZE(iov), 0), + SyscallSucceedsWithValue(size)); +} + } // namespace } // namespace testing |