Fix sendfile(2) error code
When output file is in append mode, sendfile(2) should fail with EINVAL and not EBADF. Closes #721 PiperOrigin-RevId: 265718958
This commit is contained in:
parent
c39564332b
commit
8fd89fd7a2
|
@ -91,24 +91,31 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get files.
|
// Get files.
|
||||||
outFile := t.GetFile(outFD)
|
|
||||||
if outFile == nil {
|
|
||||||
return 0, nil, syserror.EBADF
|
|
||||||
}
|
|
||||||
defer outFile.DecRef()
|
|
||||||
|
|
||||||
inFile := t.GetFile(inFD)
|
inFile := t.GetFile(inFD)
|
||||||
if inFile == nil {
|
if inFile == nil {
|
||||||
return 0, nil, syserror.EBADF
|
return 0, nil, syserror.EBADF
|
||||||
}
|
}
|
||||||
defer inFile.DecRef()
|
defer inFile.DecRef()
|
||||||
|
|
||||||
// Verify that the outfile Append flag is not set. Note that fs.Splice
|
if !inFile.Flags().Read {
|
||||||
// itself validates that the output file is writable.
|
|
||||||
if outFile.Flags().Append {
|
|
||||||
return 0, nil, syserror.EBADF
|
return 0, nil, syserror.EBADF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outFile := t.GetFile(outFD)
|
||||||
|
if outFile == nil {
|
||||||
|
return 0, nil, syserror.EBADF
|
||||||
|
}
|
||||||
|
defer outFile.DecRef()
|
||||||
|
|
||||||
|
if !outFile.Flags().Write {
|
||||||
|
return 0, nil, syserror.EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the outfile Append flag is not set.
|
||||||
|
if outFile.Flags().Append {
|
||||||
|
return 0, nil, syserror.EINVAL
|
||||||
|
}
|
||||||
|
|
||||||
// Verify that we have a regular infile. This is a requirement; the
|
// Verify that we have a regular infile. This is a requirement; the
|
||||||
// same check appears in Linux (fs/splice.c:splice_direct_to_actor).
|
// same check appears in Linux (fs/splice.c:splice_direct_to_actor).
|
||||||
if !fs.IsRegular(inFile.Dirent.Inode.StableAttr) {
|
if !fs.IsRegular(inFile.Dirent.Inode.StableAttr) {
|
||||||
|
|
|
@ -299,10 +299,30 @@ TEST(SendFileTest, DoNotSendfileIfOutfileIsAppendOnly) {
|
||||||
|
|
||||||
// Open the output file as append only.
|
// Open the output file as append only.
|
||||||
const FileDescriptor outf =
|
const FileDescriptor outf =
|
||||||
ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_APPEND));
|
ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY | O_APPEND));
|
||||||
|
|
||||||
// Send data and verify that sendfile returns the correct errno.
|
// Send data and verify that sendfile returns the correct errno.
|
||||||
EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize),
|
EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize),
|
||||||
|
SyscallFailsWithErrno(EINVAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SendFileTest, AppendCheckOrdering) {
|
||||||
|
constexpr char kData[] = "And by opposing end them: to die, to sleep";
|
||||||
|
constexpr int kDataSize = sizeof(kData) - 1;
|
||||||
|
const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
|
||||||
|
GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
|
||||||
|
|
||||||
|
const FileDescriptor read =
|
||||||
|
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
|
||||||
|
const FileDescriptor write =
|
||||||
|
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY));
|
||||||
|
const FileDescriptor append =
|
||||||
|
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_APPEND));
|
||||||
|
|
||||||
|
// Check that read/write file mode is verified before append.
|
||||||
|
EXPECT_THAT(sendfile(append.get(), read.get(), nullptr, kDataSize),
|
||||||
|
SyscallFailsWithErrno(EBADF));
|
||||||
|
EXPECT_THAT(sendfile(write.get(), write.get(), nullptr, kDataSize),
|
||||||
SyscallFailsWithErrno(EBADF));
|
SyscallFailsWithErrno(EBADF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue