diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-01-29 13:44:57 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-02-09 20:14:33 +0100 |
| commit | 033b610ec91096a5791c90761df1289fd33280e6 (patch) | |
| tree | 57863e9e73f2d664640d7c889cd052138017f4a5 /sys/linux/init_iptables.go | |
| parent | bb826eb26c510f5faa418b8a37302be43d535088 (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.go | 61 |
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 |
