summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2019-05-22 18:10:54 -0700
committerShentubot <shentubot@google.com>2019-05-22 18:11:50 -0700
commitf65dfec09650768626a9af916b0487afa557a930 (patch)
tree82ba72c03dbacea61ba1dca911795d6dd7bafaa2 /pkg
parent21915eb58b875809b60c0a43e53a97ea0560c299 (diff)
Add WCLONE / WALL support to waitid
The previous commit adds WNOTHREAD support to waitid, so we may as well complete the upstream change. Linux added WCLONE, WALL, WNOTHREAD support to waitid(2) in 91c4e8ea8f05916df0c8a6f383508ac7c9e10dba ("wait: allow sys_waitid() to accept __WNOTHREAD/__WCLONE/__WALL"). i.e., Linux 4.7. PiperOrigin-RevId: 249560587 Change-Id: Iff177b0848a3f7bae6cb5592e44500c5a942fbeb
Diffstat (limited to 'pkg')
-rw-r--r--pkg/sentry/syscalls/linux/sys_thread.go67
1 files changed, 35 insertions, 32 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_thread.go b/pkg/sentry/syscalls/linux/sys_thread.go
index 14fa7ef92..26f7e8ead 100644
--- a/pkg/sentry/syscalls/linux/sys_thread.go
+++ b/pkg/sentry/syscalls/linux/sys_thread.go
@@ -181,6 +181,32 @@ func Vfork(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return clone(t, syscall.CLONE_VM|syscall.CLONE_VFORK|int(syscall.SIGCHLD), 0, 0, 0, 0)
}
+// parseCommonWaitOptions applies the options common to wait4 and waitid to
+// wopts.
+func parseCommonWaitOptions(wopts *kernel.WaitOptions, options int) error {
+ switch options & (linux.WCLONE | linux.WALL) {
+ case 0:
+ wopts.NonCloneTasks = true
+ case linux.WCLONE:
+ wopts.CloneTasks = true
+ case linux.WALL:
+ wopts.NonCloneTasks = true
+ wopts.CloneTasks = true
+ default:
+ return syscall.EINVAL
+ }
+ if options&linux.WCONTINUED != 0 {
+ wopts.Events |= kernel.EventGroupContinue
+ }
+ if options&linux.WNOHANG == 0 {
+ wopts.BlockInterruptErr = kernel.ERESTARTSYS
+ }
+ if options&linux.WNOTHREAD == 0 {
+ wopts.SiblingChildren = true
+ }
+ return nil
+}
+
// wait4 waits for the given child process to exit.
func wait4(t *kernel.Task, pid int, statusAddr usermem.Addr, options int, rusageAddr usermem.Addr) (uintptr, error) {
if options&^(linux.WNOHANG|linux.WUNTRACED|linux.WCONTINUED|linux.WNOTHREAD|linux.WALL|linux.WCLONE) != 0 {
@@ -207,29 +233,12 @@ func wait4(t *kernel.Task, pid int, statusAddr usermem.Addr, options int, rusage
wopts.SpecificTID = kernel.ThreadID(pid)
}
- switch options & (linux.WCLONE | linux.WALL) {
- case 0:
- wopts.NonCloneTasks = true
- case linux.WCLONE:
- wopts.CloneTasks = true
- case linux.WALL:
- wopts.NonCloneTasks = true
- wopts.CloneTasks = true
- default:
- return 0, syscall.EINVAL
+ if err := parseCommonWaitOptions(&wopts, options); err != nil {
+ return 0, err
}
if options&linux.WUNTRACED != 0 {
wopts.Events |= kernel.EventChildGroupStop
}
- if options&linux.WCONTINUED != 0 {
- wopts.Events |= kernel.EventGroupContinue
- }
- if options&linux.WNOHANG == 0 {
- wopts.BlockInterruptErr = kernel.ERESTARTSYS
- }
- if options&linux.WNOTHREAD == 0 {
- wopts.SiblingChildren = true
- }
wr, err := t.Wait(&wopts)
if err != nil {
@@ -281,16 +290,15 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
options := int(args[3].Uint())
rusageAddr := args[4].Pointer()
- if options&^(linux.WNOHANG|linux.WEXITED|linux.WSTOPPED|linux.WCONTINUED|linux.WNOWAIT|linux.WNOTHREAD) != 0 {
+ if options&^(linux.WNOHANG|linux.WEXITED|linux.WSTOPPED|linux.WCONTINUED|linux.WNOWAIT|linux.WNOTHREAD|linux.WALL|linux.WCLONE) != 0 {
return 0, nil, syscall.EINVAL
}
if options&(linux.WEXITED|linux.WSTOPPED|linux.WCONTINUED) == 0 {
return 0, nil, syscall.EINVAL
}
wopts := kernel.WaitOptions{
- NonCloneTasks: true,
- Events: kernel.EventTraceeStop,
- ConsumeEvent: options&linux.WNOWAIT == 0,
+ Events: kernel.EventTraceeStop,
+ ConsumeEvent: options&linux.WNOWAIT == 0,
}
switch idtype {
case linux.P_ALL:
@@ -301,21 +309,16 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
default:
return 0, nil, syscall.EINVAL
}
+
+ if err := parseCommonWaitOptions(&wopts, options); err != nil {
+ return 0, nil, err
+ }
if options&linux.WEXITED != 0 {
wopts.Events |= kernel.EventExit
}
if options&linux.WSTOPPED != 0 {
wopts.Events |= kernel.EventChildGroupStop
}
- if options&linux.WCONTINUED != 0 {
- wopts.Events |= kernel.EventGroupContinue
- }
- if options&linux.WNOHANG == 0 {
- wopts.BlockInterruptErr = kernel.ERESTARTSYS
- }
- if options&linux.WNOTHREAD == 0 {
- wopts.SiblingChildren = true
- }
wr, err := t.Wait(&wopts)
if err != nil {