vfs2: implement fcntl(fd, F_SETFL, flags)

PiperOrigin-RevId: 316148074
This commit is contained in:
Andrei Vagin 2020-06-12 11:56:43 -07:00 committed by gVisor bot
parent 61d6c059ac
commit 6ec9d60403
4 changed files with 36 additions and 4 deletions

View File

@ -458,6 +458,29 @@ func (f *FDTable) SetFlags(fd int32, flags FDFlags) error {
return nil return nil
} }
// SetFlagsVFS2 sets the flags for the given file descriptor.
//
// True is returned iff flags were changed.
func (f *FDTable) SetFlagsVFS2(fd int32, flags FDFlags) error {
if fd < 0 {
// Don't accept negative FDs.
return syscall.EBADF
}
f.mu.Lock()
defer f.mu.Unlock()
file, _, _ := f.getVFS2(fd)
if file == nil {
// No file found.
return syscall.EBADF
}
// Update the flags.
f.setVFS2(fd, file, flags)
return nil
}
// Get returns a reference to the file and the flags for the FD or nil if no // Get returns a reference to the file and the flags for the FD or nil if no
// file is defined for the given fd. // file is defined for the given fd.
// //

View File

@ -935,10 +935,10 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return uintptr(flags.ToLinuxFDFlags()), nil, nil return uintptr(flags.ToLinuxFDFlags()), nil, nil
case linux.F_SETFD: case linux.F_SETFD:
flags := args[2].Uint() flags := args[2].Uint()
t.FDTable().SetFlags(fd, kernel.FDFlags{ err := t.FDTable().SetFlags(fd, kernel.FDFlags{
CloseOnExec: flags&linux.FD_CLOEXEC != 0, CloseOnExec: flags&linux.FD_CLOEXEC != 0,
}) })
return 0, nil, nil return 0, nil, err
case linux.F_GETFL: case linux.F_GETFL:
return uintptr(file.Flags().ToLinux()), nil, nil return uintptr(file.Flags().ToLinux()), nil, nil
case linux.F_SETFL: case linux.F_SETFL:

View File

@ -134,10 +134,10 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return uintptr(flags.ToLinuxFDFlags()), nil, nil return uintptr(flags.ToLinuxFDFlags()), nil, nil
case linux.F_SETFD: case linux.F_SETFD:
flags := args[2].Uint() flags := args[2].Uint()
t.FDTable().SetFlags(fd, kernel.FDFlags{ err := t.FDTable().SetFlagsVFS2(fd, kernel.FDFlags{
CloseOnExec: flags&linux.FD_CLOEXEC != 0, CloseOnExec: flags&linux.FD_CLOEXEC != 0,
}) })
return 0, nil, nil return 0, nil, err
case linux.F_GETFL: case linux.F_GETFL:
return uintptr(file.StatusFlags()), nil, nil return uintptr(file.StatusFlags()), nil, nil
case linux.F_SETFL: case linux.F_SETFL:

View File

@ -115,6 +115,15 @@ PosixErrorOr<Cleanup> SubprocessLock(std::string const& path, bool for_write,
return std::move(cleanup); return std::move(cleanup);
} }
TEST(FcntlTest, SetCloExecBadFD) {
// Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set.
FileDescriptor f = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
auto fd = f.get();
f.reset();
ASSERT_THAT(fcntl(fd, F_GETFD), SyscallFailsWithErrno(EBADF));
ASSERT_THAT(fcntl(fd, F_SETFD, FD_CLOEXEC), SyscallFailsWithErrno(EBADF));
}
TEST(FcntlTest, SetCloExec) { TEST(FcntlTest, SetCloExec) {
// Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set. // Open an eventfd file descriptor with FD_CLOEXEC descriptor flag not set.
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0)); FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));