1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package linux
import (
"strings"
"github.com/google/syzkaller/prog"
)
func (arch *arch) generateIptables(g *prog.Gen, typ prog.Type, old prog.Arg) (
arg prog.Arg, calls []*prog.Call) {
if old == nil {
arg = g.GenerateSpecialArg(typ, &calls)
} else {
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")
}
entriesArg := tableArg.Inner[16].(*prog.GroupArg)
if len(entriesArg.Inner) != 2 {
panic("iptable entries is expected to have 2 fields")
}
underflowArg := entriesArg.Inner[0].(*prog.GroupArg)
entriesArray := entriesArg.Inner[1].(*prog.GroupArg)
// Collect offsets of entries.
offsets := make([]uint64, len(entriesArray.Inner))
pos := underflowArg.Size()
for i, entryArg := range entriesArray.Inner {
offsets[i] = pos
pos += entryArg.Size()
}
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
} else {
return offsets[g.Rand().Intn(len(offsets))]
}
}
// Assign offsets to used hooks.
for hook := 4; hook < 9; hook++ {
hookArg := tableArg.Inner[hook].(*prog.ConstArg)
if hookArg.Type().(*prog.ConstType).Val == uint64(^uint32(0)) {
continue // unused hook
}
hookArg.Val = genOffset()
}
// Now update standard target jump offsets.
prog.ForeachSubarg(arg, func(arg, _ prog.Arg, _ *[]prog.Arg) {
if !strings.HasPrefix(arg.Type().Name(), `xt_target_t["", `) {
return
}
targetArg := arg.(*prog.GroupArg)
valArg := targetArg.Inner[3].(*prog.ConstArg)
if flagsType, ok := valArg.Type().(*prog.FlagsType); ok && int64(valArg.Val) < 0 {
for _, val := range flagsType.Vals {
if val == valArg.Val {
return // verdict
}
}
}
valArg.Val = genOffset()
})
return
}
|