[vfs2][gofer] Fix file creation flags sent to gofer.

Fixes php runtime test ext/standard/tests/file/readfile_basic.phpt
Fixes #3516

fsgofers only want the access mode in the OpenFlags passed to Create(). If more
flags are supplied (like O_APPEND in this case), read/write from that fd will
fail with EBADF. See runsc/fsgofer/fsgofer.go:WriteAt()
VFS2 was providing more than just access modes. So filtering the flags using
p9.OpenFlagsModeMask == linux.O_ACCMODE fixes the issue.

Gofer in VFS1 also only extracts the access mode flags while making the create
RPC. See pkg/sentry/fs/gofer/path.go:Create()

Even in VFS2, when we open a handle, we extract out only the access mode flags
+ O_TRUNC.
See third_party/gvisor/pkg/sentry/fsimpl/gofer/handle.go:openHandle()

Added a test for this.

PiperOrigin-RevId: 326574829
This commit is contained in:
Ayush Ranjan
2020-08-13 19:33:56 -07:00
committed by gVisor bot
parent d3bb50ebf8
commit d6520e1d05
2 changed files with 22 additions and 4 deletions
+2 -4
View File
@@ -1082,10 +1082,8 @@ func (d *dentry) createAndOpenChildLocked(ctx context.Context, rp *vfs.Resolving
}
creds := rp.Credentials()
name := rp.Component()
// Filter file creation flags and O_LARGEFILE out; the create RPC already
// has the semantics of O_CREAT|O_EXCL, while some servers will choke on
// O_LARGEFILE.
createFlags := p9.OpenFlags(opts.Flags &^ (vfs.FileCreationFlags | linux.O_LARGEFILE))
// We only want the access mode for creating the file.
createFlags := p9.OpenFlags(opts.Flags) & p9.OpenFlagsModeMask
fdobj, openFile, createQID, _, err := dirfile.create(ctx, name, createFlags, (p9.FileMode)(opts.Mode), (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
if err != nil {
dirfile.close(ctx)
+20
View File
@@ -147,6 +147,26 @@ TEST_F(OpenTest, WriteOnly) {
EXPECT_THAT(write(wo_file.get(), &buf, 1), SyscallSucceedsWithValue(1));
}
TEST_F(OpenTest, CreateWithAppend) {
std::string data = "text";
std::string new_file = NewTempAbsPath();
const FileDescriptor file = ASSERT_NO_ERRNO_AND_VALUE(
Open(new_file, O_WRONLY | O_APPEND | O_CREAT, 0666));
EXPECT_THAT(write(file.get(), data.c_str(), data.size()),
SyscallSucceedsWithValue(data.size()));
EXPECT_THAT(lseek(file.get(), 0, SEEK_SET), SyscallSucceeds());
EXPECT_THAT(write(file.get(), data.c_str(), data.size()),
SyscallSucceedsWithValue(data.size()));
// Check that the size of the file is correct and that the offset has been
// incremented to that size.
struct stat s0;
EXPECT_THAT(fstat(file.get(), &s0), SyscallSucceeds());
EXPECT_EQ(s0.st_size, 2 * data.size());
EXPECT_THAT(lseek(file.get(), 0, SEEK_CUR),
SyscallSucceedsWithValue(2 * data.size()));
}
TEST_F(OpenTest, ReadWrite) {
char buf;
const FileDescriptor rw_file =