aboutsummaryrefslogtreecommitdiffstats
path: root/sys/linux/init_iptables.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-01-29 13:44:57 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-02-09 20:14:33 +0100
commit033b610ec91096a5791c90761df1289fd33280e6 (patch)
tree57863e9e73f2d664640d7c889cd052138017f4a5 /sys/linux/init_iptables.go
parentbb826eb26c510f5faa418b8a37302be43d535088 (diff)
sys/linux: improve netfilter descriptions
Put the underflow entry at the end. Entries must end on an unconditional, non-goto entry, otherwise fallthrough from the last entry is invalid. Add arp tables support. Split unspec matches/targets to unspec and inet. Reset ipv6 and arp tables in executor. Fix number of counters in tables. Plus a bunch of assorted fixes for matches/targets.
Diffstat (limited to 'sys/linux/init_iptables.go')
-rw-r--r--sys/linux/init_iptables.go61
1 files changed, 49 insertions, 12 deletions
diff --git a/sys/linux/init_iptables.go b/sys/linux/init_iptables.go
index 1a5a1ccc9..c33204496 100644
--- a/sys/linux/init_iptables.go
+++ b/sys/linux/init_iptables.go
@@ -11,46 +11,79 @@ import (
func (arch *arch) generateIptables(g *prog.Gen, typ prog.Type, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
+ return arch.generateNetfilterTable(g, typ, old, true, 5)
+}
+
+func (arch *arch) generateArptables(g *prog.Gen, typ prog.Type, old prog.Arg) (
+ arg prog.Arg, calls []*prog.Call) {
+ return arch.generateNetfilterTable(g, typ, old, false, 3)
+}
+
+func (arch *arch) generateNetfilterTable(g *prog.Gen, typ prog.Type, old prog.Arg,
+ hasUnion bool, hookCount int) (arg prog.Arg, calls []*prog.Call) {
+ const (
+ hookStart = 4
+ nonHookFields = 7
+ unused = uint64(^uint32(0))
+ )
if old == nil {
arg = g.GenerateSpecialArg(typ, &calls)
} else {
+ // TODO(dvyukov): try to restore original hook order after mutation
+ // instead of assigning brand new offsets.
arg = old
calls = g.MutateArg(arg)
}
- tableArg := arg.(*prog.UnionArg).Option.(*prog.GroupArg)
- if len(tableArg.Inner) != 17 {
- panic("iptable is expected to have 17 fields")
+ var tableArg *prog.GroupArg
+ if hasUnion {
+ tableArg = arg.(*prog.UnionArg).Option.(*prog.GroupArg)
+ } else {
+ tableArg = arg.(*prog.GroupArg)
+ }
+ numFileds := nonHookFields + 2*hookCount
+ if len(tableArg.Inner) != numFileds {
+ panic("wrong number of fields in netfilter table")
}
- entriesArg := tableArg.Inner[16].(*prog.GroupArg)
+ entriesArg := tableArg.Inner[numFileds-1].(*prog.GroupArg)
if len(entriesArg.Inner) != 2 {
- panic("iptable entries is expected to have 2 fields")
+ panic("netfilter entries is expected to have 2 fields")
}
- underflowArg := entriesArg.Inner[0].(*prog.GroupArg)
- entriesArray := entriesArg.Inner[1].(*prog.GroupArg)
+ entriesArray := entriesArg.Inner[0].(*prog.GroupArg)
// Collect offsets of entries.
offsets := make([]uint64, len(entriesArray.Inner))
- pos := underflowArg.Size()
+ var pos uint64
for i, entryArg := range entriesArray.Inner {
offsets[i] = pos
pos += entryArg.Size()
}
+ if pos != entriesArray.Size() {
+ panic("netfilter offsets are broken")
+ }
genOffset := func() uint64 {
if g.Rand().Intn(100) == 0 {
// Assign the underflow entry once in a while.
// We have it in underflow hooks, so no point in using it frequently.
- return 0
+ return pos
} else {
return offsets[g.Rand().Intn(len(offsets))]
}
}
// Assign offsets to used hooks.
- for hook := 4; hook < 9; hook++ {
+ for hook := hookStart; hook < hookStart+hookCount; hook++ {
hookArg := tableArg.Inner[hook].(*prog.ConstArg)
- if hookArg.Type().(*prog.ConstType).Val == uint64(^uint32(0)) {
+ if hookArg.Type().(*prog.ConstType).Val == unused {
continue // unused hook
}
hookArg.Val = genOffset()
}
+ // Assign offsets to used underflow entries.
+ for hook := hookStart + hookCount; hook < hookStart+2*hookCount; hook++ {
+ hookArg := tableArg.Inner[hook].(*prog.ConstArg)
+ if hookArg.Type().(*prog.ConstType).Val == unused {
+ continue // unused hook
+ }
+ hookArg.Val = pos
+ }
// Now update standard target jump offsets.
prog.ForeachSubarg(arg, func(arg, _ prog.Arg, _ *[]prog.Arg) {
if !strings.HasPrefix(arg.Type().Name(), `xt_target_t["", `) {
@@ -58,7 +91,11 @@ func (arch *arch) generateIptables(g *prog.Gen, typ prog.Type, old prog.Arg) (
}
targetArg := arg.(*prog.GroupArg)
valArg := targetArg.Inner[3].(*prog.ConstArg)
- if flagsType, ok := valArg.Type().(*prog.FlagsType); ok && int64(valArg.Val) < 0 {
+ flagsType, ok := valArg.Type().(*prog.FlagsType)
+ if !ok {
+ return
+ }
+ if int64(valArg.Val) < 0 {
for _, val := range flagsType.Vals {
if val == valArg.Val {
return // verdict