Fix beyond EOF check for SEEK_DATA and SEEK_HOLE in gofer client.

If offset >= file_size && whence = SEEK_DATA or SEEK_HOLE, then Linux returns
ENXIO. Gofer client was allowing offset == file_size. Fixed that.

PiperOrigin-RevId: 523602673
This commit is contained in:
Ayush Ranjan
2023-04-11 22:17:32 -07:00
committed by gVisor bot
parent eed95da275
commit 3b537e7f0c
3 changed files with 21 additions and 3 deletions
+2 -2
View File
@@ -648,12 +648,12 @@ func regularFileSeekLocked(ctx context.Context, d *dentry, fdOffset, offset int6
case linux.SEEK_END:
offset += size
case linux.SEEK_DATA:
if offset > size {
if offset >= size {
return 0, linuxerr.ENXIO
}
// Use offset as specified.
case linux.SEEK_HOLE:
if offset > size {
if offset >= size {
return 0, linuxerr.ENXIO
}
offset = size
-1
View File
@@ -58,7 +58,6 @@ var exclude = map[string][]string{
"test_fcntl": []string{"TestFcntl.test_fcntl_64_bit"},
// TODO(b/76174079): Un-exclude once this bug is fixed.
"test_posix": []string{
"PosixTester.test_fs_holes", // Fails only with --overlay=none.
"PosixTester.test_sched_priority",
"PosixTester.test_sched_rr_get_interval",
"PosixTester.test_get_and_set_scheduler_and_param", // sched_setparam(2) is not supported.
+19
View File
@@ -195,6 +195,25 @@ TEST(LseekTest, EtcPasswdDup) {
ASSERT_THAT(lseek(fd3.get(), 0, SEEK_CUR), SyscallSucceedsWithValue(1000));
}
TEST(LseekTest, SeekDataAndSeekHole) {
auto file_name = NewTempAbsPath();
std::string contents("DEADBEEF");
ASSERT_NO_ERRNO(CreateWithContents(file_name, contents, 0666));
auto fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file_name, O_RDWR));
// Not all filesystems support SEEK_DATA and SEEK_HOLE yet.
SKIP_IF(lseek(fd.get(), 0, SEEK_DATA) == -1 && errno == EINVAL);
int mid = contents.size() / 2, end = contents.size();
ASSERT_THAT(lseek(fd.get(), mid, SEEK_DATA), SyscallSucceedsWithValue(mid));
ASSERT_THAT(lseek(fd.get(), mid, SEEK_HOLE), SyscallSucceedsWithValue(end));
// "ENXIO whence is SEEK_DATA or SEEK_HOLE, and offset is beyond the end of
// the file" - lseek(2)
ASSERT_THAT(lseek(fd.get(), end, SEEK_DATA), SyscallFailsWithErrno(ENXIO));
ASSERT_THAT(lseek(fd.get(), end, SEEK_HOLE), SyscallFailsWithErrno(ENXIO));
}
// TODO(magi): Add tests where we have donated in sockets.
} // namespace