mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add unsupported syscall events for get/setsockopt
PiperOrigin-RevId: 222148953 Change-Id: I21500a9f08939c45314a6414e0824490a973e5aa
This commit is contained in:
committed by
Nicolas Lacasse
parent
237f9c7a5e
commit
fadffa2ff8
@@ -43,6 +43,7 @@ go_library(
|
||||
"shm.go",
|
||||
"signal.go",
|
||||
"socket.go",
|
||||
"tcp.go",
|
||||
"time.go",
|
||||
"timer.go",
|
||||
"tty.go",
|
||||
|
||||
@@ -42,3 +42,110 @@ const (
|
||||
IPPROTO_MPLS = 137
|
||||
IPPROTO_RAW = 255
|
||||
)
|
||||
|
||||
// Socket options from uapi/linux/in.h
|
||||
const (
|
||||
IP_TOS = 1
|
||||
IP_TTL = 2
|
||||
IP_HDRINCL = 3
|
||||
IP_OPTIONS = 4
|
||||
IP_ROUTER_ALERT = 5
|
||||
IP_RECVOPTS = 6
|
||||
IP_RETOPTS = 7
|
||||
IP_PKTINFO = 8
|
||||
IP_PKTOPTIONS = 9
|
||||
IP_MTU_DISCOVER = 10
|
||||
IP_RECVERR = 11
|
||||
IP_RECVTTL = 12
|
||||
IP_RECVTOS = 13
|
||||
IP_MTU = 14
|
||||
IP_FREEBIND = 15
|
||||
IP_IPSEC_POLICY = 16
|
||||
IP_XFRM_POLICY = 17
|
||||
IP_PASSSEC = 18
|
||||
IP_TRANSPARENT = 19
|
||||
IP_ORIGDSTADDR = 20
|
||||
IP_RECVORIGDSTADDR = IP_ORIGDSTADDR
|
||||
IP_MINTTL = 21
|
||||
IP_NODEFRAG = 22
|
||||
IP_CHECKSUM = 23
|
||||
IP_BIND_ADDRESS_NO_PORT = 24
|
||||
IP_RECVFRAGSIZE = 25
|
||||
IP_MULTICAST_IF = 32
|
||||
IP_MULTICAST_TTL = 33
|
||||
IP_MULTICAST_LOOP = 34
|
||||
IP_ADD_MEMBERSHIP = 35
|
||||
IP_DROP_MEMBERSHIP = 36
|
||||
IP_UNBLOCK_SOURCE = 37
|
||||
IP_BLOCK_SOURCE = 38
|
||||
IP_ADD_SOURCE_MEMBERSHIP = 39
|
||||
IP_DROP_SOURCE_MEMBERSHIP = 40
|
||||
IP_MSFILTER = 41
|
||||
MCAST_JOIN_GROUP = 42
|
||||
MCAST_BLOCK_SOURCE = 43
|
||||
MCAST_UNBLOCK_SOURCE = 44
|
||||
MCAST_LEAVE_GROUP = 45
|
||||
MCAST_JOIN_SOURCE_GROUP = 46
|
||||
MCAST_LEAVE_SOURCE_GROUP = 47
|
||||
MCAST_MSFILTER = 48
|
||||
IP_MULTICAST_ALL = 49
|
||||
IP_UNICAST_IF = 50
|
||||
)
|
||||
|
||||
// Socket options from uapi/linux/in6.h
|
||||
const (
|
||||
IPV6_ADDRFORM = 1
|
||||
IPV6_2292PKTINFO = 2
|
||||
IPV6_2292HOPOPTS = 3
|
||||
IPV6_2292DSTOPTS = 4
|
||||
IPV6_2292RTHDR = 5
|
||||
IPV6_2292PKTOPTIONS = 6
|
||||
IPV6_CHECKSUM = 7
|
||||
IPV6_2292HOPLIMIT = 8
|
||||
IPV6_NEXTHOP = 9
|
||||
IPV6_FLOWINFO = 11
|
||||
IPV6_UNICAST_HOPS = 16
|
||||
IPV6_MULTICAST_IF = 17
|
||||
IPV6_MULTICAST_HOPS = 18
|
||||
IPV6_MULTICAST_LOOP = 19
|
||||
IPV6_ADD_MEMBERSHIP = 20
|
||||
IPV6_DROP_MEMBERSHIP = 21
|
||||
IPV6_ROUTER_ALERT = 22
|
||||
IPV6_MTU_DISCOVER = 23
|
||||
IPV6_MTU = 24
|
||||
IPV6_RECVERR = 25
|
||||
IPV6_V6ONLY = 26
|
||||
IPV6_JOIN_ANYCAST = 27
|
||||
IPV6_LEAVE_ANYCAST = 28
|
||||
IPV6_MULTICAST_ALL = 29
|
||||
IPV6_FLOWLABEL_MGR = 32
|
||||
IPV6_FLOWINFO_SEND = 33
|
||||
IPV6_IPSEC_POLICY = 34
|
||||
IPV6_XFRM_POLICY = 35
|
||||
IPV6_HDRINCL = 36
|
||||
IPV6_RECVPKTINFO = 49
|
||||
IPV6_PKTINFO = 50
|
||||
IPV6_RECVHOPLIMIT = 51
|
||||
IPV6_HOPLIMIT = 52
|
||||
IPV6_RECVHOPOPTS = 53
|
||||
IPV6_HOPOPTS = 54
|
||||
IPV6_RTHDRDSTOPTS = 55
|
||||
IPV6_RECVRTHDR = 56
|
||||
IPV6_RTHDR = 57
|
||||
IPV6_RECVDSTOPTS = 58
|
||||
IPV6_DSTOPTS = 59
|
||||
IPV6_RECVPATHMTU = 60
|
||||
IPV6_PATHMTU = 61
|
||||
IPV6_DONTFRAG = 62
|
||||
IPV6_RECVTCLASS = 66
|
||||
IPV6_TCLASS = 67
|
||||
IPV6_AUTOFLOWLABEL = 70
|
||||
IPV6_ADDR_PREFERENCES = 72
|
||||
IPV6_MINHOPCOUNT = 73
|
||||
IPV6_ORIGDSTADDR = 74
|
||||
IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
|
||||
IPV6_TRANSPARENT = 75
|
||||
IPV6_UNICAST_IF = 76
|
||||
IPV6_RECVFRAGSIZE = 77
|
||||
IPV6_FREEBIND = 78
|
||||
)
|
||||
|
||||
@@ -108,3 +108,17 @@ const NetlinkAttrHeaderSize = 4
|
||||
// NLA_ALIGNTO is the alignment of netlink attributes, from
|
||||
// uapi/linux/netlink.h.
|
||||
const NLA_ALIGNTO = 4
|
||||
|
||||
// Socket options, from uapi/linux/netlink.h.
|
||||
const (
|
||||
NETLINK_ADD_MEMBERSHIP = 1
|
||||
NETLINK_DROP_MEMBERSHIP = 2
|
||||
NETLINK_PKTINFO = 3
|
||||
NETLINK_BROADCAST_ERROR = 4
|
||||
NETLINK_NO_ENOBUFS = 5
|
||||
NETLINK_LISTEN_ALL_NSID = 8
|
||||
NETLINK_LIST_MEMBERSHIPS = 9
|
||||
NETLINK_CAP_ACK = 10
|
||||
NETLINK_EXT_ACK = 11
|
||||
NETLINK_DUMP_STRICT_CHK = 12
|
||||
)
|
||||
|
||||
+69
-18
@@ -89,8 +89,18 @@ const (
|
||||
MSG_CMSG_CLOEXEC = 0x40000000
|
||||
)
|
||||
|
||||
// SOL_SOCKET is from socket.h
|
||||
const SOL_SOCKET = 1
|
||||
// Set/get socket option levels, from socket.h.
|
||||
const (
|
||||
SOL_IP = 0
|
||||
SOL_SOCKET = 1
|
||||
SOL_TCP = 6
|
||||
SOL_UDP = 17
|
||||
SOL_IPV6 = 41
|
||||
SOL_ICMPV6 = 58
|
||||
SOL_RAW = 255
|
||||
SOL_PACKET = 263
|
||||
SOL_NETLINK = 270
|
||||
)
|
||||
|
||||
// Socket types, from linux/net.h.
|
||||
const (
|
||||
@@ -122,22 +132,63 @@ const (
|
||||
|
||||
// Socket options from socket.h.
|
||||
const (
|
||||
SO_ERROR = 4
|
||||
SO_KEEPALIVE = 9
|
||||
SO_LINGER = 13
|
||||
SO_MARK = 36
|
||||
SO_PASSCRED = 16
|
||||
SO_PEERCRED = 17
|
||||
SO_PEERNAME = 28
|
||||
SO_PROTOCOL = 38
|
||||
SO_RCVBUF = 8
|
||||
SO_RCVTIMEO = 20
|
||||
SO_REUSEADDR = 2
|
||||
SO_SNDBUF = 7
|
||||
SO_SNDTIMEO = 21
|
||||
SO_TIMESTAMP = 29
|
||||
SO_TIMESTAMPNS = 35
|
||||
SO_TYPE = 3
|
||||
SO_DEBUG = 1
|
||||
SO_REUSEADDR = 2
|
||||
SO_TYPE = 3
|
||||
SO_ERROR = 4
|
||||
SO_DONTROUTE = 5
|
||||
SO_BROADCAST = 6
|
||||
SO_SNDBUF = 7
|
||||
SO_RCVBUF = 8
|
||||
SO_KEEPALIVE = 9
|
||||
SO_OOBINLINE = 10
|
||||
SO_NO_CHECK = 11
|
||||
SO_PRIORITY = 12
|
||||
SO_LINGER = 13
|
||||
SO_BSDCOMPAT = 14
|
||||
SO_REUSEPORT = 15
|
||||
SO_PASSCRED = 16
|
||||
SO_PEERCRED = 17
|
||||
SO_RCVLOWAT = 18
|
||||
SO_SNDLOWAT = 19
|
||||
SO_RCVTIMEO = 20
|
||||
SO_SNDTIMEO = 21
|
||||
SO_BINDTODEVICE = 25
|
||||
SO_ATTACH_FILTER = 26
|
||||
SO_DETACH_FILTER = 27
|
||||
SO_GET_FILTER = SO_ATTACH_FILTER
|
||||
SO_PEERNAME = 28
|
||||
SO_TIMESTAMP = 29
|
||||
SO_ACCEPTCONN = 30
|
||||
SO_PEERSEC = 31
|
||||
SO_SNDBUFFORCE = 32
|
||||
SO_RCVBUFFORCE = 33
|
||||
SO_PASSSEC = 34
|
||||
SO_TIMESTAMPNS = 35
|
||||
SO_MARK = 36
|
||||
SO_TIMESTAMPING = 37
|
||||
SO_PROTOCOL = 38
|
||||
SO_DOMAIN = 39
|
||||
SO_RXQ_OVFL = 40
|
||||
SO_WIFI_STATUS = 41
|
||||
SO_PEEK_OFF = 42
|
||||
SO_NOFCS = 43
|
||||
SO_LOCK_FILTER = 44
|
||||
SO_SELECT_ERR_QUEUE = 45
|
||||
SO_BUSY_POLL = 46
|
||||
SO_MAX_PACING_RATE = 47
|
||||
SO_BPF_EXTENSIONS = 48
|
||||
SO_INCOMING_CPU = 49
|
||||
SO_ATTACH_BPF = 50
|
||||
SO_ATTACH_REUSEPORT_CBPF = 51
|
||||
SO_ATTACH_REUSEPORT_EBPF = 52
|
||||
SO_CNX_ADVICE = 53
|
||||
SO_MEMINFO = 55
|
||||
SO_INCOMING_NAPI_ID = 56
|
||||
SO_COOKIE = 57
|
||||
SO_PEERGROUPS = 59
|
||||
SO_ZEROCOPY = 60
|
||||
SO_TXTIME = 61
|
||||
)
|
||||
|
||||
// SockAddrMax is the maximum size of a struct sockaddr, from
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2018 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 linux
|
||||
|
||||
// Socket options from uapi/linux/tcp.h.
|
||||
const (
|
||||
TCP_NODELAY = 1
|
||||
TCP_MAXSEG = 2
|
||||
TCP_CORK = 3
|
||||
TCP_KEEPIDLE = 4
|
||||
TCP_KEEPINTVL = 5
|
||||
TCP_KEEPCNT = 6
|
||||
TCP_SYNCNT = 7
|
||||
TCP_LINGER2 = 8
|
||||
TCP_DEFER_ACCEPT = 9
|
||||
TCP_WINDOW_CLAMP = 10
|
||||
TCP_INFO = 11
|
||||
TCP_QUICKACK = 12
|
||||
TCP_CONGESTION = 13
|
||||
TCP_MD5SIG = 14
|
||||
TCP_THIN_LINEAR_TIMEOUTS = 16
|
||||
TCP_THIN_DUPACK = 17
|
||||
TCP_USER_TIMEOUT = 18
|
||||
TCP_REPAIR = 19
|
||||
TCP_REPAIR_QUEUE = 20
|
||||
TCP_QUEUE_SEQ = 21
|
||||
TCP_REPAIR_OPTIONS = 22
|
||||
TCP_FASTOPEN = 23
|
||||
TCP_TIMESTAMP = 24
|
||||
TCP_NOTSENT_LOWAT = 25
|
||||
TCP_CC_INFO = 26
|
||||
TCP_SAVE_SYN = 27
|
||||
TCP_SAVED_SYN = 28
|
||||
TCP_REPAIR_WINDOW = 29
|
||||
TCP_FASTOPEN_CONNECT = 30
|
||||
TCP_ULP = 31
|
||||
TCP_MD5SIG_EXT = 32
|
||||
TCP_FASTOPEN_KEY = 33
|
||||
TCP_FASTOPEN_NO_COOKIE = 34
|
||||
TCP_ZEROCOPY_RECEIVE = 35
|
||||
TCP_INQ = 36
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -299,6 +299,21 @@ func (s *Socket) GetSockOpt(t *kernel.Task, level int, name int, outLen int) (in
|
||||
}
|
||||
// We don't have limit on receiving size.
|
||||
return math.MaxInt32, nil
|
||||
|
||||
default:
|
||||
socket.GetSockOptEmitUnimplementedEvent(t, name)
|
||||
}
|
||||
case linux.SOL_NETLINK:
|
||||
switch name {
|
||||
case linux.NETLINK_BROADCAST_ERROR,
|
||||
linux.NETLINK_CAP_ACK,
|
||||
linux.NETLINK_DUMP_STRICT_CHK,
|
||||
linux.NETLINK_EXT_ACK,
|
||||
linux.NETLINK_LIST_MEMBERSHIPS,
|
||||
linux.NETLINK_NO_ENOBUFS,
|
||||
linux.NETLINK_PKTINFO:
|
||||
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
}
|
||||
}
|
||||
// TODO: other sockopts are not supported.
|
||||
@@ -329,7 +344,25 @@ func (s *Socket) SetSockOpt(t *kernel.Task, level int, name int, opt []byte) *sy
|
||||
// We don't have limit on receiving size. So just accept anything as
|
||||
// valid for compatibility.
|
||||
return nil
|
||||
default:
|
||||
socket.SetSockOptEmitUnimplementedEvent(t, name)
|
||||
}
|
||||
|
||||
case linux.SOL_NETLINK:
|
||||
switch name {
|
||||
case linux.NETLINK_ADD_MEMBERSHIP,
|
||||
linux.NETLINK_BROADCAST_ERROR,
|
||||
linux.NETLINK_CAP_ACK,
|
||||
linux.NETLINK_DROP_MEMBERSHIP,
|
||||
linux.NETLINK_DUMP_STRICT_CHK,
|
||||
linux.NETLINK_EXT_ACK,
|
||||
linux.NETLINK_LISTEN_ALL_NSID,
|
||||
linux.NETLINK_NO_ENOBUFS,
|
||||
linux.NETLINK_PKTINFO:
|
||||
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
}
|
||||
|
||||
}
|
||||
// TODO: other sockopts are not supported.
|
||||
return syserr.ErrProtocolNotAvailable
|
||||
|
||||
@@ -213,3 +213,94 @@ func (rt *ReceiveTimeout) SetRecvTimeout(nanoseconds int64) {
|
||||
func (rt *ReceiveTimeout) RecvTimeout() int64 {
|
||||
return atomic.LoadInt64(&rt.ns)
|
||||
}
|
||||
|
||||
// GetSockOptEmitUnimplementedEvent emits unimplemented event if name is valid.
|
||||
// It contains names that are valid for GetSockOpt when level is SOL_SOCKET.
|
||||
func GetSockOptEmitUnimplementedEvent(t *kernel.Task, name int) {
|
||||
switch name {
|
||||
case linux.SO_ACCEPTCONN,
|
||||
linux.SO_BPF_EXTENSIONS,
|
||||
linux.SO_COOKIE,
|
||||
linux.SO_DOMAIN,
|
||||
linux.SO_ERROR,
|
||||
linux.SO_GET_FILTER,
|
||||
linux.SO_INCOMING_NAPI_ID,
|
||||
linux.SO_MEMINFO,
|
||||
linux.SO_PEERCRED,
|
||||
linux.SO_PEERGROUPS,
|
||||
linux.SO_PEERNAME,
|
||||
linux.SO_PEERSEC,
|
||||
linux.SO_PROTOCOL,
|
||||
linux.SO_SNDLOWAT,
|
||||
linux.SO_TYPE:
|
||||
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
|
||||
default:
|
||||
emitUnimplementedEvent(t, name)
|
||||
}
|
||||
}
|
||||
|
||||
// SetSockOptEmitUnimplementedEvent emits unimplemented event if name is valid.
|
||||
// It contains names that are valid for SetSockOpt when level is SOL_SOCKET.
|
||||
func SetSockOptEmitUnimplementedEvent(t *kernel.Task, name int) {
|
||||
switch name {
|
||||
case linux.SO_ATTACH_BPF,
|
||||
linux.SO_ATTACH_FILTER,
|
||||
linux.SO_ATTACH_REUSEPORT_CBPF,
|
||||
linux.SO_ATTACH_REUSEPORT_EBPF,
|
||||
linux.SO_CNX_ADVICE,
|
||||
linux.SO_DETACH_FILTER,
|
||||
linux.SO_RCVBUFFORCE,
|
||||
linux.SO_SNDBUFFORCE:
|
||||
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
|
||||
default:
|
||||
emitUnimplementedEvent(t, name)
|
||||
}
|
||||
}
|
||||
|
||||
// emitUnimplementedEvent emits unimplemented event if name is valid. It
|
||||
// contains names that are common between Get and SetSocketOpt when level is
|
||||
// SOL_SOCKET.
|
||||
func emitUnimplementedEvent(t *kernel.Task, name int) {
|
||||
switch name {
|
||||
case linux.SO_BINDTODEVICE,
|
||||
linux.SO_BROADCAST,
|
||||
linux.SO_BSDCOMPAT,
|
||||
linux.SO_BUSY_POLL,
|
||||
linux.SO_DEBUG,
|
||||
linux.SO_DONTROUTE,
|
||||
linux.SO_INCOMING_CPU,
|
||||
linux.SO_KEEPALIVE,
|
||||
linux.SO_LINGER,
|
||||
linux.SO_LOCK_FILTER,
|
||||
linux.SO_MARK,
|
||||
linux.SO_MAX_PACING_RATE,
|
||||
linux.SO_NOFCS,
|
||||
linux.SO_NO_CHECK,
|
||||
linux.SO_OOBINLINE,
|
||||
linux.SO_PASSCRED,
|
||||
linux.SO_PASSSEC,
|
||||
linux.SO_PEEK_OFF,
|
||||
linux.SO_PRIORITY,
|
||||
linux.SO_RCVBUF,
|
||||
linux.SO_RCVLOWAT,
|
||||
linux.SO_RCVTIMEO,
|
||||
linux.SO_REUSEADDR,
|
||||
linux.SO_REUSEPORT,
|
||||
linux.SO_RXQ_OVFL,
|
||||
linux.SO_SELECT_ERR_QUEUE,
|
||||
linux.SO_SNDBUF,
|
||||
linux.SO_SNDTIMEO,
|
||||
linux.SO_TIMESTAMP,
|
||||
linux.SO_TIMESTAMPING,
|
||||
linux.SO_TIMESTAMPNS,
|
||||
linux.SO_TXTIME,
|
||||
linux.SO_WIFI_STATUS,
|
||||
linux.SO_ZEROCOPY:
|
||||
|
||||
t.Kernel().EmitUnimplementedEvent(t)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,10 +89,16 @@ func (c *compatEmitter) Emit(msg proto.Message) (hangup bool, err error) {
|
||||
if tr == nil {
|
||||
switch sysnr {
|
||||
case syscall.SYS_PRCTL, syscall.SYS_ARCH_PRCTL:
|
||||
tr = newCmdTracker(0)
|
||||
// args: cmd, ...
|
||||
tr = newArgsTracker(0)
|
||||
|
||||
case syscall.SYS_IOCTL, syscall.SYS_EPOLL_CTL, syscall.SYS_SHMCTL:
|
||||
tr = newCmdTracker(1)
|
||||
// args: fd, cmd, ...
|
||||
tr = newArgsTracker(1)
|
||||
|
||||
case syscall.SYS_GETSOCKOPT, syscall.SYS_SETSOCKOPT:
|
||||
// args: fd, level, name, ...
|
||||
tr = newArgsTracker(1, 2)
|
||||
|
||||
default:
|
||||
tr = &onceTracker{}
|
||||
|
||||
+39
-16
@@ -20,35 +20,58 @@ import (
|
||||
rpb "gvisor.googlesource.com/gvisor/pkg/sentry/arch/registers_go_proto"
|
||||
)
|
||||
|
||||
// cmdTracker reports only a single time for each different command argument in
|
||||
// the syscall. It's used for generic syscalls like ioctl to report once per
|
||||
// 'cmd'
|
||||
type cmdTracker struct {
|
||||
// argIdx is the syscall argument index where the command is located.
|
||||
argIdx int
|
||||
cmds map[uint32]struct{}
|
||||
// reportLimit is the max number of events that should be reported per tracker.
|
||||
const reportLimit = 100
|
||||
|
||||
// argsTracker reports only once for each different combination of arguments.
|
||||
// It's used for generic syscalls like ioctl to report once per 'cmd'.
|
||||
type argsTracker struct {
|
||||
// argsIdx is the syscall arguments to use as unique ID.
|
||||
argsIdx []int
|
||||
reported map[string]struct{}
|
||||
count int
|
||||
}
|
||||
|
||||
func newCmdTracker(argIdx int) *cmdTracker {
|
||||
return &cmdTracker{argIdx: argIdx, cmds: make(map[uint32]struct{})}
|
||||
func newArgsTracker(argIdx ...int) *argsTracker {
|
||||
return &argsTracker{argsIdx: argIdx, reported: make(map[string]struct{})}
|
||||
}
|
||||
|
||||
// cmd returns the command based on the syscall argument index.
|
||||
func (c *cmdTracker) cmd(regs *rpb.AMD64Registers) uint32 {
|
||||
switch c.argIdx {
|
||||
func (a *argsTracker) key(regs *rpb.AMD64Registers) string {
|
||||
var rv string
|
||||
for _, idx := range a.argsIdx {
|
||||
rv += fmt.Sprintf("%d|", argVal(idx, regs))
|
||||
}
|
||||
return rv
|
||||
}
|
||||
|
||||
func argVal(argIdx int, regs *rpb.AMD64Registers) uint32 {
|
||||
switch argIdx {
|
||||
case 0:
|
||||
return uint32(regs.Rdi)
|
||||
case 1:
|
||||
return uint32(regs.Rsi)
|
||||
case 2:
|
||||
return uint32(regs.Rdx)
|
||||
case 3:
|
||||
return uint32(regs.R10)
|
||||
case 4:
|
||||
return uint32(regs.R8)
|
||||
case 5:
|
||||
return uint32(regs.R9)
|
||||
}
|
||||
panic(fmt.Sprintf("unsupported syscall argument index %d", c.argIdx))
|
||||
panic(fmt.Sprintf("invalid syscall argument index %d", argIdx))
|
||||
}
|
||||
|
||||
func (c *cmdTracker) shouldReport(regs *rpb.AMD64Registers) bool {
|
||||
_, ok := c.cmds[c.cmd(regs)]
|
||||
func (a *argsTracker) shouldReport(regs *rpb.AMD64Registers) bool {
|
||||
if a.count >= reportLimit {
|
||||
return false
|
||||
}
|
||||
_, ok := a.reported[a.key(regs)]
|
||||
return !ok
|
||||
}
|
||||
|
||||
func (c *cmdTracker) onReported(regs *rpb.AMD64Registers) {
|
||||
c.cmds[c.cmd(regs)] = struct{}{}
|
||||
func (a *argsTracker) onReported(regs *rpb.AMD64Registers) {
|
||||
a.count++
|
||||
a.reported[a.key(regs)] = struct{}{}
|
||||
}
|
||||
|
||||
+29
-10
@@ -33,34 +33,53 @@ func TestOnceTracker(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCmdTracker(t *testing.T) {
|
||||
func TestArgsTracker(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
idx int
|
||||
idx []int
|
||||
rdi1 uint64
|
||||
rdi2 uint64
|
||||
rsi1 uint64
|
||||
rsi2 uint64
|
||||
want bool
|
||||
}{
|
||||
{name: "same rdi", idx: 0, rdi1: 123, rdi2: 123, want: false},
|
||||
{name: "same rsi", idx: 1, rsi1: 123, rsi2: 123, want: false},
|
||||
{name: "diff rdi", idx: 0, rdi1: 123, rdi2: 321, want: true},
|
||||
{name: "diff rsi", idx: 1, rsi1: 123, rsi2: 321, want: true},
|
||||
{name: "cmd is uint32", idx: 0, rsi1: 0xdead00000123, rsi2: 0xbeef00000123, want: false},
|
||||
{name: "same rdi", idx: []int{0}, rdi1: 123, rdi2: 123, want: false},
|
||||
{name: "same rsi", idx: []int{1}, rsi1: 123, rsi2: 123, want: false},
|
||||
{name: "diff rdi", idx: []int{0}, rdi1: 123, rdi2: 321, want: true},
|
||||
{name: "diff rsi", idx: []int{1}, rsi1: 123, rsi2: 321, want: true},
|
||||
{name: "cmd is uint32", idx: []int{0}, rsi1: 0xdead00000123, rsi2: 0xbeef00000123, want: false},
|
||||
{name: "same 2 args", idx: []int{0, 1}, rsi1: 123, rdi1: 321, rsi2: 123, rdi2: 321, want: false},
|
||||
{name: "diff 2 args", idx: []int{0, 1}, rsi1: 123, rdi1: 321, rsi2: 789, rdi2: 987, want: true},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
c := newCmdTracker(tc.idx)
|
||||
c := newArgsTracker(tc.idx...)
|
||||
regs := &rpb.AMD64Registers{Rdi: tc.rdi1, Rsi: tc.rsi1}
|
||||
if !c.shouldReport(regs) {
|
||||
t.Error("first call to checkAndMark, got: false, want: true")
|
||||
t.Error("first call to shouldReport, got: false, want: true")
|
||||
}
|
||||
c.onReported(regs)
|
||||
|
||||
regs.Rdi, regs.Rsi = tc.rdi2, tc.rsi2
|
||||
if got := c.shouldReport(regs); tc.want != got {
|
||||
t.Errorf("after first call to checkAndMark, got: %t, want: %t", got, tc.want)
|
||||
t.Errorf("second call to shouldReport, got: %t, want: %t", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestArgsTrackerLimit(t *testing.T) {
|
||||
c := newArgsTracker(0, 1)
|
||||
for i := 0; i < reportLimit; i++ {
|
||||
regs := &rpb.AMD64Registers{Rdi: 123, Rsi: uint64(i)}
|
||||
if !c.shouldReport(regs) {
|
||||
t.Error("shouldReport before limit was reached, got: false, want: true")
|
||||
}
|
||||
c.onReported(regs)
|
||||
}
|
||||
|
||||
// Should hit the count limit now.
|
||||
regs := &rpb.AMD64Registers{Rdi: 123, Rsi: 123456}
|
||||
if c.shouldReport(regs) {
|
||||
t.Error("shouldReport after limit was reached, got: true, want: false")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user