mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
committed by
gVisor bot
parent
753fb9ac5e
commit
ec1abcf521
@@ -9,6 +9,7 @@ go_library(
|
||||
"hostinet.go",
|
||||
"socket.go",
|
||||
"socket_unsafe.go",
|
||||
"sockopt.go",
|
||||
"sockopt_impl.go",
|
||||
"stack.go",
|
||||
"stack_unsafe.go",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user