Format struct pollfd in poll(2)/ppoll(2)
I0410 15:40:38.854295 3776 x:0] [ 1] poll_test E poll(0x2b00bfb5c020 [{FD: 0x3 anon_inode:[eventfd], Events: POLLOUT, REvents: ...}], 0x1, 0x1) I0410 15:40:38.854348 3776 x:0] [ 1] poll_test X poll(0x2b00bfb5c020 [{FD: 0x3 anon_inode:[eventfd], Events: POLLOUT|POLLERR|POLLHUP, REvents: POLLOUT}], 0x1, 0x1) = 0x1 (10.765?s) PiperOrigin-RevId: 244269879 Change-Id: If07ba54a486fdeaaedfc0123769b78d1da862307
This commit is contained in:
parent
ce64d9ebf0
commit
c931c8e082
|
@ -11,6 +11,7 @@ go_library(
|
||||||
"futex.go",
|
"futex.go",
|
||||||
"linux64.go",
|
"linux64.go",
|
||||||
"open.go",
|
"open.go",
|
||||||
|
"poll.go",
|
||||||
"ptrace.go",
|
"ptrace.go",
|
||||||
"signal.go",
|
"signal.go",
|
||||||
"socket.go",
|
"socket.go",
|
||||||
|
|
|
@ -24,7 +24,7 @@ var linuxAMD64 = SyscallMap{
|
||||||
4: makeSyscallInfo("stat", Path, Stat),
|
4: makeSyscallInfo("stat", Path, Stat),
|
||||||
5: makeSyscallInfo("fstat", FD, Stat),
|
5: makeSyscallInfo("fstat", FD, Stat),
|
||||||
6: makeSyscallInfo("lstat", Path, Stat),
|
6: makeSyscallInfo("lstat", Path, Stat),
|
||||||
7: makeSyscallInfo("poll", Hex, Hex, Hex),
|
7: makeSyscallInfo("poll", PollFDs, Hex, Hex),
|
||||||
8: makeSyscallInfo("lseek", Hex, Hex, Hex),
|
8: makeSyscallInfo("lseek", Hex, Hex, Hex),
|
||||||
9: makeSyscallInfo("mmap", Hex, Hex, Hex, Hex, FD, Hex),
|
9: makeSyscallInfo("mmap", Hex, Hex, Hex, Hex, FD, Hex),
|
||||||
10: makeSyscallInfo("mprotect", Hex, Hex, Hex),
|
10: makeSyscallInfo("mprotect", Hex, Hex, Hex),
|
||||||
|
@ -288,7 +288,7 @@ var linuxAMD64 = SyscallMap{
|
||||||
268: makeSyscallInfo("fchmodat", FD, Path, Mode),
|
268: makeSyscallInfo("fchmodat", FD, Path, Mode),
|
||||||
269: makeSyscallInfo("faccessat", FD, Path, Oct, Hex),
|
269: makeSyscallInfo("faccessat", FD, Path, Oct, Hex),
|
||||||
270: makeSyscallInfo("pselect6", Hex, Hex, Hex, Hex, Hex, Hex),
|
270: makeSyscallInfo("pselect6", Hex, Hex, Hex, Hex, Hex, Hex),
|
||||||
271: makeSyscallInfo("ppoll", Hex, Hex, Timespec, SigSet, Hex),
|
271: makeSyscallInfo("ppoll", PollFDs, Hex, Timespec, SigSet, Hex),
|
||||||
272: makeSyscallInfo("unshare", CloneFlags),
|
272: makeSyscallInfo("unshare", CloneFlags),
|
||||||
273: makeSyscallInfo("set_robust_list", Hex, Hex),
|
273: makeSyscallInfo("set_robust_list", Hex, Hex),
|
||||||
274: makeSyscallInfo("get_robust_list", Hex, Hex, Hex),
|
274: makeSyscallInfo("get_robust_list", Hex, Hex, Hex),
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package strace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/abi"
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/kdefs"
|
||||||
|
slinux "gvisor.googlesource.com/gvisor/pkg/sentry/syscalls/linux"
|
||||||
|
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PollEventSet is the set of poll(2) event flags.
|
||||||
|
var PollEventSet = abi.FlagSet{
|
||||||
|
{Flag: linux.POLLIN, Name: "POLLIN"},
|
||||||
|
{Flag: linux.POLLPRI, Name: "POLLPRI"},
|
||||||
|
{Flag: linux.POLLOUT, Name: "POLLOUT"},
|
||||||
|
{Flag: linux.POLLERR, Name: "POLLERR"},
|
||||||
|
{Flag: linux.POLLHUP, Name: "POLLHUP"},
|
||||||
|
{Flag: linux.POLLNVAL, Name: "POLLNVAL"},
|
||||||
|
{Flag: linux.POLLRDNORM, Name: "POLLRDNORM"},
|
||||||
|
{Flag: linux.POLLRDBAND, Name: "POLLRDBAND"},
|
||||||
|
{Flag: linux.POLLWRNORM, Name: "POLLWRNORM"},
|
||||||
|
{Flag: linux.POLLWRBAND, Name: "POLLWRBAND"},
|
||||||
|
{Flag: linux.POLLMSG, Name: "POLLMSG"},
|
||||||
|
{Flag: linux.POLLREMOVE, Name: "POLLREMOVE"},
|
||||||
|
{Flag: linux.POLLRDHUP, Name: "POLLRDHUP"},
|
||||||
|
{Flag: linux.POLLFREE, Name: "POLLFREE"},
|
||||||
|
{Flag: linux.POLL_BUSY_LOOP, Name: "POLL_BUSY_LOOP"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollFD(t *kernel.Task, pfd *linux.PollFD, post bool) string {
|
||||||
|
revents := "..."
|
||||||
|
if post {
|
||||||
|
revents = PollEventSet.Parse(uint64(pfd.REvents))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("{FD: %s, Events: %s, REvents: %s}", fd(t, kdefs.FD(pfd.FD)), PollEventSet.Parse(uint64(pfd.Events)), revents)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollFDs(t *kernel.Task, addr usermem.Addr, nfds uint, post bool) string {
|
||||||
|
if addr == 0 {
|
||||||
|
return "null"
|
||||||
|
}
|
||||||
|
|
||||||
|
pfds, err := slinux.CopyInPollFDs(t, addr, nfds)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("%#x (error decoding pollfds: %s)", addr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := make([]string, 0, len(pfds))
|
||||||
|
for i := range pfds {
|
||||||
|
s = append(s, pollFD(t, &pfds[i], post))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%#x [%s]", addr, strings.Join(s, ", "))
|
||||||
|
}
|
|
@ -438,6 +438,8 @@ func (i *SyscallInfo) pre(t *kernel.Task, args arch.SyscallArguments, maximumBlo
|
||||||
output = append(output, capHeader(t, args[arg].Pointer()))
|
output = append(output, capHeader(t, args[arg].Pointer()))
|
||||||
case CapData:
|
case CapData:
|
||||||
output = append(output, capData(t, args[arg-1].Pointer(), args[arg].Pointer()))
|
output = append(output, capData(t, args[arg-1].Pointer(), args[arg].Pointer()))
|
||||||
|
case PollFDs:
|
||||||
|
output = append(output, pollFDs(t, args[arg].Pointer(), uint(args[arg+1].Uint()), false))
|
||||||
case Oct:
|
case Oct:
|
||||||
output = append(output, "0o"+strconv.FormatUint(args[arg].Uint64(), 8))
|
output = append(output, "0o"+strconv.FormatUint(args[arg].Uint64(), 8))
|
||||||
case Hex:
|
case Hex:
|
||||||
|
@ -502,6 +504,8 @@ func (i *SyscallInfo) post(t *kernel.Task, args arch.SyscallArguments, rval uint
|
||||||
output[arg] = sigAction(t, args[arg].Pointer())
|
output[arg] = sigAction(t, args[arg].Pointer())
|
||||||
case PostCapData:
|
case PostCapData:
|
||||||
output[arg] = capData(t, args[arg-1].Pointer(), args[arg].Pointer())
|
output[arg] = capData(t, args[arg-1].Pointer(), args[arg].Pointer())
|
||||||
|
case PollFDs:
|
||||||
|
output[arg] = pollFDs(t, args[arg].Pointer(), uint(args[arg+1].Uint()), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,10 @@ const (
|
||||||
// PostCapData is the data argument to capget(2)/capset(2), formatted
|
// PostCapData is the data argument to capget(2)/capset(2), formatted
|
||||||
// after syscall execution. The previous argument must be CapHeader.
|
// after syscall execution. The previous argument must be CapHeader.
|
||||||
PostCapData
|
PostCapData
|
||||||
|
|
||||||
|
// PollFDs is an array of struct pollfd. The number of entries in the
|
||||||
|
// array is in the next argument.
|
||||||
|
PollFDs
|
||||||
)
|
)
|
||||||
|
|
||||||
// defaultFormat is the syscall argument format to use if the actual format is
|
// defaultFormat is the syscall argument format to use if the actual format is
|
||||||
|
|
|
@ -155,18 +155,28 @@ func pollBlock(t *kernel.Task, pfd []linux.PollFD, timeout time.Duration) (time.
|
||||||
return timeout, n, nil
|
return timeout, n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func doPoll(t *kernel.Task, pfdAddr usermem.Addr, nfds uint, timeout time.Duration) (time.Duration, uintptr, error) {
|
// CopyInPollFDs copies an array of struct pollfd unless nfds exceeds the max.
|
||||||
|
func CopyInPollFDs(t *kernel.Task, addr usermem.Addr, nfds uint) ([]linux.PollFD, error) {
|
||||||
if uint64(nfds) > t.ThreadGroup().Limits().GetCapped(limits.NumberOfFiles, fileCap) {
|
if uint64(nfds) > t.ThreadGroup().Limits().GetCapped(limits.NumberOfFiles, fileCap) {
|
||||||
return timeout, 0, syserror.EINVAL
|
return nil, syserror.EINVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd := make([]linux.PollFD, nfds)
|
pfd := make([]linux.PollFD, nfds)
|
||||||
if nfds > 0 {
|
if nfds > 0 {
|
||||||
if _, err := t.CopyIn(pfdAddr, &pfd); err != nil {
|
if _, err := t.CopyIn(addr, &pfd); err != nil {
|
||||||
return timeout, 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pfd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doPoll(t *kernel.Task, addr usermem.Addr, nfds uint, timeout time.Duration) (time.Duration, uintptr, error) {
|
||||||
|
pfd, err := CopyInPollFDs(t, addr, nfds)
|
||||||
|
if err != nil {
|
||||||
|
return timeout, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
// Compatibility warning: Linux adds POLLHUP and POLLERR just before
|
// Compatibility warning: Linux adds POLLHUP and POLLERR just before
|
||||||
// polling, in fs/select.c:do_pollfd(). Since pfd is copied out after
|
// polling, in fs/select.c:do_pollfd(). Since pfd is copied out after
|
||||||
// polling, changing event masks here is an application-visible difference.
|
// polling, changing event masks here is an application-visible difference.
|
||||||
|
@ -180,7 +190,7 @@ func doPoll(t *kernel.Task, pfdAddr usermem.Addr, nfds uint, timeout time.Durati
|
||||||
// The poll entries are copied out regardless of whether
|
// The poll entries are copied out regardless of whether
|
||||||
// any are set or not. This aligns with the Linux behavior.
|
// any are set or not. This aligns with the Linux behavior.
|
||||||
if nfds > 0 && err == nil {
|
if nfds > 0 && err == nil {
|
||||||
if _, err := t.CopyOut(pfdAddr, pfd); err != nil {
|
if _, err := t.CopyOut(addr, pfd); err != nil {
|
||||||
return remainingTimeout, 0, err
|
return remainingTimeout, 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue