diff options
Diffstat (limited to 'pkg/sentry/syscalls')
-rw-r--r-- | pkg/sentry/syscalls/linux/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/syscalls/linux/flags.go | 5 | ||||
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_file.go | 78 |
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 |