summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2020-09-03 23:29:13 -0700
committergVisor bot <gvisor-bot@google.com>2020-09-03 23:30:47 -0700
commitc564293b65eefcf1342023694e4aae82314de014 (patch)
tree053a2bbe2de3b980a48987f9d0fb66dae9e72bf3
parentb6d6a120d07ec0d1b3c0a3abc9e78b6e0bbd3966 (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/BUILD1
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/splice.go22
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