iptables: check revision numbers and support owner matcher v1

This change also replaces use of kernel.Task with a narrower type (IDMapper) in
preparation for a follow-up CL.

PiperOrigin-RevId: 578387814
This commit is contained in:
Kevin Krakauer
2023-10-31 21:17:26 -07:00
committed by gVisor bot
parent 5f75371657
commit 7f08016fb8
13 changed files with 329 additions and 42 deletions
+23 -5
View File
@@ -633,8 +633,8 @@ const (
XT_UDP_INV_MASK = 0x03
)
// IPTOwnerInfo holds data for matching packets with owner. It corresponds
// to struct ipt_owner_info in libxt_owner.c of iptables binary.
// IPTOwnerInfo holds data for matching packets with the owner v0 matcher. It
// corresponds to struct ipt_owner_info in libxt_owner.c of iptables binary.
//
// +marshal
type IPTOwnerInfo struct {
@@ -661,11 +661,29 @@ type IPTOwnerInfo struct {
Invert uint8 `marshal:"unaligned"`
}
// SizeOfIPTOwnerInfo is the size of an XTOwnerMatchInfo.
// SizeOfIPTOwnerInfo is the size of an IPTOwnerInfo.
const SizeOfIPTOwnerInfo = 34
// Flags in IPTOwnerInfo.Match. Corresponding constants are in
// include/uapi/linux/netfilter/xt_owner.h.
// XTOwnerMatchInfo holds data for matching packets with the owner v1 matcher.
// It corresponds to struct xt_owner_match_info in
// include/uapi/linux/netfilter/xt_owner.h
//
// +marshal
type XTOwnerMatchInfo struct {
UIDMin uint32
UIDMax uint32
GIDMin uint32
GIDMax uint32
Match uint8
Invert uint8
_ [2]byte
}
// SizeOfXTOwnerMatchInfo is the size of an XTOwnerMatchInfo.
const SizeOfXTOwnerMatchInfo = 20
// Flags in IPTOwnerInfo.Match and XTOwnerMatchInfo.Match. Corresponding
// constants are in include/uapi/linux/netfilter/xt_owner.h.
const (
// Match the UID of the packet.
XT_OWNER_UID = 1 << 0
+13 -1
View File
@@ -1,4 +1,4 @@
load("//tools:defs.bzl", "go_library")
load("//tools:defs.bzl", "go_library", "go_test")
package(
default_applicable_licenses = ["//:license"],
@@ -13,6 +13,7 @@ go_library(
"ipv6.go",
"netfilter.go",
"owner_matcher.go",
"owner_matcher_v1.go",
"targets.go",
"tcp_matcher.go",
"udp_matcher.go",
@@ -35,3 +36,14 @@ go_library(
"//pkg/tcpip/stack",
],
)
go_test(
name = "netfilter_test",
srcs = ["netfilter_test.go"],
embedsrcs = ["istio_blob"],
library = ":netfilter",
deps = [
"//pkg/sentry/kernel/auth",
"//pkg/tcpip/stack",
],
)
+37 -13
View File
@@ -19,45 +19,65 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
// matchMaker knows how to (un)marshal the matcher named name().
// matchMaker knows how to (un)marshal the matcher named name(). UPDATE THIS
type matchMaker interface {
// name is the matcher name as stored in the xt_entry_match struct.
name() string
// revision is the match revision as stored in the xt_entry_match
// struct.
revision() uint8
// marshal converts from a stack.Matcher to an ABI struct.
marshal(matcher matcher) []byte
// unmarshal converts from the ABI matcher struct to an
// stack.Matcher.
unmarshal(task *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error)
unmarshal(mapper IDMapper, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error)
}
type matchKey struct {
name string
revision uint8
}
func key(mm matchMaker) matchKey {
return matchKey{
name: mm.name(),
revision: mm.revision(),
}
}
type matcher interface {
name() string
revision() uint8
}
// matchMakers maps the name of supported matchers to the matchMaker that
// marshals and unmarshals it. It is immutable after package initialization.
var matchMakers = map[string]matchMaker{}
var matchMakers = map[matchKey]matchMaker{}
// registermatchMaker should be called by match extensions to register them
// with the netfilter package.
func registerMatchMaker(mm matchMaker) {
if _, ok := matchMakers[mm.name()]; ok {
panic(fmt.Sprintf("Multiple matches registered with name %q.", mm.name()))
if _, ok := matchMakers[key(mm)]; ok {
panic(fmt.Sprintf("Multiple matches registered with key %+v.", key(mm)))
}
matchMakers[mm.name()] = mm
matchMakers[key(mm)] = mm
}
func marshalMatcher(mr stack.Matcher) []byte {
matcher := mr.(matcher)
matchMaker, ok := matchMakers[matcher.name()]
key := matchKey{
name: matcher.name(),
revision: matcher.revision(),
}
matchMaker, ok := matchMakers[key]
if !ok {
panic(fmt.Sprintf("Unknown matcher of type %T.", matcher))
}
@@ -85,12 +105,16 @@ func marshalEntryMatch(name string, data []byte) []byte {
return buf
}
func unmarshalMatcher(task *kernel.Task, match linux.XTEntryMatch, filter stack.IPHeaderFilter, buf []byte) (stack.Matcher, error) {
matchMaker, ok := matchMakers[match.Name.String()]
if !ok {
return nil, fmt.Errorf("unsupported matcher with name %q", match.Name.String())
func unmarshalMatcher(mapper IDMapper, match linux.XTEntryMatch, filter stack.IPHeaderFilter, buf []byte) (stack.Matcher, error) {
key := matchKey{
name: match.Name.String(),
revision: match.Revision,
}
return matchMaker.unmarshal(task, buf, filter)
matchMaker, ok := matchMakers[key]
if !ok {
return nil, fmt.Errorf("unsupported matcher with name %q and revision %d", match.Name.String(), match.Revision)
}
return matchMaker.unmarshal(mapper, buf, filter)
}
// targetMaker knows how to (un)marshal a target. Once registered,
+2 -3
View File
@@ -18,7 +18,6 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -126,7 +125,7 @@ func getEntries4(table stack.Table, tablename linux.TableName) (linux.KernelIPTG
return entries, info
}
func modifyEntries4(task *kernel.Task, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
func modifyEntries4(mapper IDMapper, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
nflog("set entries: setting entries in table %q", replace.Name.String())
// Convert input into a list of rules and their offsets.
@@ -162,7 +161,7 @@ func modifyEntries4(task *kernel.Task, stk *stack.Stack, optVal []byte, replace
nflog("entry doesn't have enough room for its matchers (only %d bytes remain)", len(optVal))
return nil, syserr.ErrInvalidArgument
}
matchers, err := parseMatchers(task, filter, optVal[:matchersSize])
matchers, err := parseMatchers(mapper, filter, optVal[:matchersSize])
if err != nil {
nflog("failed to parse matchers: %v", err)
return nil, syserr.ErrInvalidArgument
+2 -3
View File
@@ -18,7 +18,6 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -129,7 +128,7 @@ func getEntries6(table stack.Table, tablename linux.TableName) (linux.KernelIP6T
return entries, info
}
func modifyEntries6(task *kernel.Task, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
func modifyEntries6(mapper IDMapper, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
nflog("set entries: setting entries in table %q", replace.Name.String())
// Convert input into a list of rules and their offsets.
@@ -165,7 +164,7 @@ func modifyEntries6(task *kernel.Task, stk *stack.Stack, optVal []byte, replace
nflog("entry doesn't have enough room for its matchers (only %d bytes remain)", len(optVal))
return nil, syserr.ErrInvalidArgument
}
matchers, err := parseMatchers(task, filter, optVal[:matchersSize])
matchers, err := parseMatchers(mapper, filter, optVal[:matchersSize])
if err != nil {
nflog("failed to parse matchers: %v", err)
return nil, syserr.ErrInvalidArgument
Binary file not shown.
+13 -6
View File
@@ -26,6 +26,7 @@ import (
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -34,7 +35,7 @@ import (
// enableLogging controls whether to log the (de)serialization of netfilter
// structs between userspace and netstack. These logs are useful when
// developing iptables, but can pollute sentry logs otherwise.
const enableLogging = false
const enableLogging = true
// nflog logs messages related to the writing and reading of iptables.
func nflog(format string, args ...any) {
@@ -173,9 +174,15 @@ func setHooksAndUnderflow(info *linux.IPTGetinfo, table stack.Table, offset uint
}
}
// An IDMapper maps UIDs and GIDs to KUIDs and KGIDs.
type IDMapper interface {
MapToKUID(uid auth.UID) auth.KUID
MapToKGID(uid auth.GID) auth.KGID
}
// SetEntries sets iptables rules for a single table. See
// net/ipv4/netfilter/ip_tables.c:translate_table for reference.
func SetEntries(task *kernel.Task, stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
func SetEntries(mapper IDMapper, stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
var replace linux.IPTReplace
optVal = replace.UnmarshalBytes(optVal)
@@ -193,9 +200,9 @@ func SetEntries(task *kernel.Task, stk *stack.Stack, optVal []byte, ipv6 bool) *
var err *syserr.Error
var offsets map[uint32]int
if ipv6 {
offsets, err = modifyEntries6(task, stk, optVal, &replace, &table)
offsets, err = modifyEntries6(mapper, stk, optVal, &replace, &table)
} else {
offsets, err = modifyEntries4(task, stk, optVal, &replace, &table)
offsets, err = modifyEntries4(mapper, stk, optVal, &replace, &table)
}
if err != nil {
return err
@@ -295,7 +302,7 @@ func SetEntries(task *kernel.Task, stk *stack.Stack, optVal []byte, ipv6 bool) *
// parseMatchers parses 0 or more matchers from optVal. optVal should contain
// only the matchers.
func parseMatchers(task *kernel.Task, filter stack.IPHeaderFilter, optVal []byte) ([]stack.Matcher, error) {
func parseMatchers(mapper IDMapper, filter stack.IPHeaderFilter, optVal []byte) ([]stack.Matcher, error) {
nflog("set entries: parsing matchers of size %d", len(optVal))
var matchers []stack.Matcher
for len(optVal) > 0 {
@@ -318,7 +325,7 @@ func parseMatchers(task *kernel.Task, filter stack.IPHeaderFilter, optVal []byte
}
// Parse the specific matcher.
matcher, err := unmarshalMatcher(task, match, filter, optVal[linux.SizeOfXTEntryMatch:match.MatchSize])
matcher, err := unmarshalMatcher(mapper, match, filter, optVal[linux.SizeOfXTEntryMatch:match.MatchSize])
if err != nil {
return nil, fmt.Errorf("failed to create matcher: %v", err)
}
@@ -0,0 +1,56 @@
// 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 netfilter
import (
_ "embed"
"testing"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
// istioBlob is a golden iptables ruleset generated by Istio. It is already in
// the format ready to by passed to IPT_SO_SET_REPLACE.
//
// Updating this requires running Istio, calling IPT_SO_GET_INFO and
// IPT_SO_GET_ENTRIES, then stitching the structs up. So be careful when
// updating!
//
//go:embed istio_blob
var istioBlob []byte
// FakeIDMapper implements IDMapper.
type FakeIDMapper struct{}
// MapToKUID implements IDMapper.
func (*FakeIDMapper) MapToKUID(auth.UID) auth.KUID {
return 0
}
// MapToKGID implements IDMapper.
func (*FakeIDMapper) MapToKGID(auth.GID) auth.KGID {
return 0
}
// TestIstioBlob tests that we support the iptables ruleset generated by Istio,
// i.e. that we can parse the rules and set them in netstack.
func TestIstioBlob(t *testing.T) {
mapper := FakeIDMapper{}
stack := stack.New(stack.Options{})
if err := SetEntries(&mapper, stack, istioBlob, false); err != nil {
t.Fatalf("failed to set Istio rules, try setting enableLogging and running again: %v", err)
}
}
+11 -5
View File
@@ -19,7 +19,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -38,6 +37,10 @@ func (ownerMarshaler) name() string {
return matcherNameOwner
}
func (ownerMarshaler) revision() uint8 {
return 0
}
// marshal implements matchMaker.marshal.
func (ownerMarshaler) marshal(mr matcher) []byte {
matcher := mr.(*OwnerMatcher)
@@ -65,7 +68,7 @@ func (ownerMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
func (ownerMarshaler) unmarshal(task *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
func (ownerMarshaler) unmarshal(mapper IDMapper, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfIPTOwnerInfo {
return nil, fmt.Errorf("buf has insufficient size for owner match: %d", len(buf))
}
@@ -77,9 +80,8 @@ func (ownerMarshaler) unmarshal(task *kernel.Task, buf []byte, filter stack.IPHe
nflog("parsed IPTOwnerInfo: %+v", matchData)
var owner OwnerMatcher
creds := task.Credentials()
owner.uid = creds.UserNamespace.MapToKUID(auth.UID(matchData.UID))
owner.gid = creds.UserNamespace.MapToKGID(auth.GID(matchData.GID))
owner.uid = mapper.MapToKUID(auth.UID(matchData.UID))
owner.gid = mapper.MapToKGID(auth.GID(matchData.GID))
// Check flags.
if matchData.Match&linux.XT_OWNER_UID != 0 {
@@ -113,6 +115,10 @@ func (*OwnerMatcher) name() string {
return matcherNameOwner
}
func (*OwnerMatcher) revision() uint8 {
return 0
}
// Match implements Matcher.Match.
func (om *OwnerMatcher) Match(hook stack.Hook, pkt stack.PacketBufferPtr, _, _ string) (bool, bool) {
// Support only for OUTPUT chain.
@@ -0,0 +1,152 @@
// 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 netfilter
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
func init() {
registerMatchMaker(ownerMarshalerV1{})
}
// ownerMarshalerV1 implements matchMaker for owner matching.
type ownerMarshalerV1 struct{}
// name implements matchMaker.name.
func (ownerMarshalerV1) name() string {
return matcherNameOwner
}
func (ownerMarshalerV1) revision() uint8 {
return 1
}
// marshal implements matchMaker.marshal.
func (ownerMarshalerV1) marshal(mr matcher) []byte {
matcher := mr.(*OwnerMatcherV1)
ownerInfo := linux.XTOwnerMatchInfo{
UIDMin: uint32(matcher.uid),
UIDMax: uint32(matcher.uid),
GIDMin: uint32(matcher.gid),
GIDMax: uint32(matcher.gid),
}
// Support for UID and GID match.
if matcher.matchUID {
ownerInfo.Match |= linux.XT_OWNER_UID
}
if matcher.matchGID {
ownerInfo.Match |= linux.XT_OWNER_GID
}
if matcher.invertUID {
ownerInfo.Invert |= linux.XT_OWNER_UID
}
if matcher.invertGID {
ownerInfo.Invert |= linux.XT_OWNER_GID
}
buf := marshal.Marshal(&ownerInfo)
return marshalEntryMatch(matcherNameOwner, buf)
}
// unmarshal implements matchMaker.unmarshal.
func (ownerMarshalerV1) unmarshal(mapper IDMapper, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfXTOwnerMatchInfo {
return nil, fmt.Errorf("buf has insufficient size for owner match: %d", len(buf))
}
// For alignment reasons, the match's total size may
// exceed what's strictly necessary to hold matchData.
var matchData linux.XTOwnerMatchInfo
matchData.UnmarshalUnsafe(buf)
nflog("parsed XTOwnerMatchInfo: %+v", matchData)
if matchData.UIDMin != matchData.UIDMax {
nflog("owner v1 doesn't support differing UID min/max")
}
if matchData.GIDMin != matchData.GIDMax {
nflog("owner v1 doesn't support differing GID min/max")
}
owner := OwnerMatcherV1{
uid: mapper.MapToKUID(auth.UID(matchData.UIDMin)),
gid: mapper.MapToKGID(auth.GID(matchData.GIDMin)),
matchUID: matchData.Match&linux.XT_OWNER_UID != 0,
matchGID: matchData.Match&linux.XT_OWNER_GID != 0,
invertUID: matchData.Invert&linux.XT_OWNER_UID != 0,
invertGID: matchData.Invert&linux.XT_OWNER_GID != 0,
}
return &owner, nil
}
// OwnerMatcherV1 matches against a UID and/or GID.
type OwnerMatcherV1 struct {
uid auth.KUID
gid auth.KGID
matchUID bool
matchGID bool
invertUID bool
invertGID bool
}
// name implements matcher.name.
func (*OwnerMatcherV1) name() string {
return matcherNameOwner
}
func (*OwnerMatcherV1) revision() uint8 {
return 1
}
// Match implements Matcher.Match.
func (om *OwnerMatcherV1) Match(hook stack.Hook, pkt stack.PacketBufferPtr, _, _ string) (bool, bool) {
// Support only for OUTPUT chain.
if hook != stack.Output {
return false, true
}
// If the packet owner is not set, drop the packet.
if pkt.Owner == nil {
return false, true
}
var matches bool
// Check for UID match.
if om.matchUID {
if auth.KUID(pkt.Owner.KUID()) == om.uid {
matches = true
}
if matches == om.invertUID {
return false, false
}
}
// Check for GID match.
if om.matchGID {
matches = false
if auth.KGID(pkt.Owner.KGID()) == om.gid {
matches = true
}
if matches == om.invertGID {
return false, false
}
}
return true, false
}
+9 -2
View File
@@ -19,7 +19,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -38,6 +37,10 @@ func (tcpMarshaler) name() string {
return matcherNameTCP
}
func (tcpMarshaler) revision() uint8 {
return 0
}
// marshal implements matchMaker.marshal.
func (tcpMarshaler) marshal(mr matcher) []byte {
matcher := mr.(*TCPMatcher)
@@ -51,7 +54,7 @@ func (tcpMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
func (tcpMarshaler) unmarshal(_ *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
func (tcpMarshaler) unmarshal(_ IDMapper, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfXTTCP {
return nil, fmt.Errorf("buf has insufficient size for TCP match: %d", len(buf))
}
@@ -94,6 +97,10 @@ func (*TCPMatcher) name() string {
return matcherNameTCP
}
func (*TCPMatcher) revision() uint8 {
return 0
}
// Match implements Matcher.Match.
func (tm *TCPMatcher) Match(hook stack.Hook, pkt stack.PacketBufferPtr, _, _ string) (bool, bool) {
switch pkt.NetworkProtocolNumber {
+9 -2
View File
@@ -19,7 +19,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -38,6 +37,10 @@ func (udpMarshaler) name() string {
return matcherNameUDP
}
func (udpMarshaler) revision() uint8 {
return 0
}
// marshal implements matchMaker.marshal.
func (udpMarshaler) marshal(mr matcher) []byte {
matcher := mr.(*UDPMatcher)
@@ -51,7 +54,7 @@ func (udpMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
func (udpMarshaler) unmarshal(_ *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
func (udpMarshaler) unmarshal(_ IDMapper, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfXTUDP {
return nil, fmt.Errorf("buf has insufficient size for UDP match: %d", len(buf))
}
@@ -91,6 +94,10 @@ func (*UDPMatcher) name() string {
return matcherNameUDP
}
func (*UDPMatcher) revision() uint8 {
return 0
}
// Match implements Matcher.Match.
func (um *UDPMatcher) Match(hook stack.Hook, pkt stack.PacketBufferPtr, _, _ string) (bool, bool) {
switch pkt.NetworkProtocolNumber {
+2 -2
View File
@@ -2311,7 +2311,7 @@ func setSockOptIPv6(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int
return syserr.ErrNoDevice
}
// Stack must be a netstack stack.
return netfilter.SetEntries(t, stk.(*Stack).Stack, optVal, true)
return netfilter.SetEntries(t.Credentials().UserNamespace, stk.(*Stack).Stack, optVal, true)
case linux.IP6T_SO_SET_ADD_COUNTERS:
log.Infof("IP6T_SO_SET_ADD_COUNTERS is not supported")
@@ -2558,7 +2558,7 @@ func setSockOptIP(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int,
return syserr.ErrNoDevice
}
// Stack must be a netstack stack.
return netfilter.SetEntries(t, stk.(*Stack).Stack, optVal, false)
return netfilter.SetEntries(t.Credentials().UserNamespace, stk.(*Stack).Stack, optVal, false)
case linux.IPT_SO_SET_ADD_COUNTERS:
log.Infof("IPT_SO_SET_ADD_COUNTERS is not supported")