summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/syscalls
diff options
context:
space:
mode:
authorIan Gudger <igudger@google.com>2018-06-21 10:52:33 -0700
committerShentubot <shentubot@google.com>2018-06-21 10:53:21 -0700
commitd571a4359cebbcf8a9b201bb125f1cdc9fb126e4 (patch)
tree53d993db5ab045897c4ad50bb73670e3f018ffea /pkg/sentry/syscalls
parentf2a687001ded18a4343c1aa3bfba18b08c6a816a (diff)
Implement ioctl(FIOASYNC)
FIOASYNC and friends are used to send signals when a file is ready for IO. This may or may not be needed by Nginx. While Nginx does use it, it is unclear if the code that uses it has any effect. PiperOrigin-RevId: 201550828 Change-Id: I7ba05a7db4eb2dfffde11e9bd9a35b65b98d7f50
Diffstat (limited to 'pkg/sentry/syscalls')
-rw-r--r--pkg/sentry/syscalls/linux/BUILD1
-rw-r--r--pkg/sentry/syscalls/linux/flags.go5
-rw-r--r--pkg/sentry/syscalls/linux/sys_file.go78
3 files changed, 78 insertions, 6 deletions
diff --git a/pkg/sentry/syscalls/linux/BUILD b/pkg/sentry/syscalls/linux/BUILD
index 7cfd37fb1..d3f3cc459 100644
--- a/pkg/sentry/syscalls/linux/BUILD
+++ b/pkg/sentry/syscalls/linux/BUILD
@@ -82,6 +82,7 @@ go_library(
"//pkg/sentry/kernel/auth",
"//pkg/sentry/kernel/epoll",
"//pkg/sentry/kernel/eventfd",
+ "//pkg/sentry/kernel/fasync",
"//pkg/sentry/kernel/kdefs",
"//pkg/sentry/kernel/pipe",
"//pkg/sentry/kernel/sched",
diff --git a/pkg/sentry/syscalls/linux/flags.go b/pkg/sentry/syscalls/linux/flags.go
index 82bfd7c2a..3d39a20f4 100644
--- a/pkg/sentry/syscalls/linux/flags.go
+++ b/pkg/sentry/syscalls/linux/flags.go
@@ -61,6 +61,9 @@ func flagsToLinux(flags fs.FileFlags) (mask uint) {
if flags.Directory {
mask |= syscall.O_DIRECTORY
}
+ if flags.Async {
+ mask |= syscall.O_ASYNC
+ }
switch {
case flags.Read && flags.Write:
mask |= syscall.O_RDWR
@@ -82,6 +85,7 @@ func linuxToFlags(mask uint) (flags fs.FileFlags) {
Write: (mask & syscall.O_ACCMODE) != syscall.O_RDONLY,
Append: mask&syscall.O_APPEND != 0,
Directory: mask&syscall.O_DIRECTORY != 0,
+ Async: mask&syscall.O_ASYNC != 0,
}
}
@@ -91,5 +95,6 @@ func linuxToSettableFlags(mask uint) fs.SettableFileFlags {
Direct: mask&syscall.O_DIRECT != 0,
NonBlocking: mask&syscall.O_NONBLOCK != 0,
Append: mask&syscall.O_APPEND != 0,
+ Async: mask&syscall.O_ASYNC != 0,
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go
index e2980842f..490649f87 100644
--- a/pkg/sentry/syscalls/linux/sys_file.go
+++ b/pkg/sentry/syscalls/linux/sys_file.go
@@ -25,6 +25,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/lock"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/auth"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/fasync"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/kdefs"
ktime "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
"gvisor.googlesource.com/gvisor/pkg/sentry/limits"
@@ -528,6 +529,33 @@ func Ioctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
file.SetFlags(flags.Settable())
return 0, nil, nil
+ case linux.FIOASYNC:
+ var set int32
+ if _, err := t.CopyIn(args[2].Pointer(), &set); err != nil {
+ return 0, nil, err
+ }
+ flags := file.Flags()
+ if set != 0 {
+ flags.Async = true
+ } else {
+ flags.Async = false
+ }
+ file.SetFlags(flags.Settable())
+ return 0, nil, nil
+
+ case linux.FIOSETOWN, linux.SIOCSPGRP:
+ var set int32
+ if _, err := t.CopyIn(args[2].Pointer(), &set); err != nil {
+ return 0, nil, err
+ }
+ fSetOwn(t, file, set)
+ return 0, nil, nil
+
+ case linux.FIOGETOWN, linux.SIOCGPGRP:
+ who := fGetOwn(t, file)
+ _, err := t.CopyOut(args[2].Pointer(), &who)
+ return 0, nil, err
+
default:
ret, err := file.FileOperations.Ioctl(t, t.MemoryManager(), args)
if err != nil {
@@ -725,6 +753,39 @@ func Dup3(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
return uintptr(newfd), nil, nil
}
+func fGetOwn(t *kernel.Task, file *fs.File) int32 {
+ ma := file.Async(nil)
+ if ma == nil {
+ return 0
+ }
+ a := ma.(*fasync.FileAsync)
+ ot, otg, opg := a.Owner()
+ switch {
+ case ot != nil:
+ return int32(t.PIDNamespace().IDOfTask(ot))
+ case otg != nil:
+ return int32(t.PIDNamespace().IDOfThreadGroup(otg))
+ case opg != nil:
+ return int32(-t.PIDNamespace().IDOfProcessGroup(opg))
+ default:
+ return 0
+ }
+}
+
+// fSetOwn sets the file's owner with the semantics of F_SETOWN in Linux.
+//
+// If who is positive, it represents a PID. If negative, it represents a PGID.
+// If the PID or PGID is invalid, the owner is silently unset.
+func fSetOwn(t *kernel.Task, file *fs.File, who int32) {
+ a := file.Async(fasync.New).(*fasync.FileAsync)
+ if who < 0 {
+ pg := t.PIDNamespace().ProcessGroupWithID(kernel.ProcessGroupID(-who))
+ a.SetOwnerProcessGroup(t, pg)
+ }
+ tg := t.PIDNamespace().ThreadGroupWithID(kernel.ThreadID(who))
+ a.SetOwnerThreadGroup(t, tg)
+}
+
// Fcntl implements linux syscall fcntl(2).
func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
fd := kdefs.FD(args[0].Int())
@@ -737,7 +798,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
defer file.DecRef()
switch cmd {
- case syscall.F_DUPFD, syscall.F_DUPFD_CLOEXEC:
+ case linux.F_DUPFD, linux.F_DUPFD_CLOEXEC:
from := kdefs.FD(args[2].Int())
fdFlags := kernel.FDFlags{CloseOnExec: cmd == syscall.F_DUPFD_CLOEXEC}
fd, err := t.FDMap().NewFDFrom(from, file, fdFlags, t.ThreadGroup().Limits())
@@ -745,19 +806,19 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return 0, nil, err
}
return uintptr(fd), nil, nil
- case syscall.F_GETFD:
+ case linux.F_GETFD:
return uintptr(fdFlagsToLinux(flags)), nil, nil
- case syscall.F_SETFD:
+ case linux.F_SETFD:
flags := args[2].Uint()
t.FDMap().SetFlags(fd, kernel.FDFlags{
CloseOnExec: flags&syscall.FD_CLOEXEC != 0,
})
- case syscall.F_GETFL:
+ case linux.F_GETFL:
return uintptr(flagsToLinux(file.Flags())), nil, nil
- case syscall.F_SETFL:
+ case linux.F_SETFL:
flags := uint(args[2].Uint())
file.SetFlags(linuxToSettableFlags(flags))
- case syscall.F_SETLK, syscall.F_SETLKW:
+ case linux.F_SETLK, linux.F_SETLKW:
// In Linux the file system can choose to provide lock operations for an inode.
// Normally pipe and socket types lack lock operations. We diverge and use a heavy
// hammer by only allowing locks on files and directories.
@@ -854,6 +915,11 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
default:
return 0, nil, syserror.EINVAL
}
+ case linux.F_GETOWN:
+ return uintptr(fGetOwn(t, file)), nil, nil
+ case linux.F_SETOWN:
+ fSetOwn(t, file, args[2].Int())
+ return 0, nil, nil
default:
// Everything else is not yet supported.
return 0, nil, syserror.EINVAL