Refactor hostinet get/setsockopt handlers and filters.

There is a lot of duplication between the get/setsockopt handlers for hostinet
and the filters. This CL introduces an intermediate type hostinet.SockOpt which
is used to generate both handlers and filters.

There is no functional change.

PiperOrigin-RevId: 508430221
This commit is contained in:
Nicolas Lacasse
2023-02-09 11:34:01 -08:00
committed by gVisor bot
parent 753fb9ac5e
commit ec1abcf521
6 changed files with 261 additions and 528 deletions
+1
View File
@@ -9,6 +9,7 @@ go_library(
"hostinet.go",
"socket.go",
"socket_unsafe.go",
"sockopt.go",
"sockopt_impl.go",
"stack.go",
"stack_unsafe.go",
-148
View File
@@ -16,16 +16,13 @@ package hostinet
import (
"fmt"
"time"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -42,8 +39,6 @@ import (
)
const (
sizeofInt32 = 4
// sizeofSockaddr is the size in bytes of the largest sockaddr type
// supported by this package.
sizeofSockaddr = unix.SizeofSockaddrInet6 // sizeof(sockaddr_in6) > sizeof(sockaddr_in)
@@ -388,149 +383,6 @@ func (s *Socket) Shutdown(_ *kernel.Task, how int) *syserr.Error {
}
}
// GetSockOpt implements socket.Socket.GetSockOpt.
func (s *Socket) GetSockOpt(t *kernel.Task, level, name int, optValAddr hostarch.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
if outLen < 0 {
return nil, syserr.ErrInvalidArgument
}
// Only allow known and safe options.
optlen, copyIn := getSockOptLen(t, level, name)
switch level {
case linux.SOL_IP:
switch name {
case linux.IP_TOS, linux.IP_RECVTOS, linux.IP_TTL, linux.IP_RECVTTL, linux.IP_PKTINFO, linux.IP_RECVORIGDSTADDR, linux.IP_RECVERR:
optlen = sizeofInt32
}
case linux.SOL_IPV6:
switch name {
case linux.IPV6_TCLASS, linux.IPV6_RECVTCLASS, linux.IPV6_RECVPKTINFO, linux.IPV6_UNICAST_HOPS, linux.IPV6_MULTICAST_HOPS, linux.IPV6_RECVHOPLIMIT, linux.IPV6_RECVERR, linux.IPV6_V6ONLY, linux.IPV6_RECVORIGDSTADDR:
optlen = sizeofInt32
}
case linux.SOL_SOCKET:
switch name {
case linux.SO_BROADCAST, linux.SO_ERROR, linux.SO_KEEPALIVE, linux.SO_SNDBUF, linux.SO_RCVBUF, linux.SO_REUSEADDR, linux.SO_TIMESTAMP, linux.SO_ACCEPTCONN:
optlen = sizeofInt32
case linux.SO_LINGER:
optlen = unix.SizeofLinger
case linux.SO_RCVTIMEO:
optlen = linux.SizeOfTimeval
recvTimeout := linux.NsecToTimeval(s.RecvTimeout())
return &recvTimeout, nil
case linux.SO_SNDTIMEO:
optlen = linux.SizeOfTimeval
sndTimeout := linux.NsecToTimeval(s.SendTimeout())
return &sndTimeout, nil
}
case linux.SOL_TCP:
switch name {
case linux.TCP_NODELAY, linux.TCP_MAXSEG, linux.TCP_INQ, linux.TCP_USER_TIMEOUT, linux.TCP_DEFER_ACCEPT, linux.TCP_SYNCNT, linux.TCP_WINDOW_CLAMP:
optlen = sizeofInt32
case linux.TCP_INFO:
optlen = linux.SizeOfTCPInfo
// Truncate the output buffer to outLen size.
if optlen > outLen {
optlen = outLen
}
case linux.TCP_CONGESTION:
optlen = outLen
}
}
if optlen == 0 {
return nil, syserr.ErrProtocolNotAvailable // ENOPROTOOPT
}
if outLen < optlen {
return nil, syserr.ErrInvalidArgument
}
opt := make([]byte, optlen)
if copyIn {
// This is non-intuitive as normally in getsockopt one assumes that the
// parameter is purely an out parameter. But some custom options do require
// copying in the optVal so we do it here only for those custom options.
if _, err := t.CopyInBytes(optValAddr, opt); err != nil {
return nil, syserr.FromError(err)
}
}
var err error
opt, err = getsockopt(s.fd, level, name, opt)
if err != nil {
return nil, syserr.FromError(err)
}
opt = postGetSockOpt(t, level, name, opt)
optP := primitive.ByteSlice(opt)
return &optP, nil
}
// SetSockOpt implements socket.Socket.SetSockOpt.
func (s *Socket) SetSockOpt(t *kernel.Task, level, name int, opt []byte) *syserr.Error {
// Only allow known and safe options.
optlen := setSockOptLen(t, level, name)
switch level {
case linux.SOL_IP:
switch name {
case linux.IP_TOS, linux.IP_RECVTOS, linux.IP_TTL, linux.IP_RECVTTL, linux.IP_PKTINFO, linux.IP_RECVORIGDSTADDR, linux.IP_RECVERR:
optlen = sizeofInt32
}
case linux.SOL_IPV6:
switch name {
case linux.IPV6_TCLASS, linux.IPV6_RECVTCLASS, linux.IPV6_RECVPKTINFO, linux.IPV6_UNICAST_HOPS, linux.IPV6_MULTICAST_HOPS, linux.IPV6_RECVHOPLIMIT, linux.IPV6_RECVERR, linux.IPV6_V6ONLY, linux.IPV6_RECVORIGDSTADDR:
optlen = sizeofInt32
}
case linux.SOL_SOCKET:
switch name {
case linux.SO_BROADCAST, linux.SO_SNDBUF, linux.SO_RCVBUF, linux.SO_REUSEADDR, linux.SO_TIMESTAMP:
optlen = sizeofInt32
case linux.SO_RCVTIMEO:
// Since our host sockets are always non-blocking,
// there is no point in setting these timeouts on the
// host. But we must store them internally so that we
// can put deadlines on our own blocking.
optlen = linux.SizeOfTimeval
var v linux.Timeval
v.UnmarshalBytes(opt[:optlen])
if v.Usec < 0 || v.Usec >= int64(time.Second/time.Microsecond) {
return syserr.ErrDomain
}
s.SetRecvTimeout(v.ToNsecCapped())
return nil
case linux.SO_SNDTIMEO:
// See above.
optlen = linux.SizeOfTimeval
var v linux.Timeval
v.UnmarshalBytes(opt[:optlen])
if v.Usec < 0 || v.Usec >= int64(time.Second/time.Microsecond) {
return syserr.ErrDomain
}
s.SetSendTimeout(v.ToNsecCapped())
return nil
}
case linux.SOL_TCP:
switch name {
case linux.TCP_NODELAY, linux.TCP_INQ, linux.TCP_MAXSEG, linux.TCP_USER_TIMEOUT, linux.TCP_DEFER_ACCEPT, linux.TCP_SYNCNT, linux.TCP_WINDOW_CLAMP:
optlen = sizeofInt32
case linux.TCP_CONGESTION:
optlen = len(opt)
}
}
if optlen == 0 {
// Pretend to accept socket options we don't understand. This seems
// dangerous, but it's what netstack does...
return nil
}
if len(opt) < optlen {
return syserr.ErrInvalidArgument
}
opt = opt[:optlen]
_, _, errno := unix.Syscall6(unix.SYS_SETSOCKOPT, uintptr(s.fd), uintptr(level), uintptr(name), uintptr(firstBytePtr(opt)), uintptr(len(opt)), 0)
if errno != 0 {
return syserr.FromError(errno)
}
return nil
}
func (s *Socket) recvMsgFromHost(iovs []unix.Iovec, flags int, senderRequested bool, controlLen uint64) (uint64, int, []byte, []byte, error) {
// We always do a non-blocking recv*().
sysflags := flags | unix.MSG_DONTWAIT
+219
View File
@@ -0,0 +1,219 @@
// Copyright 2023 The gVisor Authors.
//
// 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 hostinet
import (
"fmt"
"sync"
"time"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
)
const (
sizeofInt16 = 2
sizeofInt32 = 4
)
// SockOpt is used to generate get/setsockopt handlers and filters.
type SockOpt struct {
// Level the socket option applies to.
Level uint64
// Name of the option.
Name uint64
// Size of the parameter. A size of 0 indicates that any size is
// allowed (used for strings types).
Size uint64
// Support getsockopt on this option.
AllowGet bool
// Support setsockopt on this option.
AllowSet bool
}
// SockOpts are the socket options supported by hostinet.
var SockOpts = []SockOpt{
{linux.SOL_IP, linux.IP_PKTINFO, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVERR, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVORIGDSTADDR, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVTOS, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVTTL, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_TOS, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_TTL, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_MULTICAST_HOPS, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_RECVERR, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_RECVHOPLIMIT, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_RECVORIGDSTADDR, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_RECVPKTINFO, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_RECVTCLASS, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_TCLASS, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_UNICAST_HOPS, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_V6ONLY, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_ACCEPTCONN, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_BROADCAST, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_ERROR, sizeofInt32, false, true},
{linux.SOL_SOCKET, linux.SO_KEEPALIVE, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_LINGER, linux.SizeOfLinger, true, true},
{linux.SOL_SOCKET, linux.SO_RCVBUF, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_REUSEADDR, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_SNDBUF, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_TIMESTAMP, sizeofInt32, true, true},
{linux.SOL_SOCKET, linux.SO_TYPE, sizeofInt32, false, true},
{linux.SOL_TCP, linux.TCP_CONGESTION, 0 /* string */, true, true},
{linux.SOL_TCP, linux.TCP_DEFER_ACCEPT, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_INFO, uint64(linux.SizeOfTCPInfo), true, false},
{linux.SOL_TCP, linux.TCP_INQ, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_MAXSEG, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_NODELAY, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_SYNCNT, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_USER_TIMEOUT, sizeofInt32, true, true},
{linux.SOL_TCP, linux.TCP_WINDOW_CLAMP, sizeofInt32, true, true},
}
// sockOptMap is a map of {level, name} -> SockOpts. It is an optimization for
// looking up SockOpts by level and name. The map is initialized in the first
// call to Get/SetSockOpt.
var (
sockOptMap map[levelName]SockOpt
sockOptMapOnce sync.Once
)
type levelName struct {
level uint64
name uint64
}
func initSockOptMap(t *kernel.Task) {
opts := append(SockOpts, extraSockOpts(t)...)
sockOptMap = make(map[levelName]SockOpt, len(opts))
for _, opt := range opts {
ln := levelName{opt.Level, opt.Name}
if _, ok := sockOptMap[ln]; ok {
panic(fmt.Sprintf("multiple sockopts with level=%d and name=%d", opt.Level, opt.Name))
}
sockOptMap[ln] = opt
}
}
// GetSockOpt implements socket.Socket.GetSockOpt.
func (s *Socket) GetSockOpt(t *kernel.Task, level, name int, optValAddr hostarch.Addr, optLen int) (marshal.Marshallable, *syserr.Error) {
sockOptMapOnce.Do(func() { initSockOptMap(t) })
if optLen < 0 {
return nil, syserr.ErrInvalidArgument
}
// Special case send/recv timeouts since those are handled internally.
if level == linux.SOL_SOCKET {
switch name {
case linux.SO_RCVTIMEO:
recvTimeout := linux.NsecToTimeval(s.RecvTimeout())
return &recvTimeout, nil
case linux.SO_SNDTIMEO:
sndTimeout := linux.NsecToTimeval(s.SendTimeout())
return &sndTimeout, nil
}
}
sockOpt, ok := sockOptMap[levelName{uint64(level), uint64(name)}]
if !ok {
return nil, syserr.ErrProtocolNotAvailable
}
var opt []byte
if sockOpt.Size > 0 {
// Validate size of input buffer.
if uint64(optLen) < sockOpt.Size {
// Special case for TCP_INFO. We allow smaller buffers, and
// only fill up what we can.
if level != linux.SOL_TCP || name != linux.TCP_INFO {
return nil, syserr.ErrInvalidArgument
}
}
opt = make([]byte, sockOpt.Size)
} else {
// No size checking. This is probably a string. Use the size
// they gave us.
opt = make([]byte, optLen)
}
if err := preGetSockOpt(t, level, name, optValAddr, opt); err != nil {
return nil, syserr.FromError(err)
}
var err error
opt, err = getsockopt(s.fd, level, name, opt)
if err != nil {
return nil, syserr.FromError(err)
}
opt = postGetSockOpt(t, level, name, opt)
// Special-case for TCP_INFO. We truncate the buffer to whatever size
// the user requested.
if level == linux.SOL_TCP && name == linux.TCP_INFO && uint64(optLen) < sockOpt.Size {
opt = opt[:optLen]
}
optP := primitive.ByteSlice(opt)
return &optP, nil
}
// SetSockOpt implements socket.Socket.SetSockOpt.
func (s *Socket) SetSockOpt(t *kernel.Task, level, name int, opt []byte) *syserr.Error {
sockOptMapOnce.Do(func() { initSockOptMap(t) })
// Special case send/recv timeouts since those are handled internally.
if level == linux.SOL_SOCKET {
switch name {
case linux.SO_RCVTIMEO:
optLen := linux.SizeOfTimeval
var v linux.Timeval
v.UnmarshalBytes(opt[:optLen])
if v.Usec < 0 || v.Usec >= int64(time.Second/time.Microsecond) {
return syserr.ErrDomain
}
s.SetRecvTimeout(v.ToNsecCapped())
return nil
case linux.SO_SNDTIMEO:
optLen := linux.SizeOfTimeval
var v linux.Timeval
v.UnmarshalBytes(opt[:optLen])
if v.Usec < 0 || v.Usec >= int64(time.Second/time.Microsecond) {
return syserr.ErrDomain
}
s.SetSendTimeout(v.ToNsecCapped())
return nil
}
}
sockOpt, ok := sockOptMap[levelName{uint64(level), uint64(name)}]
if !ok {
// Pretend to accept socket options we don't understand. This
// seems dangerous, but it's what netstack does...
return nil
}
if sockOpt.Size > 0 {
if uint64(len(opt)) < sockOpt.Size {
return syserr.ErrInvalidArgument
}
opt = opt[:sockOpt.Size]
}
if _, _, errno := unix.Syscall6(unix.SYS_SETSOCKOPT, uintptr(s.fd), uintptr(level), uintptr(name), uintptr(firstBytePtr(opt)), uintptr(len(opt)), 0); errno != 0 {
return syserr.FromError(errno)
}
return nil
}
+6 -6
View File
@@ -18,17 +18,17 @@
package hostinet
import (
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
)
func getSockOptLen(t *kernel.Task, level, name int) (len int, copyIn bool) {
return 0, false // No custom options.
func extraSockOpts(t *kernel.Task) []SockOpt {
return nil
}
func setSockOptLen(t *kernel.Task, level, name int) int {
return 0 // No custom options.
func preGetSockOpt(t *kernel.Task, level, name int, optValAddr hostarch.Addr, opt []byte) error {
return nil
}
func postGetSockOpt(t *kernel.Task, level, name int, opt []byte) []byte {
return opt // No custom changes to option value.
return opt
}
+1
View File
@@ -25,6 +25,7 @@ go_library(
"//pkg/log",
"//pkg/seccomp",
"//pkg/sentry/platform",
"//pkg/sentry/socket/hostinet",
"//pkg/tcpip/link/fdbased",
"@org_golang_x_sys//unix:go_default_library",
],
+34 -374
View File
@@ -16,13 +16,13 @@ package filter
import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/seccomp"
"gvisor.dev/gvisor/pkg/sentry/socket/hostinet"
)
// hostInetFilters contains syscalls that are needed by sentry/socket/hostinet.
func hostInetFilters() seccomp.SyscallRules {
return seccomp.SyscallRules{
rules := seccomp.SyscallRules{
unix.SYS_ACCEPT4: []seccomp.Rule{
{
seccomp.MatchAny{},
@@ -35,183 +35,6 @@ func hostInetFilters() seccomp.SyscallRules {
unix.SYS_CONNECT: {},
unix.SYS_GETPEERNAME: {},
unix.SYS_GETSOCKNAME: {},
unix.SYS_GETSOCKOPT: []seccomp.Rule{
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_TOS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVTOS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_TTL),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVTTL),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_PKTINFO),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVORIGDSTADDR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVERR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_TCLASS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVTCLASS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVPKTINFO),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_UNICAST_HOPS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_MULTICAST_HOPS),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVHOPLIMIT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVERR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_V6ONLY),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(linux.IPV6_RECVORIGDSTADDR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_BROADCAST),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_ERROR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_KEEPALIVE),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_SNDBUF),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_RCVBUF),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_REUSEADDR),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_TYPE),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_LINGER),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_TIMESTAMP),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_ACCEPTCONN),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(unix.TCP_NODELAY),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(unix.TCP_INFO),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_INQ),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_MAXSEG),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_CONGESTION),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_USER_TIMEOUT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_DEFER_ACCEPT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_SYNCNT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_WINDOW_CLAMP),
},
},
unix.SYS_IOCTL: []seccomp.Rule{
{
seccomp.MatchAny{},
@@ -236,201 +59,6 @@ func hostInetFilters() seccomp.SyscallRules {
unix.SYS_RECVMSG: {},
unix.SYS_SENDMSG: {},
unix.SYS_SENDTO: {},
unix.SYS_SETSOCKOPT: []seccomp.Rule{
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_BROADCAST),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_SNDBUF),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_RCVBUF),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_REUSEADDR),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_SOCKET),
seccomp.EqualTo(unix.SO_TIMESTAMP),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(unix.TCP_NODELAY),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_INQ),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_MAXSEG),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_CONGESTION),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_USER_TIMEOUT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_DEFER_ACCEPT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_SYNCNT),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_TCP),
seccomp.EqualTo(linux.TCP_WINDOW_CLAMP),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_TOS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVTOS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_TTL),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVTTL),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_PKTINFO),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVPKTINFO),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVORIGDSTADDR),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IP),
seccomp.EqualTo(unix.IP_RECVERR),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_TCLASS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVTCLASS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_UNICAST_HOPS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_MULTICAST_HOPS),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVHOPLIMIT),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(linux.IPV6_RECVORIGDSTADDR),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_RECVERR),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
{
seccomp.MatchAny{},
seccomp.EqualTo(unix.SOL_IPV6),
seccomp.EqualTo(unix.IPV6_V6ONLY),
seccomp.MatchAny{},
seccomp.EqualTo(4),
},
},
unix.SYS_SHUTDOWN: []seccomp.Rule{
{
seccomp.MatchAny{},
@@ -469,4 +97,36 @@ func hostInetFilters() seccomp.SyscallRules {
},
unix.SYS_WRITEV: {},
}
getSockOptRules := []seccomp.Rule{}
setSockOptRules := []seccomp.Rule{}
for _, opt := range hostinet.SockOpts {
if opt.AllowGet {
getSockOptRules = append(getSockOptRules, seccomp.Rule{
seccomp.MatchAny{},
seccomp.EqualTo(opt.Level),
seccomp.EqualTo(opt.Name),
})
}
if opt.AllowSet {
if opt.Size > 0 {
setSockOptRules = append(setSockOptRules, seccomp.Rule{
seccomp.MatchAny{},
seccomp.EqualTo(opt.Level),
seccomp.EqualTo(opt.Name),
seccomp.MatchAny{},
seccomp.EqualTo(opt.Size),
})
} else {
setSockOptRules = append(setSockOptRules, seccomp.Rule{
seccomp.MatchAny{},
seccomp.EqualTo(opt.Level),
seccomp.EqualTo(opt.Name),
})
}
}
}
rules[unix.SYS_GETSOCKOPT] = getSockOptRules
rules[unix.SYS_SETSOCKOPT] = setSockOptRules
return rules
}