mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Getting a panic when running tests. For some reason the filter table is
ending up with the wrong chains and is indexing -1 into rules.
This commit is contained in:
@@ -25,7 +25,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
@@ -45,7 +44,7 @@ type metadata struct {
|
||||
}
|
||||
|
||||
// GetInfo returns information about iptables.
|
||||
func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTGetinfo, *syserr.Error) {
|
||||
func GetInfo(t *kernel.Task, stack *stack.Stack, outPtr usermem.Addr) (linux.IPTGetinfo, *syserr.Error) {
|
||||
// Read in the struct and table name.
|
||||
var info linux.IPTGetinfo
|
||||
if _, err := t.CopyIn(outPtr, &info); err != nil {
|
||||
@@ -53,7 +52,7 @@ func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTG
|
||||
}
|
||||
|
||||
// Find the appropriate table.
|
||||
table, err := findTable(ep, info.Name.String())
|
||||
table, err := findTable(stack, info.Name.String())
|
||||
if err != nil {
|
||||
return linux.IPTGetinfo{}, err
|
||||
}
|
||||
@@ -76,7 +75,7 @@ func GetInfo(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr) (linux.IPTG
|
||||
}
|
||||
|
||||
// GetEntries returns netstack's iptables rules encoded for the iptables tool.
|
||||
func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen int) (linux.KernelIPTGetEntries, *syserr.Error) {
|
||||
func GetEntries(t *kernel.Task, stack *stack.Stack, outPtr usermem.Addr, outLen int) (linux.KernelIPTGetEntries, *syserr.Error) {
|
||||
// Read in the struct and table name.
|
||||
var userEntries linux.IPTGetEntries
|
||||
if _, err := t.CopyIn(outPtr, &userEntries); err != nil {
|
||||
@@ -84,7 +83,7 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
|
||||
}
|
||||
|
||||
// Find the appropriate table.
|
||||
table, err := findTable(ep, userEntries.Name.String())
|
||||
table, err := findTable(stack, userEntries.Name.String())
|
||||
if err != nil {
|
||||
return linux.KernelIPTGetEntries{}, err
|
||||
}
|
||||
@@ -103,12 +102,8 @@ func GetEntries(t *kernel.Task, ep tcpip.Endpoint, outPtr usermem.Addr, outLen i
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func findTable(ep tcpip.Endpoint, tableName string) (iptables.Table, *syserr.Error) {
|
||||
ipt, err := ep.IPTables()
|
||||
if err != nil {
|
||||
return iptables.Table{}, syserr.FromError(err)
|
||||
}
|
||||
table, ok := ipt.Tables[tableName]
|
||||
func findTable(stack *stack.Stack, tableName string) (iptables.Table, *syserr.Error) {
|
||||
table, ok := stack.IPTables().Tables[tableName]
|
||||
if !ok {
|
||||
return iptables.Table{}, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
@@ -826,7 +826,11 @@ func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr us
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
info, err := netfilter.GetInfo(t, s.Endpoint, outPtr)
|
||||
stack := inet.StackFromContext(t)
|
||||
if stack == nil {
|
||||
return nil, syserr.ErrNoDevice
|
||||
}
|
||||
info, err := netfilter.GetInfo(t, stack.(*Stack).Stack, outPtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -837,7 +841,11 @@ func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr us
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
|
||||
entries, err := netfilter.GetEntries(t, s.Endpoint, outPtr, outLen)
|
||||
stack := inet.StackFromContext(t)
|
||||
if stack == nil {
|
||||
return nil, syserr.ErrNoDevice
|
||||
}
|
||||
entries, err := netfilter.GetEntries(t, stack.(*Stack).Stack, outPtr, outLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ go_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/iptables",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
importpath = "gvisor.dev/gvisor/pkg/tcpip/iptables",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/log",
|
||||
"//pkg/tcpip",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
// tool.
|
||||
package iptables
|
||||
|
||||
import "github.com/google/netstack/tcpip"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
const (
|
||||
TablenameNat = "nat"
|
||||
@@ -135,31 +140,47 @@ func (it *IPTables) Check(hook Hook, pkt tcpip.PacketBuffer) bool {
|
||||
|
||||
// Go through each table containing the hook.
|
||||
for _, tablename := range it.Priorities[hook] {
|
||||
verdict := it.checkTable(tablename)
|
||||
verdict := it.checkTable(hook, pkt, tablename)
|
||||
switch verdict {
|
||||
// TODO: We either got a final verdict or simply continue on.
|
||||
// If the table returns Accept, move on to the next table.
|
||||
case Accept:
|
||||
continue
|
||||
// The Drop verdict is final.
|
||||
case Drop:
|
||||
log.Infof("kevin: Packet dropped")
|
||||
return false
|
||||
case Stolen, Queue, Repeat, None, Jump, Return, Continue:
|
||||
panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
|
||||
}
|
||||
}
|
||||
|
||||
// Every table returned Accept.
|
||||
log.Infof("kevin: Packet accepted")
|
||||
return true
|
||||
}
|
||||
|
||||
func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) bool {
|
||||
func (it *IPTables) checkTable(hook Hook, pkt tcpip.PacketBuffer, tablename string) Verdict {
|
||||
log.Infof("kevin: iptables.IPTables: checking table %q", tablename)
|
||||
table := it.Tables[tablename]
|
||||
ruleIdx := table.BuiltinChains[hook]
|
||||
log.Infof("kevin: iptables.IPTables: table %+v", table)
|
||||
|
||||
// Start from ruleIdx and go down until a rule gives us a verdict.
|
||||
for ruleIdx := table.BuiltinChains[hook]; ruleIdx < len(table.Rules); ruleIdx++ {
|
||||
verdict := checkRule(hook, pkt, table, ruleIdx)
|
||||
verdict := it.checkRule(hook, pkt, table, ruleIdx)
|
||||
switch verdict {
|
||||
// For either of these cases, this table is done with the
|
||||
// packet.
|
||||
case Accept, Drop:
|
||||
return verdict
|
||||
// Continue traversing the rules of the table.
|
||||
case Continue:
|
||||
continue
|
||||
case Stolen, Queue, Repeat, None, Jump, Return:
|
||||
panic(fmt.Sprintf("Unimplemented verdict %v.", verdict))
|
||||
}
|
||||
}
|
||||
|
||||
panic("Traversed past the entire list of iptables rules.")
|
||||
panic(fmt.Sprintf("Traversed past the entire list of iptables rules in table %q.", tablename))
|
||||
}
|
||||
|
||||
func (it *IPTables) checkRule(hook Hook, pkt tcpip.PacketBuffer, table Table, ruleIdx int) Verdict {
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package iptables
|
||||
|
||||
import "gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
import "gvisor.dev/gvisor/pkg/tcpip"
|
||||
|
||||
// UnconditionalAcceptTarget accepts all packets.
|
||||
type UnconditionalAcceptTarget struct{}
|
||||
|
||||
// Action implements Target.Action.
|
||||
func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (UnconditionalAcceptTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
return Accept, ""
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func (UnconditionalAcceptTarget) Action(packet buffer.VectorisedView) (Verdict,
|
||||
type UnconditionalDropTarget struct{}
|
||||
|
||||
// Action implements Target.Action.
|
||||
func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (UnconditionalDropTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
return Drop, ""
|
||||
}
|
||||
|
||||
@@ -38,6 +38,6 @@ func (UnconditionalDropTarget) Action(packet buffer.VectorisedView) (Verdict, st
|
||||
type PanicTarget struct{}
|
||||
|
||||
// Actions implements Target.Action.
|
||||
func (PanicTarget) Action(packet buffer.VectorisedView) (Verdict, string) {
|
||||
func (PanicTarget) Action(packet tcpip.PacketBuffer) (Verdict, string) {
|
||||
panic("PanicTarget triggered.")
|
||||
}
|
||||
|
||||
@@ -14,9 +14,7 @@
|
||||
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
)
|
||||
import "gvisor.dev/gvisor/pkg/tcpip"
|
||||
|
||||
// A Hook specifies one of the hooks built into the network stack.
|
||||
//
|
||||
@@ -165,7 +163,7 @@ type Matcher interface {
|
||||
// Match returns whether the packet matches and whether the packet
|
||||
// should be "hotdropped", i.e. dropped immediately. This is usually
|
||||
// used for suspicious packets.
|
||||
Match(hook Hook, packet buffer.VectorisedView, interfaceName string) (matches bool, hotdrop bool)
|
||||
Match(hook Hook, packet tcpip.PacketBuffer, interfaceName string) (matches bool, hotdrop bool)
|
||||
}
|
||||
|
||||
// A Target is the interface for taking an action for a packet.
|
||||
@@ -173,5 +171,5 @@ type Target interface {
|
||||
// Action takes an action on the packet and returns a verdict on how
|
||||
// traversal should (or should not) continue. If the return value is
|
||||
// Jump, it also returns the name of the chain to jump to.
|
||||
Action(packet buffer.VectorisedView) (Verdict, string)
|
||||
Action(packet tcpip.PacketBuffer) (Verdict, string)
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
|
||||
return tcpip.Address(h.ProtocolAddressSender()), ProtocolAddress
|
||||
}
|
||||
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
if addrWithPrefix.Address != ProtocolAddress {
|
||||
return nil, tcpip.ErrBadLocalAddress
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ go_library(
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/iptables",
|
||||
"//pkg/tcpip/network/fragmentation",
|
||||
"//pkg/tcpip/network/hash",
|
||||
"//pkg/tcpip/stack",
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/fragmentation"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/hash"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
@@ -54,10 +55,11 @@ type endpoint struct {
|
||||
dispatcher stack.TransportDispatcher
|
||||
fragmentation *fragmentation.Fragmentation
|
||||
protocol *protocol
|
||||
stack *stack.Stack
|
||||
}
|
||||
|
||||
// NewEndpoint creates a new ipv4 endpoint.
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
e := &endpoint{
|
||||
nicID: nicID,
|
||||
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
|
||||
@@ -66,6 +68,7 @@ func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWi
|
||||
dispatcher: dispatcher,
|
||||
fragmentation: fragmentation.NewFragmentation(fragmentation.HighFragThreshold, fragmentation.LowFragThreshold, fragmentation.DefaultReassembleTimeout),
|
||||
protocol: p,
|
||||
stack: st,
|
||||
}
|
||||
|
||||
return e, nil
|
||||
@@ -351,7 +354,8 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt tcpip.PacketBuffer) {
|
||||
pkt.NetworkHeader = headerView[:h.HeaderLength()]
|
||||
|
||||
// iptables filtering.
|
||||
if ok := iptables.Check(iptables.Input, pkt); !ok {
|
||||
ipt := e.stack.IPTables()
|
||||
if ok := ipt.Check(iptables.Input, pkt); !ok {
|
||||
// iptables is telling us to drop the packet.
|
||||
return
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
|
||||
}
|
||||
|
||||
// NewEndpoint creates a new ipv6 endpoint.
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint, st *stack.Stack) (stack.NetworkEndpoint, *tcpip.Error) {
|
||||
return &endpoint{
|
||||
nicID: nicID,
|
||||
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
|
||||
|
||||
@@ -467,7 +467,7 @@ func (n *NIC) addAddressLocked(protocolAddress tcpip.ProtocolAddress, peb Primar
|
||||
}
|
||||
|
||||
// Create the new network endpoint.
|
||||
ep, err := netProto.NewEndpoint(n.id, protocolAddress.AddressWithPrefix, n.stack, n, n.linkEP)
|
||||
ep, err := netProto.NewEndpoint(n.id, protocolAddress.AddressWithPrefix, n.stack, n, n.linkEP, n.stack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ type NetworkProtocol interface {
|
||||
ParseAddresses(v buffer.View) (src, dst tcpip.Address)
|
||||
|
||||
// NewEndpoint creates a new endpoint of this protocol.
|
||||
NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint) (NetworkEndpoint, *tcpip.Error)
|
||||
NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint, st *Stack) (NetworkEndpoint, *tcpip.Error)
|
||||
|
||||
// SetOption allows enabling/disabling protocol specific features.
|
||||
// SetOption returns an error if the option is not supported or the
|
||||
|
||||
@@ -40,7 +40,6 @@ import (
|
||||
"time"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/iptables"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
@@ -446,9 +445,6 @@ type Endpoint interface {
|
||||
// NOTE: This method is a no-op for sockets other than TCP.
|
||||
ModerateRecvBuf(copied int)
|
||||
|
||||
// IPTables returns the iptables for this endpoint's stack.
|
||||
IPTables() (iptables.IPTables, error)
|
||||
|
||||
// Info returns a copy to the transport endpoint info.
|
||||
Info() EndpointInfo
|
||||
|
||||
|
||||
Reference in New Issue
Block a user