diff options
author | Dean Deng <deandeng@google.com> | 2020-09-03 23:29:13 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-09-03 23:30:47 -0700 |
commit | c564293b65eefcf1342023694e4aae82314de014 (patch) | |
tree | 053a2bbe2de3b980a48987f9d0fb66dae9e72bf3 | |
parent | b6d6a120d07ec0d1b3c0a3abc9e78b6e0bbd3966 (diff) |
Adjust input file offset when sendfile only completes a partial write.
Fixes #3779.
PiperOrigin-RevId: 330057268
-rw-r--r-- | pkg/sentry/syscalls/linux/vfs2/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/syscalls/linux/vfs2/splice.go | 22 |
2 files changed, 15 insertions, 8 deletions
diff --git a/pkg/sentry/syscalls/linux/vfs2/BUILD b/pkg/sentry/syscalls/linux/vfs2/BUILD index 64696b438..0030dee39 100644 --- a/pkg/sentry/syscalls/linux/vfs2/BUILD +++ b/pkg/sentry/syscalls/linux/vfs2/BUILD @@ -44,6 +44,7 @@ go_library( "//pkg/context", "//pkg/fspath", "//pkg/gohacks", + "//pkg/log", "//pkg/sentry/arch", "//pkg/sentry/fs/lock", "//pkg/sentry/fsbridge", diff --git a/pkg/sentry/syscalls/linux/vfs2/splice.go b/pkg/sentry/syscalls/linux/vfs2/splice.go index 68ce94778..5543cfac2 100644 --- a/pkg/sentry/syscalls/linux/vfs2/splice.go +++ b/pkg/sentry/syscalls/linux/vfs2/splice.go @@ -18,6 +18,7 @@ import ( "io" "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sentry/arch" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/kernel/pipe" @@ -390,16 +391,21 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc err = dw.waitForOut(t) } if err != nil { - // We didn't complete the write. Only - // report the bytes that were actually - // written, and rewind the offset. + // We didn't complete the write. Only report the bytes that were actually + // written, and rewind offsets as needed. notWritten := int64(len(wbuf)) n -= notWritten - if offset != -1 { - // TODO(gvisor.dev/issue/3779): The inFile offset will be incorrect if we - // roll back, because it has already been advanced by the full amount. - // Merely seeking on inFile does not work, because there may be concurrent - // file operations. + if offset == -1 { + // We modified the offset of the input file itself during the read + // operation. Rewind it. + if _, seekErr := inFile.Seek(t, -notWritten, linux.SEEK_CUR); seekErr != nil { + // Log the error but don't return it, since the write has already + // completed successfully. + log.Warningf("failed to roll back input file offset: %v", seekErr) + } + } else { + // The sendfile call was provided an offset parameter that should be + // adjusted to reflect the number of bytes sent. Rewind it. offset -= notWritten } break |