aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-05 13:31:14 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-05 15:52:42 +0200
commitffe7e17368d7ae6c2b40da2ce0703d8ad8a116ac (patch)
tree195b7c32977fdaab05acb1282a727fb480593431
parent4fc47026945ebec3fc81d0c897547670034cfb58 (diff)
prog, sys: move types to prog
Large overhaul moves syscalls and arg types from sys to prog. Sys package now depends on prog and contains only generated descriptions of syscalls. Introduce prog.Target type that encapsulates all targer properties, like syscall list, ptr/page size, etc. Also moves OS-dependent pieces like mmap call generation from prog to sys. Update #191
-rw-r--r--pkg/compiler/check.go22
-rw-r--r--pkg/compiler/compiler.go26
-rw-r--r--pkg/compiler/gen.go112
-rw-r--r--pkg/compiler/types.go172
-rw-r--r--pkg/csource/csource.go4
-rw-r--r--pkg/csource/csource_test.go1
-rw-r--r--pkg/host/host.go32
-rw-r--r--pkg/host/host_test.go11
-rw-r--r--pkg/ipc/ipc_test.go1
-rw-r--r--prog/analysis.go124
-rw-r--r--prog/checksum.go2
-rw-r--r--prog/checksum_test.go11
-rw-r--r--prog/decl_test.go (renamed from sys/decl_test.go)4
-rw-r--r--prog/encoding.go24
-rw-r--r--prog/encoding_test.go7
-rw-r--r--prog/encodingexec.go5
-rw-r--r--prog/encodingexec_test.go13
-rw-r--r--prog/export_test.go47
-rw-r--r--prog/hints.go6
-rw-r--r--prog/hints_test.go2
-rw-r--r--prog/mutation.go25
-rw-r--r--prog/mutation_test.go27
-rw-r--r--prog/prio.go2
-rw-r--r--prog/prog.go26
-rw-r--r--prog/prog_test.go35
-rw-r--r--prog/rand.go141
-rw-r--r--prog/size.go14
-rw-r--r--prog/size_test.go13
-rw-r--r--prog/target.go117
-rw-r--r--prog/types.go (renamed from sys/decl.go)73
-rw-r--r--prog/validation.go2
-rw-r--r--sys/init.go257
-rw-r--r--sys/sys_386.go6
-rw-r--r--sys/sys_amd64.go6
-rw-r--r--sys/sys_arm.go6
-rw-r--r--sys/sys_arm64.go6
-rw-r--r--sys/sys_ppc64le.go6
-rw-r--r--sys/syz-sysgen/syscallnr.go4
-rw-r--r--sys/syz-sysgen/sysgen.go5
-rw-r--r--syz-fuzzer/fuzzer.go16
-rw-r--r--syz-manager/html.go5
-rw-r--r--syz-manager/manager.go1
-rw-r--r--syz-manager/mgrconfig/mgrconfig.go13
-rw-r--r--tools/syz-execprog/execprog.go1
-rw-r--r--tools/syz-mutate/mutate.go1
-rw-r--r--tools/syz-stress/stress.go12
-rw-r--r--tools/syz-upgrade/upgrade.go1
47 files changed, 793 insertions, 654 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 7b0cf34aa..99ac1d447 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -9,7 +9,7 @@ import (
"fmt"
"github.com/google/syzkaller/pkg/ast"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
func (comp *compiler) check() {
@@ -191,7 +191,7 @@ func (comp *compiler) checkLenType(t *ast.Type, name string, fields []*ast.Field
}
return
}
- _, args, _ := comp.getArgsBase(t, "", sys.DirIn, isArg)
+ _, args, _ := comp.getArgsBase(t, "", prog.DirIn, isArg)
for i, arg := range args {
argDesc := desc.Args[i]
if argDesc.Type == typeArgLenTarget {
@@ -232,7 +232,7 @@ func (comp *compiler) checkLenTarget(t *ast.Type, name, target string, fields []
type structDir struct {
Struct string
- Dir sys.Dir
+ Dir prog.Dir
}
func (comp *compiler) checkConstructors() {
@@ -242,10 +242,10 @@ func (comp *compiler) checkConstructors() {
switch n := decl.(type) {
case *ast.Call:
for _, arg := range n.Args {
- comp.checkTypeCtors(arg.Type, sys.DirIn, true, ctors, checked)
+ comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, checked)
}
if n.Ret != nil {
- comp.checkTypeCtors(n.Ret, sys.DirOut, true, ctors, checked)
+ comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, checked)
}
}
}
@@ -261,16 +261,16 @@ func (comp *compiler) checkConstructors() {
}
}
-func (comp *compiler) checkTypeCtors(t *ast.Type, dir sys.Dir, isArg bool,
+func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
ctors map[string]bool, checked map[structDir]bool) {
desc := comp.getTypeDesc(t)
if desc == typeResource {
- // TODO(dvyukov): consider changing this to "dir == sys.DirOut".
+ // TODO(dvyukov): consider changing this to "dir == prog.DirOut".
// We have few questionable cases where resources can be created
// only by inout struct fields. These structs should be split
// into two different structs: one is in and second is out.
// But that will require attaching dir to individual fields.
- if dir != sys.DirIn {
+ if dir != prog.DirIn {
r := comp.resources[t.Ident]
for r != nil && !ctors[r.Name.Name] {
ctors[r.Name.Name] = true
@@ -376,7 +376,7 @@ func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []
comp.checkStructRecursion(checked, comp.structs[t.Ident], path)
return
}
- _, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
+ _, args, base := comp.getArgsBase(t, "", prog.DirIn, false)
if desc == typePtr && base.IsOptional {
return // optional pointers prune recursion
}
@@ -464,7 +464,7 @@ func (comp *compiler) checkType(t *ast.Type, isArg, isRet, isStruct, isResourceB
return
}
if desc.Check != nil {
- _, args, base := comp.getArgsBase(t, "", sys.DirIn, isArg)
+ _, args, base := comp.getArgsBase(t, "", prog.DirIn, isArg)
desc.Check(comp, t, args, base)
}
}
@@ -574,7 +574,7 @@ func (comp *compiler) checkVarlens() {
}
func (comp *compiler) isVarlen(t *ast.Type) bool {
- desc, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
+ desc, args, base := comp.getArgsBase(t, "", prog.DirIn, false)
return desc.Varlen != nil && desc.Varlen(comp, t, args, base)
}
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go
index 8cccf53c4..f6641f9c9 100644
--- a/pkg/compiler/compiler.go
+++ b/pkg/compiler/compiler.go
@@ -12,7 +12,7 @@ import (
"strings"
"github.com/google/syzkaller/pkg/ast"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
// Overview of compilation process:
@@ -22,20 +22,20 @@ import (
// This step also does verification of include/incdir/define AST nodes.
// 3. User translates constants to values.
// 4. Compile on AST and const values does the rest of the work and returns Prog
-// containing generated sys objects.
+// containing generated prog objects.
// 4.1. assignSyscallNumbers: uses consts to assign syscall numbers.
// This step also detects unsupported syscalls and discards no longer
// needed AST nodes (inlcude, define, comments, etc).
// 4.2. patchConsts: patches Int nodes refering to consts with corresponding values.
// Also detects unsupported syscalls, structs, resources due to missing consts.
// 4.3. check: does extensive semantical checks of AST.
-// 4.4. gen: generates sys objects from AST.
+// 4.4. gen: generates prog objects from AST.
// Prog is description compilation result.
type Prog struct {
- Resources []*sys.ResourceDesc
- Syscalls []*sys.Syscall
- StructDescs []*sys.KeyedStruct
+ Resources []*prog.ResourceDesc
+ Syscalls []*prog.Syscall
+ StructDescs []*prog.KeyedStruct
// Set of unsupported syscalls/flags.
Unsupported map[string]bool
}
@@ -54,8 +54,8 @@ func Compile(desc *ast.Description, consts map[string]uint64, ptrSize uint64, eh
structs: make(map[string]*ast.Struct),
intFlags: make(map[string]*ast.IntFlags),
strFlags: make(map[string]*ast.StrFlags),
- structDescs: make(map[sys.StructKey]*sys.StructDesc),
- structNodes: make(map[*sys.StructDesc]*ast.Struct),
+ structDescs: make(map[prog.StructKey]*prog.StructDesc),
+ structNodes: make(map[*prog.StructDesc]*ast.Struct),
structVarlen: make(map[string]bool),
}
comp.assignSyscallNumbers(consts)
@@ -89,8 +89,8 @@ type compiler struct {
intFlags map[string]*ast.IntFlags
strFlags map[string]*ast.StrFlags
- structDescs map[sys.StructKey]*sys.StructDesc
- structNodes map[*sys.StructDesc]*ast.Struct
+ structDescs map[prog.StructKey]*prog.StructDesc
+ structNodes map[*prog.StructDesc]*ast.Struct
structVarlen map[string]bool
}
@@ -161,8 +161,8 @@ func (comp *compiler) getTypeDesc(t *ast.Type) *typeDesc {
return nil
}
-func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg bool) (
- *typeDesc, []*ast.Type, sys.IntTypeCommon) {
+func (comp *compiler) getArgsBase(t *ast.Type, field string, dir prog.Dir, isArg bool) (
+ *typeDesc, []*ast.Type, prog.IntTypeCommon) {
desc := comp.getTypeDesc(t)
args, opt := removeOpt(t)
size := sizeUnassigned
@@ -173,7 +173,7 @@ func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg
if !isArg {
baseType := args[len(args)-1]
args = args[:len(args)-1]
- base = typeInt.Gen(comp, baseType, nil, base).(*sys.IntType).IntTypeCommon
+ base = typeInt.Gen(comp, baseType, nil, base).(*prog.IntType).IntTypeCommon
}
}
return desc, args, base
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go
index e3b7ffd66..eeeed011c 100644
--- a/pkg/compiler/gen.go
+++ b/pkg/compiler/gen.go
@@ -8,13 +8,13 @@ import (
"sort"
"github.com/google/syzkaller/pkg/ast"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
const sizeUnassigned = ^uint64(0)
-func (comp *compiler) genResources() []*sys.ResourceDesc {
- var resources []*sys.ResourceDesc
+func (comp *compiler) genResources() []*prog.ResourceDesc {
+ var resources []*prog.ResourceDesc
for _, decl := range comp.desc.Nodes {
if n, ok := decl.(*ast.Resource); ok {
resources = append(resources, comp.genResource(n))
@@ -26,8 +26,8 @@ func (comp *compiler) genResources() []*sys.ResourceDesc {
return resources
}
-func (comp *compiler) genResource(n *ast.Resource) *sys.ResourceDesc {
- res := &sys.ResourceDesc{
+func (comp *compiler) genResource(n *ast.Resource) *prog.ResourceDesc {
+ res := &prog.ResourceDesc{
Name: n.Name.Name,
}
var base *ast.Type
@@ -40,12 +40,12 @@ func (comp *compiler) genResource(n *ast.Resource) *sys.ResourceDesc {
if len(res.Values) == 0 {
res.Values = []uint64{0}
}
- res.Type = comp.genType(base, "", sys.DirIn, false)
+ res.Type = comp.genType(base, "", prog.DirIn, false)
return res
}
-func (comp *compiler) genSyscalls() []*sys.Syscall {
- var calls []*sys.Syscall
+func (comp *compiler) genSyscalls() []*prog.Syscall {
+ var calls []*prog.Syscall
for _, decl := range comp.desc.Nodes {
if n, ok := decl.(*ast.Call); ok {
calls = append(calls, comp.genSyscall(n))
@@ -60,32 +60,32 @@ func (comp *compiler) genSyscalls() []*sys.Syscall {
return calls
}
-func (comp *compiler) genSyscall(n *ast.Call) *sys.Syscall {
- var ret sys.Type
+func (comp *compiler) genSyscall(n *ast.Call) *prog.Syscall {
+ var ret prog.Type
if n.Ret != nil {
- ret = comp.genType(n.Ret, "ret", sys.DirOut, true)
+ ret = comp.genType(n.Ret, "ret", prog.DirOut, true)
}
- return &sys.Syscall{
+ return &prog.Syscall{
Name: n.Name.Name,
CallName: n.CallName,
NR: n.NR,
- Args: comp.genFieldArray(n.Args, sys.DirIn, true),
+ Args: comp.genFieldArray(n.Args, prog.DirIn, true),
Ret: ret,
}
}
-func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct {
+func (comp *compiler) genStructDescs(syscalls []*prog.Syscall) []*prog.KeyedStruct {
// Calculate struct/union/array sizes, add padding to structs and detach
// StructDesc's from StructType's. StructType's can be recursive so it's
// not possible to write them out inline as other types. To break the
// recursion detach them, and write StructDesc's out as separate array
- // of KeyedStruct's. sys package will reattach them during init.
+ // of KeyedStruct's. prog package will reattach them during init.
padded := make(map[interface{}]bool)
- detach := make(map[**sys.StructDesc]bool)
- var structs []*sys.KeyedStruct
- var rec func(t sys.Type)
- checkStruct := func(key sys.StructKey, descp **sys.StructDesc) bool {
+ detach := make(map[**prog.StructDesc]bool)
+ var structs []*prog.KeyedStruct
+ var rec func(t prog.Type)
+ checkStruct := func(key prog.StructKey, descp **prog.StructDesc) bool {
detach[descp] = true
desc := *descp
if padded[desc] {
@@ -101,17 +101,17 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
return false
}
}
- structs = append(structs, &sys.KeyedStruct{
+ structs = append(structs, &prog.KeyedStruct{
Key: key,
Desc: desc,
})
return true
}
- rec = func(t0 sys.Type) {
+ rec = func(t0 prog.Type) {
switch t := t0.(type) {
- case *sys.PtrType:
+ case *prog.PtrType:
rec(t.Type)
- case *sys.ArrayType:
+ case *prog.ArrayType:
if padded[t] {
return
}
@@ -123,10 +123,10 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
}
padded[t] = true
t.TypeSize = 0
- if t.Kind == sys.ArrayRangeLen && t.RangeBegin == t.RangeEnd && !t.Type.Varlen() {
+ if t.Kind == prog.ArrayRangeLen && t.RangeBegin == t.RangeEnd && !t.Type.Varlen() {
t.TypeSize = t.RangeBegin * t.Type.Size()
}
- case *sys.StructType:
+ case *prog.StructType:
if !checkStruct(t.Key, &t.StructDesc) {
return
}
@@ -149,7 +149,7 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
}
}
}
- case *sys.UnionType:
+ case *prog.UnionType:
if !checkStruct(t.Key, &t.StructDesc) {
return
}
@@ -182,7 +182,7 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
}
}
- // Detach StructDesc's from StructType's. sys will reattach them again.
+ // Detach StructDesc's from StructType's. prog will reattach them again.
for descp := range detach {
*descp = nil
}
@@ -197,10 +197,10 @@ func (comp *compiler) genStructDescs(syscalls []*sys.Syscall) []*sys.KeyedStruct
return structs
}
-func (comp *compiler) genStructDesc(res *sys.StructDesc, n *ast.Struct, dir sys.Dir) {
+func (comp *compiler) genStructDesc(res *prog.StructDesc, n *ast.Struct, dir prog.Dir) {
// Leave node for genStructDescs to calculate size/padding.
comp.structNodes[res] = n
- *res = sys.StructDesc{
+ *res = prog.StructDesc{
TypeCommon: genCommon(n.Name.Name, "", sizeUnassigned, dir, false),
Fields: comp.genFieldArray(n.Fields, dir, false),
}
@@ -227,7 +227,7 @@ func (comp *compiler) isStructVarlen(name string) bool {
return varlen
}
-func (comp *compiler) markBitfields(fields []sys.Type) {
+func (comp *compiler) markBitfields(fields []prog.Type) {
var bfOffset uint64
for i, f := range fields {
if f.BitfieldLength() == 0 {
@@ -245,25 +245,25 @@ func (comp *compiler) markBitfields(fields []sys.Type) {
}
}
-func setBitfieldOffset(t0 sys.Type, offset uint64, middle bool) {
+func setBitfieldOffset(t0 prog.Type, offset uint64, middle bool) {
switch t := t0.(type) {
- case *sys.IntType:
+ case *prog.IntType:
t.BitfieldOff, t.BitfieldMdl = offset, middle
- case *sys.ConstType:
+ case *prog.ConstType:
t.BitfieldOff, t.BitfieldMdl = offset, middle
- case *sys.LenType:
+ case *prog.LenType:
t.BitfieldOff, t.BitfieldMdl = offset, middle
- case *sys.FlagsType:
+ case *prog.FlagsType:
t.BitfieldOff, t.BitfieldMdl = offset, middle
- case *sys.ProcType:
+ case *prog.ProcType:
t.BitfieldOff, t.BitfieldMdl = offset, middle
default:
panic(fmt.Sprintf("type %#v can't be a bitfield", t))
}
}
-func (comp *compiler) addAlignment(fields []sys.Type, varlen, packed bool, alignAttr uint64) []sys.Type {
- var newFields []sys.Type
+func (comp *compiler) addAlignment(fields []prog.Type, varlen, packed bool, alignAttr uint64) []prog.Type {
+ var newFields []prog.Type
if packed {
// If a struct is packed, statically sized and has explicitly set alignment,
// add a padding at the end.
@@ -312,19 +312,19 @@ func (comp *compiler) addAlignment(fields []sys.Type, varlen, packed bool, align
return newFields
}
-func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
+func (comp *compiler) typeAlign(t0 prog.Type) uint64 {
switch t0.(type) {
- case *sys.IntType, *sys.ConstType, *sys.LenType, *sys.FlagsType, *sys.ProcType,
- *sys.CsumType, *sys.PtrType, *sys.VmaType, *sys.ResourceType:
+ case *prog.IntType, *prog.ConstType, *prog.LenType, *prog.FlagsType, *prog.ProcType,
+ *prog.CsumType, *prog.PtrType, *prog.VmaType, *prog.ResourceType:
return t0.Size()
- case *sys.BufferType:
+ case *prog.BufferType:
return 1
}
switch t := t0.(type) {
- case *sys.ArrayType:
+ case *prog.ArrayType:
return comp.typeAlign(t.Type)
- case *sys.StructType:
+ case *prog.StructType:
packed, alignAttr := comp.parseStructAttrs(comp.structNodes[t.StructDesc])
if alignAttr != 0 {
return alignAttr // overrided by user attribute
@@ -339,7 +339,7 @@ func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
}
}
return align
- case *sys.UnionType:
+ case *prog.UnionType:
align := uint64(0)
for _, f := range t.Fields {
if a := comp.typeAlign(f); align < a {
@@ -352,32 +352,32 @@ func (comp *compiler) typeAlign(t0 sys.Type) uint64 {
}
}
-func genPad(size uint64) sys.Type {
- return &sys.ConstType{
- IntTypeCommon: genIntCommon(genCommon("pad", "", size, sys.DirIn, false), 0, false),
+func genPad(size uint64) prog.Type {
+ return &prog.ConstType{
+ IntTypeCommon: genIntCommon(genCommon("pad", "", size, prog.DirIn, false), 0, false),
IsPad: true,
}
}
-func (comp *compiler) genField(f *ast.Field, dir sys.Dir, isArg bool) sys.Type {
+func (comp *compiler) genField(f *ast.Field, dir prog.Dir, isArg bool) prog.Type {
return comp.genType(f.Type, f.Name.Name, dir, isArg)
}
-func (comp *compiler) genFieldArray(fields []*ast.Field, dir sys.Dir, isArg bool) []sys.Type {
- var res []sys.Type
+func (comp *compiler) genFieldArray(fields []*ast.Field, dir prog.Dir, isArg bool) []prog.Type {
+ var res []prog.Type
for _, f := range fields {
res = append(res, comp.genField(f, dir, isArg))
}
return res
}
-func (comp *compiler) genType(t *ast.Type, field string, dir sys.Dir, isArg bool) sys.Type {
+func (comp *compiler) genType(t *ast.Type, field string, dir prog.Dir, isArg bool) prog.Type {
desc, args, base := comp.getArgsBase(t, field, dir, isArg)
return desc.Gen(comp, t, args, base)
}
-func genCommon(name, field string, size uint64, dir sys.Dir, opt bool) sys.TypeCommon {
- return sys.TypeCommon{
+func genCommon(name, field string, size uint64, dir prog.Dir, opt bool) prog.TypeCommon {
+ return prog.TypeCommon{
TypeName: name,
TypeSize: size,
FldName: field,
@@ -386,8 +386,8 @@ func genCommon(name, field string, size uint64, dir sys.Dir, opt bool) sys.TypeC
}
}
-func genIntCommon(com sys.TypeCommon, bitLen uint64, bigEndian bool) sys.IntTypeCommon {
- return sys.IntTypeCommon{
+func genIntCommon(com prog.TypeCommon, bitLen uint64, bigEndian bool) prog.IntTypeCommon {
+ return prog.IntTypeCommon{
TypeCommon: com,
BigEndian: bigEndian,
BitfieldLen: bitLen,
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index 2a398e3fb..193617574 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -8,7 +8,7 @@ import (
"strconv"
"github.com/google/syzkaller/pkg/ast"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
// typeDesc is arg/field type descriptor.
@@ -23,11 +23,11 @@ type typeDesc struct {
OptArgs int // number of optional arguments in Args array
Args []namedArg // type arguments
// Check does custom verification of the type (optional).
- Check func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon)
+ Check func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon)
// Varlen returns if the type is variable-length (false if not set).
- Varlen func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool
- // Gen generates corresponding sys.Type.
- Gen func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type
+ Varlen func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool
+ // Gen generates corresponding prog.Type.
+ Gen func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type
}
// typeArg describes a type argument.
@@ -58,17 +58,17 @@ var typeInt = &typeDesc{
ResourceBase: true,
OptArgs: 1,
Args: []namedArg{{"range", typeArgRange}},
- Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
+ Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
typeArgBase.Type.Check(comp, t)
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
size, be := comp.parseIntType(t.Ident)
- kind, rangeBegin, rangeEnd := sys.IntPlain, uint64(0), uint64(0)
+ kind, rangeBegin, rangeEnd := prog.IntPlain, uint64(0), uint64(0)
if len(args) > 0 {
- kind, rangeBegin, rangeEnd = sys.IntRange, args[0].Value, args[0].Value2
+ kind, rangeBegin, rangeEnd = prog.IntRange, args[0].Value, args[0].Value2
}
base.TypeSize = size
- return &sys.IntType{
+ return &prog.IntType{
IntTypeCommon: genIntCommon(base.TypeCommon, t.Value2, be),
Kind: kind,
RangeBegin: rangeBegin,
@@ -81,13 +81,13 @@ var typePtr = &typeDesc{
Names: []string{"ptr", "ptr64"},
CanBeArg: true,
Args: []namedArg{{"direction", typeArgDir}, {"type", typeArgType}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
- base.ArgDir = sys.DirIn // pointers are always in
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
+ base.ArgDir = prog.DirIn // pointers are always in
base.TypeSize = comp.ptrSize
if t.Ident == "ptr64" {
base.TypeSize = 8
}
- return &sys.PtrType{
+ return &prog.PtrType{
TypeCommon: base.TypeCommon,
Type: comp.genType(args[1], "", genDir(args[0]), false),
}
@@ -99,13 +99,13 @@ var typeArray = &typeDesc{
CantBeOpt: true,
OptArgs: 1,
Args: []namedArg{{"type", typeArgType}, {"size", typeArgRange}},
- Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
+ Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 1 && args[1].Value == 0 && args[1].Value2 == 0 {
// This is the only case that can yield 0 static type size.
comp.error(args[1].Pos, "arrays of size 0 are not supported")
}
},
- Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
+ Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
if comp.isVarlen(args[0]) {
return true
}
@@ -114,23 +114,23 @@ var typeArray = &typeDesc{
}
return true
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
elemType := comp.genType(args[0], "", base.ArgDir, false)
- kind, begin, end := sys.ArrayRandLen, uint64(0), uint64(0)
+ kind, begin, end := prog.ArrayRandLen, uint64(0), uint64(0)
if len(args) > 1 {
- kind, begin, end = sys.ArrayRangeLen, args[1].Value, args[1].Value2
+ kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value2
}
- if it, ok := elemType.(*sys.IntType); ok && it.Kind == sys.IntPlain && it.TypeSize == 1 {
+ if it, ok := elemType.(*prog.IntType); ok && it.Kind == prog.IntPlain && it.TypeSize == 1 {
// Special case: buffer is better mutated.
- bufKind := sys.BufferBlobRand
+ bufKind := prog.BufferBlobRand
base.TypeSize = 0
- if kind == sys.ArrayRangeLen {
- bufKind = sys.BufferBlobRange
+ if kind == prog.ArrayRangeLen {
+ bufKind = prog.BufferBlobRange
if begin == end {
base.TypeSize = begin * elemType.Size()
}
}
- return &sys.BufferType{
+ return &prog.BufferType{
TypeCommon: base.TypeCommon,
Kind: bufKind,
RangeBegin: begin,
@@ -138,7 +138,7 @@ var typeArray = &typeDesc{
}
}
// TypeSize is assigned later in genStructDescs.
- return &sys.ArrayType{
+ return &prog.ArrayType{
TypeCommon: base.TypeCommon,
Type: elemType,
Kind: kind,
@@ -155,7 +155,7 @@ var typeLen = &typeDesc{
CantBeRet: true,
NeedBase: true,
Args: []namedArg{{"len target", typeArgLenTarget}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var byteSize uint64
switch t.Ident {
case "bytesize":
@@ -163,7 +163,7 @@ var typeLen = &typeDesc{
case "bytesize2", "bytesize4", "bytesize8":
byteSize, _ = strconv.ParseUint(t.Ident[8:], 10, 8)
}
- return &sys.LenType{
+ return &prog.LenType{
IntTypeCommon: base,
Buf: args[0].Ident,
ByteSize: byteSize,
@@ -177,8 +177,8 @@ var typeConst = &typeDesc{
CantBeOpt: true,
NeedBase: true,
Args: []namedArg{{"value", typeArgInt}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
- return &sys.ConstType{
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
+ return &prog.ConstType{
IntTypeCommon: base,
Val: args[0].Value,
}
@@ -195,18 +195,18 @@ var typeFlags = &typeDesc{
CantBeOpt: true,
NeedBase: true,
Args: []namedArg{{"flags", typeArgFlags}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
name := args[0].Ident
base.TypeName = name
f := comp.intFlags[name]
if len(f.Values) == 0 {
// We can get this if all values are unsupported consts.
- return &sys.IntType{
+ return &prog.IntType{
IntTypeCommon: base,
- Kind: sys.IntPlain,
+ Kind: prog.IntPlain,
}
}
- return &sys.FlagsType{
+ return &prog.FlagsType{
IntTypeCommon: base,
Vals: genIntArray(f.Values),
}
@@ -226,14 +226,14 @@ var typeArgFlags = &typeArg{
var typeFilename = &typeDesc{
Names: []string{"filename"},
CantBeOpt: true,
- Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
+ Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
return true
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0
- return &sys.BufferType{
+ return &prog.BufferType{
TypeCommon: base.TypeCommon,
- Kind: sys.BufferFilename,
+ Kind: prog.BufferFilename,
}
},
}
@@ -243,10 +243,10 @@ var typeFileoff = &typeDesc{
CanBeArg: true,
CantBeOpt: true,
NeedBase: true,
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
- return &sys.IntType{
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
+ return &prog.IntType{
IntTypeCommon: base,
- Kind: sys.IntFileoff,
+ Kind: prog.IntFileoff,
}
},
}
@@ -256,13 +256,13 @@ var typeVMA = &typeDesc{
CanBeArg: true,
OptArgs: 1,
Args: []namedArg{{"size range", typeArgRange}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
begin, end := uint64(0), uint64(0)
if len(args) > 0 {
begin, end = args[0].Value, args[0].Value2
}
base.TypeSize = comp.ptrSize
- return &sys.VmaType{
+ return &prog.VmaType{
TypeCommon: base.TypeCommon,
RangeBegin: begin,
RangeEnd: end,
@@ -277,11 +277,11 @@ var typeSignalno = &typeDesc{
Names: []string{"signalno"},
CanBeArg: true,
CantBeOpt: true,
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 4
- return &sys.IntType{
+ return &prog.IntType{
IntTypeCommon: base,
- Kind: sys.IntRange,
+ Kind: prog.IntRange,
RangeBegin: 0,
RangeEnd: 65,
}
@@ -295,17 +295,17 @@ var typeCsum = &typeDesc{
CantBeRet: true,
OptArgs: 1,
Args: []namedArg{{"csum target", typeArgLenTarget}, {"kind", typeArgCsumType}, {"proto", typeArgInt}},
- Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
- if len(args) > 2 && genCsumKind(args[1]) != sys.CsumPseudo {
+ Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
+ if len(args) > 2 && genCsumKind(args[1]) != prog.CsumPseudo {
comp.error(args[2].Pos, "only pseudo csum can have proto")
}
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
var proto uint64
if len(args) > 2 {
proto = args[2].Value
}
- return &sys.CsumType{
+ return &prog.CsumType{
IntTypeCommon: base,
Buf: args[0].Ident,
Kind: genCsumKind(args[1]),
@@ -319,12 +319,12 @@ var typeArgCsumType = &typeArg{
Names: []string{"inet", "pseudo"},
}
-func genCsumKind(t *ast.Type) sys.CsumKind {
+func genCsumKind(t *ast.Type) prog.CsumKind {
switch t.Ident {
case "inet":
- return sys.CsumInet
+ return prog.CsumInet
case "pseudo":
- return sys.CsumPseudo
+ return prog.CsumPseudo
default:
panic(fmt.Sprintf("unknown csum kind %q", t.Ident))
}
@@ -336,7 +336,7 @@ var typeProc = &typeDesc{
CantBeOpt: true,
NeedBase: true,
Args: []namedArg{{"range start", typeArgInt}, {"per-proc values", typeArgInt}},
- Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
+ Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
start := args[0].Value
perProc := args[1].Value
if perProc == 0 {
@@ -354,8 +354,8 @@ var typeProc = &typeDesc{
}
}
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
- return &sys.ProcType{
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
+ return &prog.ProcType{
IntTypeCommon: base,
ValuesStart: args[0].Value,
ValuesPerProc: args[1].Value,
@@ -367,14 +367,14 @@ var typeText = &typeDesc{
Names: []string{"text"},
CantBeOpt: true,
Args: []namedArg{{"kind", typeArgTextType}},
- Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
+ Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
return true
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = 0
- return &sys.BufferType{
+ return &prog.BufferType{
TypeCommon: base.TypeCommon,
- Kind: sys.BufferText,
+ Kind: prog.BufferText,
Text: genTextType(args[0]),
}
},
@@ -385,18 +385,18 @@ var typeArgTextType = &typeArg{
Names: []string{"x86_real", "x86_16", "x86_32", "x86_64", "arm64"},
}
-func genTextType(t *ast.Type) sys.TextKind {
+func genTextType(t *ast.Type) prog.TextKind {
switch t.Ident {
case "x86_real":
- return sys.Text_x86_real
+ return prog.Text_x86_real
case "x86_16":
- return sys.Text_x86_16
+ return prog.Text_x86_16
case "x86_32":
- return sys.Text_x86_32
+ return prog.Text_x86_32
case "x86_64":
- return sys.Text_x86_64
+ return prog.Text_x86_64
case "arm64":
- return sys.Text_arm64
+ return prog.Text_arm64
default:
panic(fmt.Sprintf("unknown text type %q", t.Ident))
}
@@ -406,14 +406,14 @@ var typeBuffer = &typeDesc{
Names: []string{"buffer"},
CanBeArg: true,
Args: []namedArg{{"direction", typeArgDir}},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
base.TypeSize = comp.ptrSize
- return &sys.PtrType{
+ return &prog.PtrType{
TypeCommon: base.TypeCommon,
- Type: &sys.BufferType{
+ Type: &prog.BufferType{
// BufferBlobRand is always varlen.
TypeCommon: genCommon("", "", 0, genDir(args[0]), false),
- Kind: sys.BufferBlobRand,
+ Kind: prog.BufferBlobRand,
},
}
},
@@ -423,7 +423,7 @@ var typeString = &typeDesc{
Names: []string{"string"},
OptArgs: 2,
Args: []namedArg{{"literal or flags", typeArgStringFlags}, {"size", typeArgInt}},
- Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) {
+ Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 1 {
size := args[1].Value
vals := []string{args[0].String}
@@ -439,10 +439,10 @@ var typeString = &typeDesc{
}
}
},
- Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
+ Varlen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
return comp.stringSize(args) == 0
},
- Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
subkind := ""
var vals []string
if len(args) > 0 {
@@ -465,9 +465,9 @@ var typeString = &typeDesc{
vals[i] = s
}
base.TypeSize = comp.stringSize(args)
- return &sys.BufferType{
+ return &prog.BufferType{
TypeCommon: base.TypeCommon,
- Kind: sys.BufferString,
+ Kind: prog.BufferString,
SubKind: subkind,
Values: vals,
}
@@ -527,15 +527,15 @@ var typeResource = &typeDesc{
}
func init() {
- typeResource.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ typeResource.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
// Find and generate base type to get its size.
var baseType *ast.Type
for r := comp.resources[t.Ident]; r != nil; {
baseType = r.Base
r = comp.resources[r.Base.Ident]
}
- base.TypeSize = comp.genType(baseType, "", sys.DirIn, false).Size()
- return &sys.ResourceType{
+ base.TypeSize = comp.genType(baseType, "", prog.DirIn, false).Size()
+ return &prog.ResourceType{
TypeCommon: base.TypeCommon,
}
}
@@ -548,27 +548,27 @@ var typeStruct = &typeDesc{
}
func init() {
- typeStruct.Varlen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) bool {
+ typeStruct.Varlen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) bool {
return comp.isStructVarlen(t.Ident)
}
- typeStruct.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base sys.IntTypeCommon) sys.Type {
+ typeStruct.Gen = func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
s := comp.structs[t.Ident]
- key := sys.StructKey{t.Ident, base.ArgDir}
+ key := prog.StructKey{t.Ident, base.ArgDir}
desc := comp.structDescs[key]
if desc == nil {
// Need to assign to structDescs before calling genStructDesc to break recursion.
- desc = new(sys.StructDesc)
+ desc = new(prog.StructDesc)
comp.structDescs[key] = desc
comp.genStructDesc(desc, s, base.ArgDir)
}
if s.IsUnion {
- return &sys.UnionType{
+ return &prog.UnionType{
Key: key,
FldName: base.FldName,
StructDesc: desc,
}
} else {
- return &sys.StructType{
+ return &prog.StructType{
Key: key,
FldName: base.FldName,
StructDesc: desc,
@@ -582,14 +582,14 @@ var typeArgDir = &typeArg{
Names: []string{"in", "out", "inout"},
}
-func genDir(t *ast.Type) sys.Dir {
+func genDir(t *ast.Type) prog.Dir {
switch t.Ident {
case "in":
- return sys.DirIn
+ return prog.DirIn
case "out":
- return sys.DirOut
+ return prog.DirOut
case "inout":
- return sys.DirInOut
+ return prog.DirInOut
default:
panic(fmt.Sprintf("unknown direction %q", t.Ident))
}
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index b46fda351..e1b32e752 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -20,7 +20,7 @@ import (
"unsafe"
"github.com/google/syzkaller/prog"
- "github.com/google/syzkaller/sys"
+ _ "github.com/google/syzkaller/sys"
)
type Options struct {
@@ -367,7 +367,7 @@ loop:
fmt.Fprintf(w, "\twrite_file(\"/sys/kernel/debug/fail_futex/ignore-private\", \"N\");\n")
fmt.Fprintf(w, "\tinject_fault(%v);\n", opts.FaultNth)
}
- meta := sys.Syscalls[instr]
+ meta := prog.Syscalls[instr]
emitCall := true
if meta.CallName == "syz_test" {
emitCall = false
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index e4e9e1f7f..fbe984b3c 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -13,6 +13,7 @@ import (
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func initTest(t *testing.T) (rand.Source, int) {
diff --git a/pkg/host/host.go b/pkg/host/host.go
index 9aafbce6e..0fa66dfa4 100644
--- a/pkg/host/host.go
+++ b/pkg/host/host.go
@@ -12,13 +12,13 @@ import (
"syscall"
"github.com/google/syzkaller/pkg/osutil"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
// DetectSupportedSyscalls returns list on supported syscalls on host.
-func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
+func DetectSupportedSyscalls() (map[*prog.Syscall]bool, error) {
// There are 3 possible strategies:
- // 1. Executes all syscalls with presumably invalid arguments and check for ENOSYS.
+ // 1. Executes all syscalls with presumably invalid arguments and check for ENOprog.
// But not all syscalls are safe to execute. For example, pause will hang,
// while setpgrp will push the process into own process group.
// 2. Check presence of /sys/kernel/debug/tracing/events/syscalls/sys_enter_* files.
@@ -28,8 +28,8 @@ func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
// Requires CONFIG_KALLSYMS. Seems to be the most reliable. That's what we use here.
kallsyms, _ := ioutil.ReadFile("/proc/kallsyms")
- supported := make(map[*sys.Syscall]bool)
- for _, c := range sys.Syscalls {
+ supported := make(map[*prog.Syscall]bool)
+ for _, c := range prog.Syscalls {
if isSupported(kallsyms, c) {
supported[c] = true
}
@@ -37,7 +37,7 @@ func DetectSupportedSyscalls() (map[*sys.Syscall]bool, error) {
return supported, nil
}
-func isSupported(kallsyms []byte, c *sys.Syscall) bool {
+func isSupported(kallsyms []byte, c *prog.Syscall) bool {
if c.NR == ^uint64(0) {
return false // don't even have a syscall number
}
@@ -59,12 +59,12 @@ func isSupported(kallsyms []byte, c *sys.Syscall) bool {
return bytes.Index(kallsyms, []byte(" T sys_"+c.CallName+"\n")) != -1
}
-func isSupportedSyzkall(c *sys.Syscall) bool {
+func isSupportedSyzkall(c *prog.Syscall) bool {
switch c.CallName {
case "syz_test":
return false
case "syz_open_dev":
- if _, ok := c.Args[0].(*sys.ConstType); ok {
+ if _, ok := c.Args[0].(*prog.ConstType); ok {
// This is for syz_open_dev$char/block.
// They are currently commented out, but in case one enables them.
return true
@@ -112,8 +112,8 @@ func isSupportedSyzkall(c *sys.Syscall) bool {
panic("unknown syzkall: " + c.Name)
}
-func isSupportedSocket(c *sys.Syscall) bool {
- af, ok := c.Args[0].(*sys.ConstType)
+func isSupportedSocket(c *prog.Syscall) bool {
+ af, ok := c.Args[0].(*prog.ConstType)
if !ok {
println(c.Name)
panic("socket family is not const")
@@ -125,7 +125,7 @@ func isSupportedSocket(c *sys.Syscall) bool {
return err != syscall.ENOSYS && err != syscall.EAFNOSUPPORT
}
-func isSupportedOpen(c *sys.Syscall) bool {
+func isSupportedOpen(c *prog.Syscall) bool {
fname, ok := extractStringConst(c.Args[0])
if !ok {
return true
@@ -137,7 +137,7 @@ func isSupportedOpen(c *sys.Syscall) bool {
return err == nil
}
-func isSupportedOpenAt(c *sys.Syscall) bool {
+func isSupportedOpenAt(c *prog.Syscall) bool {
fname, ok := extractStringConst(c.Args[1])
if !ok {
return true
@@ -149,13 +149,13 @@ func isSupportedOpenAt(c *sys.Syscall) bool {
return err == nil
}
-func extractStringConst(typ sys.Type) (string, bool) {
- ptr, ok := typ.(*sys.PtrType)
+func extractStringConst(typ prog.Type) (string, bool) {
+ ptr, ok := typ.(*prog.PtrType)
if !ok {
panic("first open arg is not a pointer to string const")
}
- str, ok := ptr.Type.(*sys.BufferType)
- if !ok || str.Kind != sys.BufferString || len(str.Values) != 1 {
+ str, ok := ptr.Type.(*prog.BufferType)
+ if !ok || str.Kind != prog.BufferString || len(str.Values) != 1 {
return "", false
}
v := str.Values[0]
diff --git a/pkg/host/host_test.go b/pkg/host/host_test.go
index 1eea00fe6..dc9225d5a 100644
--- a/pkg/host/host_test.go
+++ b/pkg/host/host_test.go
@@ -7,7 +7,8 @@ import (
"syscall"
"testing"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func TestLog(t *testing.T) {
@@ -18,7 +19,7 @@ func TestLog(t *testing.T) {
t.Skipf("skipping: %v", err)
}
t.Logf("unsupported:")
- for _, c := range sys.Syscalls {
+ for _, c := range prog.Syscalls {
s, ok := supp[c]
if ok && !s {
t.Fatalf("map contains false value")
@@ -27,9 +28,9 @@ func TestLog(t *testing.T) {
t.Logf("\t%v", c.Name)
}
}
- trans := sys.TransitivelyEnabledCalls(supp)
+ trans := prog.TransitivelyEnabledCalls(supp)
t.Logf("transitively unsupported:")
- for _, c := range sys.Syscalls {
+ for _, c := range prog.Syscalls {
s, ok := trans[c]
if ok && !s {
t.Fatalf("map contains false value")
@@ -58,7 +59,7 @@ func TestSupportedSyscalls(t *testing.T) {
"stat",
}
for _, name := range safe {
- c := sys.SyscallMap[name]
+ c := prog.SyscallMap[name]
if c == nil {
t.Fatalf("can't find syscall '%v'", name)
}
diff --git a/pkg/ipc/ipc_test.go b/pkg/ipc/ipc_test.go
index 68fbb94cd..b6bfca81d 100644
--- a/pkg/ipc/ipc_test.go
+++ b/pkg/ipc/ipc_test.go
@@ -13,6 +13,7 @@ import (
"github.com/google/syzkaller/pkg/csource"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
const timeout = 10 * time.Second
diff --git a/prog/analysis.go b/prog/analysis.go
index 05837131a..009a15a21 100644
--- a/prog/analysis.go
+++ b/prog/analysis.go
@@ -10,8 +10,6 @@ package prog
import (
"fmt"
-
- . "github.com/google/syzkaller/sys"
)
const (
@@ -68,46 +66,18 @@ func (s *state) analyze(c *Call) {
}
}
})
- switch c.Meta.Name {
- case "mmap":
- // Filter out only very wrong arguments.
- length := c.Args[1].(*ConstArg)
- if length.Val == 0 {
- break
+ start, npages, mapped := analyzeMmap(c)
+ if npages != 0 {
+ if start+npages > uint64(len(s.pages)) {
+ panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v",
+ start, npages, len(s.pages)))
}
- flags := c.Args[3].(*ConstArg)
- fd := c.Args[4].(*ResultArg)
- if flags.Val&MAP_ANONYMOUS == 0 && fd.Val == InvalidFD {
- break
- }
- s.addressable(c.Args[0].(*PointerArg), length, true)
- case "munmap":
- s.addressable(c.Args[0].(*PointerArg), c.Args[1].(*ConstArg), false)
- case "mremap":
- s.addressable(c.Args[4].(*PointerArg), c.Args[2].(*ConstArg), true)
- case "io_submit":
- if arr := c.Args[2].(*PointerArg).Res; arr != nil {
- for _, ptr := range arr.(*GroupArg).Inner {
- p := ptr.(*PointerArg)
- if p.Res != nil && p.Res.Type().Name() == "iocb" {
- s.resources["iocbptr"] = append(s.resources["iocbptr"], ptr)
- }
- }
+ for i := uint64(0); i < npages; i++ {
+ s.pages[start+i] = mapped
}
}
}
-func (s *state) addressable(addr *PointerArg, size *ConstArg, ok bool) {
- sizePages := size.Val / pageSize
- if addr.PageIndex+sizePages > uint64(len(s.pages)) {
- panic(fmt.Sprintf("address is out of bounds: page=%v len=%v bound=%v\naddr: %+v\nsize: %+v",
- addr.PageIndex, sizePages, len(s.pages), addr, size))
- }
- for i := uint64(0); i < sizePages; i++ {
- s.pages[addr.PageIndex+i] = ok
- }
-}
-
func foreachSubargImpl(arg Arg, parent *[]Arg, f func(arg, base Arg, parent *[]Arg)) {
var rec func(arg, base Arg, parent *[]Arg)
rec = func(arg, base Arg, parent *[]Arg) {
@@ -181,86 +151,6 @@ func foreachSubargOffset(arg Arg, f func(arg Arg, offset uint64)) {
rec(arg, 0)
}
-func sanitizeCall(c *Call) {
- switch c.Meta.CallName {
- case "mmap":
- // Add MAP_FIXED flag, otherwise it produces non-deterministic results.
- _, ok := c.Args[0].(*PointerArg)
- if !ok {
- panic("mmap address is not ArgPointer")
- }
- _, ok = c.Args[1].(*ConstArg)
- if !ok {
- panic("mmap length is not ArgPageSize")
- }
- flags, ok := c.Args[3].(*ConstArg)
- if !ok {
- panic("mmap flag arg is not const")
- }
- flags.Val |= MAP_FIXED
- case "mremap":
- // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
- flags, ok := c.Args[3].(*ConstArg)
- if !ok {
- panic("mremap flag arg is not const")
- }
- if flags.Val&MREMAP_MAYMOVE != 0 {
- flags.Val |= MREMAP_FIXED
- }
- case "mknod", "mknodat":
- mode, ok1 := c.Args[1].(*ConstArg)
- dev, ok2 := c.Args[2].(*ConstArg)
- if c.Meta.CallName == "mknodat" {
- mode, ok1 = c.Args[2].(*ConstArg)
- dev, ok2 = c.Args[3].(*ConstArg)
- }
- if !ok1 || !ok2 {
- panic("mknod mode is not const")
- }
- // Char and block devices read/write io ports, kernel memory and do other nasty things.
- // TODO: not required if executor drops privileges.
- switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) {
- case S_IFREG, S_IFIFO, S_IFSOCK:
- case S_IFBLK:
- if dev.Val>>8 == 7 {
- break // loop
- }
- mode.Val &^= S_IFBLK
- mode.Val |= S_IFREG
- case S_IFCHR:
- mode.Val &^= S_IFCHR
- mode.Val |= S_IFREG
- }
- case "syslog":
- cmd := c.Args[0].(*ConstArg)
- // These disable console output, but we need it.
- if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON {
- cmd.Val = SYSLOG_ACTION_SIZE_UNREAD
- }
- case "ioctl":
- cmd := c.Args[1].(*ConstArg)
- // Freeze kills machine. Though, it is an interesting functions,
- // so we need to test it somehow.
- // TODO: not required if executor drops privileges.
- if uint32(cmd.Val) == FIFREEZE {
- cmd.Val = FITHAW
- }
- case "ptrace":
- req := c.Args[0].(*ConstArg)
- // PTRACE_TRACEME leads to unkillable processes, see:
- // https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
- if req.Val == PTRACE_TRACEME {
- req.Val = ^uint64(0)
- }
- case "exit", "exit_group":
- code := c.Args[0].(*ConstArg)
- // These codes are reserved by executor.
- if code.Val%128 == 67 || code.Val%128 == 68 {
- code.Val = 1
- }
- }
-}
-
func RequiresBitmasks(p *Prog) bool {
result := false
for _, c := range p.Calls {
diff --git a/prog/checksum.go b/prog/checksum.go
index 0c8f7210d..b5226e715 100644
--- a/prog/checksum.go
+++ b/prog/checksum.go
@@ -5,8 +5,6 @@ package prog
import (
"fmt"
-
- . "github.com/google/syzkaller/sys"
)
type CsumChunkKind int
diff --git a/prog/checksum_test.go b/prog/checksum_test.go
index 205450255..004769328 100644
--- a/prog/checksum_test.go
+++ b/prog/checksum_test.go
@@ -1,23 +1,26 @@
// Copyright 2016 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 prog
+package prog_test
import (
"testing"
+
+ . "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func TestChecksumCalcRandom(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
for _, call := range p.Calls {
- calcChecksumsCall(call, i%32)
+ CalcChecksumsCall(call, i%32)
}
for try := 0; try <= 10; try++ {
p.Mutate(rs, 10, nil, nil)
for _, call := range p.Calls {
- calcChecksumsCall(call, i%32)
+ CalcChecksumsCall(call, i%32)
}
}
}
diff --git a/sys/decl_test.go b/prog/decl_test.go
index a156f4f61..e716cdf5e 100644
--- a/sys/decl_test.go
+++ b/prog/decl_test.go
@@ -1,7 +1,7 @@
// Copyright 2015 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 sys
+package prog
import (
"testing"
@@ -10,7 +10,7 @@ import (
func TestResourceCtors(t *testing.T) {
for _, c := range Syscalls {
for _, res := range c.InputResources() {
- if len(resourceCtors(res.Desc.Kind, true)) == 0 {
+ if len(calcResourceCtors(res.Desc.Kind, true)) == 0 {
t.Errorf("call %v requires input resource %v, but there are no calls that can create this resource", c.Name, res.Desc.Name)
}
}
diff --git a/prog/encoding.go b/prog/encoding.go
index 2081b1abb..a6ded73ca 100644
--- a/prog/encoding.go
+++ b/prog/encoding.go
@@ -10,8 +10,6 @@ import (
"fmt"
"io"
"strconv"
-
- . "github.com/google/syzkaller/sys"
)
// String generates a very compact program description (mostly for debug output).
@@ -146,7 +144,7 @@ func Deserialize(data []byte) (prog *Prog, err error) {
}
c := &Call{
Meta: meta,
- Ret: returnArg(meta.Ret),
+ Ret: MakeReturnArg(meta.Ret),
}
prog.Calls = append(prog.Calls, c)
p.Parse('(')
@@ -213,13 +211,13 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
}
switch typ.(type) {
case *ConstType, *IntType, *FlagsType, *ProcType, *LenType, *CsumType:
- arg = constArg(typ, v)
+ arg = MakeConstArg(typ, v)
case *ResourceType:
- arg = resultArg(typ, nil, v)
+ arg = MakeResultArg(typ, nil, v)
case *PtrType:
- arg = pointerArg(typ, 0, 0, 0, nil)
+ arg = MakePointerArg(typ, 0, 0, 0, nil)
case *VmaType:
- arg = pointerArg(typ, 0, 0, 0, nil)
+ arg = MakePointerArg(typ, 0, 0, 0, nil)
default:
return nil, fmt.Errorf("bad const type %+v", typ)
}
@@ -229,7 +227,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
if !ok || v == nil {
return nil, fmt.Errorf("result %v references unknown variable (vars=%+v)", id, vars)
}
- arg = resultArg(typ, v, 0)
+ arg = MakeResultArg(typ, v, 0)
if p.Char() == '/' {
p.Parse('/')
op := p.Ident()
@@ -267,7 +265,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
if err != nil {
return nil, err
}
- arg = pointerArg(typ, page, off, size, inner)
+ arg = MakePointerArg(typ, page, off, size, inner)
case '(':
// This used to parse length of VmaType and return ArgPageSize, which is now removed.
// Leaving this for now for backwards compatibility.
@@ -275,7 +273,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
if err != nil {
return nil, err
}
- arg = constArg(typ, pages*pageSize)
+ arg = MakeConstArg(typ, pages*pageSize)
case '"':
p.Parse('"')
val := ""
@@ -301,7 +299,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
}
fld := t1.Fields[i]
if IsPad(fld) {
- inner = append(inner, constArg(fld, 0))
+ inner = append(inner, MakeConstArg(fld, 0))
} else {
arg, err := parseArg(fld, p, vars)
if err != nil {
@@ -317,7 +315,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
for len(inner) < len(t1.Fields) {
inner = append(inner, defaultArg(t1.Fields[len(inner)]))
}
- arg = groupArg(typ, inner)
+ arg = MakeGroupArg(typ, inner)
case '[':
t1, ok := typ.(*ArrayType)
if !ok {
@@ -336,7 +334,7 @@ func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
}
}
p.Parse(']')
- arg = groupArg(typ, inner)
+ arg = MakeGroupArg(typ, inner)
case '@':
t1, ok := typ.(*UnionType)
if !ok {
diff --git a/prog/encoding_test.go b/prog/encoding_test.go
index f4036b458..c58fe7dc8 100644
--- a/prog/encoding_test.go
+++ b/prog/encoding_test.go
@@ -1,7 +1,7 @@
// Copyright 2016 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 prog
+package prog_test
import (
"fmt"
@@ -9,6 +9,9 @@ import (
"regexp"
"sort"
"testing"
+
+ . "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func setToArray(s map[string]struct{}) []string {
@@ -76,7 +79,7 @@ func TestCallSet(t *testing.T) {
}
func TestCallSetRandom(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
calls0 := make(map[string]struct{})
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index d50e4f3be..a4f41a694 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -9,8 +9,6 @@ package prog
import (
"fmt"
"sort"
-
- . "github.com/google/syzkaller/sys"
)
const (
@@ -37,9 +35,6 @@ const (
const (
ExecBufferSize = 2 << 20
-
- pageSize = 4 << 10
- dataOffset = 512 << 20
)
type Args []Arg
diff --git a/prog/encodingexec_test.go b/prog/encodingexec_test.go
index 37bfe04c0..9a2dd1d1e 100644
--- a/prog/encodingexec_test.go
+++ b/prog/encodingexec_test.go
@@ -1,7 +1,7 @@
// Copyright 2016 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 prog
+package prog_test
import (
"bytes"
@@ -9,13 +9,12 @@ import (
"fmt"
"testing"
- . "github.com/google/syzkaller/sys"
+ . "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
-const ptrSize = 8
-
func TestSerializeForExecRandom(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
buf := make([]byte, ExecBufferSize)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
@@ -46,6 +45,10 @@ func TestSerializeForExec(t *testing.T) {
argResult = uint64(ExecArgResult)
argData = uint64(ExecArgData)
)
+ var (
+ dataOffset = DataOffset()
+ ptrSize = PtrSize()
+ )
callID := func(name string) uint64 {
c := SyscallMap[name]
if c == nil {
diff --git a/prog/export_test.go b/prog/export_test.go
new file mode 100644
index 000000000..c5337d695
--- /dev/null
+++ b/prog/export_test.go
@@ -0,0 +1,47 @@
+// Copyright 2017 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 prog
+
+import (
+ "math/rand"
+ "testing"
+ "time"
+)
+
+// Export guts for testing.
+
+func init() {
+ debug = true
+}
+
+var (
+ CalcChecksumsCall = calcChecksumsCall
+ AssignSizesCall = assignSizesCall
+ DefaultArg = defaultArg
+ InitTest = initTest
+)
+
+func PtrSize() uint64 {
+ return ptrSize
+}
+
+func DataOffset() uint64 {
+ return dataOffset
+}
+
+func PageSize() uint64 {
+ return pageSize
+}
+
+func initTest(t *testing.T) (rand.Source, int) {
+ t.Parallel()
+ iters := 10000
+ if testing.Short() {
+ iters = 100
+ }
+ seed := int64(time.Now().UnixNano())
+ rs := rand.NewSource(seed)
+ t.Logf("seed=%v", seed)
+ return rs, iters
+}
diff --git a/prog/hints.go b/prog/hints.go
index ba8131081..e268d46a6 100644
--- a/prog/hints.go
+++ b/prog/hints.go
@@ -20,8 +20,6 @@ package prog
import (
"encoding/binary"
-
- . "github.com/google/syzkaller/sys"
)
type uint64Set map[uint64]bool
@@ -95,7 +93,7 @@ func generateHints(p *Prog, compMap CompMap, c *Call, arg Arg, exec func(p *Prog
switch a := arg.(type) {
case *ConstArg:
- originalArg = constArg(a.Type(), a.Val)
+ originalArg = MakeConstArg(a.Type(), a.Val)
checkConstArg(a, compMap, constArgCandidate)
case *DataArg:
originalArg = dataArg(a.Type(), a.Data)
@@ -105,7 +103,7 @@ func generateHints(p *Prog, compMap CompMap, c *Call, arg Arg, exec func(p *Prog
func checkConstArg(arg *ConstArg, compMap CompMap, cb func(newArg Arg)) {
for replacer := range shrinkExpand(arg.Val, compMap) {
- cb(constArg(arg.typ, replacer))
+ cb(MakeConstArg(arg.typ, replacer))
}
}
diff --git a/prog/hints_test.go b/prog/hints_test.go
index 5409925bf..3f0a10726 100644
--- a/prog/hints_test.go
+++ b/prog/hints_test.go
@@ -7,8 +7,6 @@ import (
"fmt"
"reflect"
"testing"
-
- . "github.com/google/syzkaller/sys"
)
type ConstArgTest struct {
diff --git a/prog/mutation.go b/prog/mutation.go
index a45a02fe1..e793e28e4 100644
--- a/prog/mutation.go
+++ b/prog/mutation.go
@@ -7,8 +7,6 @@ import (
"fmt"
"math/rand"
"unsafe"
-
- . "github.com/google/syzkaller/sys"
)
func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Prog) {
@@ -178,11 +176,11 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
arg1, calls1 := r.addr(s, t, size, a.Res)
p.replaceArg(c, arg, arg1, calls1)
case *StructType:
- ctor := isSpecialStruct(t)
- if ctor == nil {
+ gen := specialStructs[t.Name()]
+ if gen == nil {
panic("bad arg returned by mutationArgs: StructType")
}
- arg1, calls1 := ctor(r, s)
+ arg1, calls1 := gen(&Gen{r, s}, t, arg.(*GroupArg))
for i, f := range arg1.(*GroupArg).Inner {
p.replaceArg(c, arg.(*GroupArg).Inner[i], f, calls1)
calls1 = nil
@@ -255,7 +253,16 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
// predicate pred. It iteratively generates simpler programs and asks pred
// whether it is equal to the orginal program or not. If it is equivalent then
// the simplification attempt is committed and the process continues.
-func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool) (*Prog, int) {
+func Minimize(p0 *Prog, callIndex0 int, pred0 func(*Prog, int) bool, crash bool) (*Prog, int) {
+ pred := pred0
+ if debug {
+ pred = func(p *Prog, callIndex int) bool {
+ if err := p.validate(); err != nil {
+ panic(err)
+ }
+ return pred0(p, callIndex)
+ }
+ }
name0 := ""
if callIndex0 != -1 {
if callIndex0 < 0 || callIndex0 >= len(p0.Calls) {
@@ -291,7 +298,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
}
}
// Prepend uber-mmap.
- mmap := createMmapCall(uint64(lo), uint64(hi-lo)+1)
+ mmap := makeMmap(uint64(lo), uint64(hi-lo)+1)
p.Calls = append([]*Call{mmap}, p.Calls...)
if callIndex != -1 {
callIndex++
@@ -496,7 +503,7 @@ func mutationArgs(c *Call) (args, bases []Arg) {
foreachArg(c, func(arg, base Arg, _ *[]Arg) {
switch typ := arg.Type().(type) {
case *StructType:
- if isSpecialStruct(typ) == nil {
+ if specialStructs[typ.Name()] == nil {
// For structs only individual fields are updated.
return
}
@@ -524,7 +531,7 @@ func mutationArgs(c *Call) (args, bases []Arg) {
return
}
if base != nil {
- if _, ok := base.Type().(*StructType); ok && isSpecialStruct(base.Type()) != nil {
+ if _, ok := base.Type().(*StructType); ok && specialStructs[base.Type().Name()] != nil {
// These special structs are mutated as a whole.
return
}
diff --git a/prog/mutation_test.go b/prog/mutation_test.go
index 2f70e0a5d..060fe5f33 100644
--- a/prog/mutation_test.go
+++ b/prog/mutation_test.go
@@ -1,16 +1,19 @@
// Copyright 2015 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 prog
+package prog_test
import (
"bytes"
"fmt"
"testing"
+
+ . "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func TestClone(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
p1 := p.Clone()
@@ -23,7 +26,7 @@ func TestClone(t *testing.T) {
}
func TestMutate(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
next:
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
@@ -47,7 +50,7 @@ next:
}
func TestMutateCorpus(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
var corpus []*Prog
for i := 0; i < 100; i++ {
p := Generate(rs, 10, nil)
@@ -137,7 +140,7 @@ func TestMutateTable(t *testing.T) {
"readv(r0, &(0x7f0000000000)=[{&(0x7f0000001000)=\"00\", 0x1}, {&(0x7f0000002000)=\"00\", 0x2}, {&(0x7f0000000000)=\"00\", 0x3}], 0x3)\n",
},
}
- rs, _ := initTest(t)
+ rs, _ := InitTest(t)
nextTest:
for ti, test := range tests {
p, err := Deserialize([]byte(test[0]))
@@ -288,35 +291,23 @@ func TestMinimize(t *testing.T) {
}
func TestMinimizeRandom(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
iters /= 10 // Long test.
for i := 0; i < iters; i++ {
p := Generate(rs, 5, nil)
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
- if err := p1.validate(); err != nil {
- t.Fatalf("invalid program: %v", err)
- }
return false
}, true)
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
- if err := p1.validate(); err != nil {
- t.Fatalf("invalid program: %v", err)
- }
return true
}, true)
}
for i := 0; i < iters; i++ {
p := Generate(rs, 5, nil)
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
- if err := p1.validate(); err != nil {
- t.Fatalf("invalid program: %v", err)
- }
return false
}, false)
Minimize(p, len(p.Calls)-1, func(p1 *Prog, callIndex int) bool {
- if err := p1.validate(); err != nil {
- t.Fatalf("invalid program: %v", err)
- }
return true
}, false)
}
diff --git a/prog/prio.go b/prog/prio.go
index 92d2ea3db..c64ae319b 100644
--- a/prog/prio.go
+++ b/prog/prio.go
@@ -7,8 +7,6 @@ import (
"fmt"
"math/rand"
"sort"
-
- . "github.com/google/syzkaller/sys"
)
// Calulation of call-to-call priorities.
diff --git a/prog/prog.go b/prog/prog.go
index 6e18f3a4a..579bac4e0 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -5,8 +5,6 @@ package prog
import (
"fmt"
-
- . "github.com/google/syzkaller/sys"
)
type Prog struct {
@@ -224,11 +222,11 @@ func encodeValue(value uint64, size uint64, bigEndian bool) uint64 {
}
}
-func constArg(t Type, v uint64) Arg {
+func MakeConstArg(t Type, v uint64) Arg {
return &ConstArg{ArgCommon: ArgCommon{typ: t}, Val: v}
}
-func resultArg(t Type, r Arg, v uint64) Arg {
+func MakeResultArg(t Type, r Arg, v uint64) Arg {
arg := &ResultArg{ArgCommon: ArgCommon{typ: t}, Res: r, Val: v}
if r == nil {
return arg
@@ -249,11 +247,11 @@ func dataArg(t Type, data []byte) Arg {
return &DataArg{ArgCommon: ArgCommon{typ: t}, Data: append([]byte{}, data...)}
}
-func pointerArg(t Type, page uint64, off int, npages uint64, obj Arg) Arg {
+func MakePointerArg(t Type, page uint64, off int, npages uint64, obj Arg) Arg {
return &PointerArg{ArgCommon: ArgCommon{typ: t}, PageIndex: page, PageOffset: off, PagesNum: npages, Res: obj}
}
-func groupArg(t Type, inner []Arg) Arg {
+func MakeGroupArg(t Type, inner []Arg) Arg {
return &GroupArg{ArgCommon: ArgCommon{typ: t}, Inner: inner}
}
@@ -261,16 +259,16 @@ func unionArg(t Type, opt Arg, typ Type) Arg {
return &UnionArg{ArgCommon: ArgCommon{typ: t}, Option: opt, OptionType: typ}
}
-func returnArg(t Type) Arg {
+func MakeReturnArg(t Type) Arg {
return &ReturnArg{ArgCommon: ArgCommon{typ: t}}
}
func defaultArg(t Type) Arg {
switch typ := t.(type) {
case *IntType, *ConstType, *FlagsType, *LenType, *ProcType, *CsumType:
- return constArg(t, t.Default())
+ return MakeConstArg(t, t.Default())
case *ResourceType:
- return resultArg(t, nil, typ.Desc.Type.Default())
+ return MakeResultArg(t, nil, typ.Desc.Type.Default())
case *BufferType:
var data []byte
if typ.Kind == BufferString && typ.TypeSize != 0 {
@@ -278,23 +276,23 @@ func defaultArg(t Type) Arg {
}
return dataArg(t, data)
case *ArrayType:
- return groupArg(t, nil)
+ return MakeGroupArg(t, nil)
case *StructType:
var inner []Arg
for _, field := range typ.Fields {
inner = append(inner, defaultArg(field))
}
- return groupArg(t, inner)
+ return MakeGroupArg(t, inner)
case *UnionType:
return unionArg(t, defaultArg(typ.Fields[0]), typ.Fields[0])
case *VmaType:
- return pointerArg(t, 0, 0, 1, nil)
+ return MakePointerArg(t, 0, 0, 1, nil)
case *PtrType:
var res Arg
if !t.Optional() && t.Dir() != DirOut {
res = defaultArg(typ.Type)
}
- return pointerArg(t, 0, 0, 0, res)
+ return MakePointerArg(t, 0, 0, 0, res)
default:
panic("unknown arg type")
}
@@ -364,7 +362,7 @@ func (p *Prog) removeArg(c *Call, arg0 Arg) {
if _, ok := arg1.(*ResultArg); !ok {
panic("use references not ArgResult")
}
- arg2 := resultArg(arg1.Type(), nil, arg1.Type().Default())
+ arg2 := MakeResultArg(arg1.Type(), nil, arg1.Type().Default())
p.replaceArg(c, arg1, arg2, nil)
}
}
diff --git a/prog/prog_test.go b/prog/prog_test.go
index b377846fb..69aa9c166 100644
--- a/prog/prog_test.go
+++ b/prog/prog_test.go
@@ -6,47 +6,29 @@ package prog
import (
"bytes"
"fmt"
- "math/rand"
"testing"
- "time"
-
- . "github.com/google/syzkaller/sys"
+ //. "github.com/google/syzkaller/prog"
+ //_ "github.com/google/syzkaller/sys"
)
-func init() {
- debug = true
-}
-
-func initTest(t *testing.T) (rand.Source, int) {
- t.Parallel()
- iters := 10000
- if testing.Short() {
- iters = 100
- }
- seed := int64(time.Now().UnixNano())
- rs := rand.NewSource(seed)
- t.Logf("seed=%v", seed)
- return rs, iters
-}
-
func TestGeneration(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
Generate(rs, 20, nil)
}
}
func TestDefault(t *testing.T) {
- initTest(t)
+ InitTest(t)
for _, meta := range SyscallMap {
for _, t := range meta.Args {
- defaultArg(t)
+ DefaultArg(t)
}
}
}
func TestDefaultCallArgs(t *testing.T) {
- initTest(t)
+ InitTest(t)
for _, meta := range SyscallMap {
// Ensure that we can restore all arguments of all calls.
prog := fmt.Sprintf("%v()", meta.Name)
@@ -61,7 +43,7 @@ func TestDefaultCallArgs(t *testing.T) {
}
func TestSerialize(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
data := p.Serialize()
@@ -83,9 +65,10 @@ func TestSerialize(t *testing.T) {
}
func TestVmaType(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
meta := SyscallMap["syz_test$vma0"]
r := newRand(rs)
+ pageSize := PageSize()
for i := 0; i < iters; i++ {
s := newState(nil)
calls := r.generateParticularCall(s, meta)
diff --git a/prog/rand.go b/prog/rand.go
index 110436e37..1993d7461 100644
--- a/prog/rand.go
+++ b/prog/rand.go
@@ -12,7 +12,6 @@ import (
"sync"
"github.com/google/syzkaller/pkg/ifuzz"
- . "github.com/google/syzkaller/sys"
)
var pageStartPool = sync.Pool{New: func() interface{} { return new([]uint64) }}
@@ -224,102 +223,6 @@ func (r *randGen) randStringImpl(s *state, vals []string) []byte {
return buf.Bytes()
}
-func isSpecialStruct(typ Type) func(r *randGen, s *state) (Arg, []*Call) {
- a, ok := typ.(*StructType)
- if !ok {
- panic("must be a struct")
- }
- switch typ.Name() {
- case "timespec":
- return func(r *randGen, s *state) (Arg, []*Call) {
- return r.timespec(s, a, false)
- }
- case "timeval":
- return func(r *randGen, s *state) (Arg, []*Call) {
- return r.timespec(s, a, true)
- }
- }
- return nil
-}
-
-func (r *randGen) timespec(s *state, typ *StructType, usec bool) (arg Arg, calls []*Call) {
- // We need to generate timespec/timeval that are either (1) definitely in the past,
- // or (2) definitely in unreachable fututre, or (3) few ms ahead of now.
- // Note timespec/timeval can be absolute or relative to now.
- switch {
- case r.nOutOf(1, 4):
- // now for relative, past for absolute
- arg = groupArg(typ, []Arg{
- resultArg(typ.Fields[0], nil, 0),
- resultArg(typ.Fields[1], nil, 0),
- })
- case r.nOutOf(1, 3):
- // few ms ahead for relative, past for absolute
- nsec := uint64(10 * 1e6)
- if usec {
- nsec /= 1e3
- }
- arg = groupArg(typ, []Arg{
- resultArg(typ.Fields[0], nil, 0),
- resultArg(typ.Fields[1], nil, nsec),
- })
- case r.nOutOf(1, 2):
- // unreachable fututre for both relative and absolute
- arg = groupArg(typ, []Arg{
- resultArg(typ.Fields[0], nil, 2e9),
- resultArg(typ.Fields[1], nil, 0),
- })
- default:
- // few ms ahead for absolute
- meta := SyscallMap["clock_gettime"]
- ptrArgType := meta.Args[1].(*PtrType)
- argType := ptrArgType.Type.(*StructType)
- tp := groupArg(argType, []Arg{
- resultArg(argType.Fields[0], nil, 0),
- resultArg(argType.Fields[1], nil, 0),
- })
- var tpaddr Arg
- tpaddr, calls = r.addr(s, ptrArgType, 16, tp)
- gettime := &Call{
- Meta: meta,
- Args: []Arg{
- constArg(meta.Args[0], CLOCK_REALTIME),
- tpaddr,
- },
- Ret: returnArg(meta.Ret),
- }
- calls = append(calls, gettime)
- sec := resultArg(typ.Fields[0], tp.(*GroupArg).Inner[0], 0)
- nsec := resultArg(typ.Fields[1], tp.(*GroupArg).Inner[1], 0)
- if usec {
- nsec.(*ResultArg).OpDiv = 1e3
- nsec.(*ResultArg).OpAdd = 10 * 1e3
- } else {
- nsec.(*ResultArg).OpAdd = 10 * 1e6
- }
- arg = groupArg(typ, []Arg{sec, nsec})
- }
- return
-}
-
-// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
-func createMmapCall(start, npages uint64) *Call {
- meta := SyscallMap["mmap"]
- mmap := &Call{
- Meta: meta,
- Args: []Arg{
- pointerArg(meta.Args[0], start, 0, npages, nil),
- constArg(meta.Args[1], npages*pageSize),
- constArg(meta.Args[2], PROT_READ|PROT_WRITE),
- constArg(meta.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED),
- resultArg(meta.Args[4], nil, InvalidFD),
- constArg(meta.Args[5], 0),
- },
- Ret: returnArg(meta.Ret),
- }
- return mmap
-}
-
func (r *randGen) addr1(s *state, typ Type, size uint64, data Arg) (Arg, []*Call) {
npages := (size + pageSize - 1) / pageSize
if npages == 0 {
@@ -339,8 +242,8 @@ func (r *randGen) addr1(s *state, typ Type, size uint64, data Arg) (Arg, []*Call
if !free {
continue
}
- c := createMmapCall(i, npages)
- return pointerArg(typ, i, 0, 0, data), []*Call{c}
+ c := makeMmap(i, npages)
+ return MakePointerArg(typ, i, 0, 0, data), []*Call{c}
}
return r.randPageAddr(s, typ, npages, data, false), nil
}
@@ -357,7 +260,7 @@ func (r *randGen) addr(s *state, typ Type, size uint64, data Arg) (Arg, []*Call)
case r.nOutOf(50, 52):
a.PageOffset = -int(size)
case r.nOutOf(1, 2):
- a.PageOffset = r.Intn(pageSize)
+ a.PageOffset = r.Intn(int(pageSize))
default:
if size > 0 {
a.PageOffset = -r.Intn(int(size))
@@ -395,13 +298,13 @@ func (r *randGen) randPageAddr(s *state, typ Type, npages uint64, data Arg, vma
}
*poolPtr = starts
pageStartPool.Put(poolPtr)
- return pointerArg(typ, page, 0, npages, data)
+ return MakePointerArg(typ, page, 0, npages, data)
}
func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []*Call) {
if r.inCreateResource {
special := res.SpecialValues()
- return resultArg(res, nil, special[r.Intn(len(special))]), nil
+ return MakeResultArg(res, nil, special[r.Intn(len(special))]), nil
}
r.inCreateResource = true
defer func() { r.inCreateResource = false }()
@@ -428,7 +331,7 @@ func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []
metas = append(metas, meta)
}
if len(metas) == 0 {
- return resultArg(res, nil, res.Default()), nil
+ return MakeResultArg(res, nil, res.Default()), nil
}
// Now we have a set of candidate calls that can create the necessary resource.
@@ -447,7 +350,7 @@ func (r *randGen) createResource(s *state, res *ResourceType) (arg Arg, calls []
}
if len(allres) != 0 {
// Bingo!
- arg := resultArg(res, allres[r.Intn(len(allres))], 0)
+ arg := MakeResultArg(res, allres[r.Intn(len(allres))], 0)
return arg, calls
}
// Discard unsuccessful calls.
@@ -550,7 +453,7 @@ func (r *randGen) generateCall(s *state, p *Prog) []*Call {
func (r *randGen) generateParticularCall(s *state, meta *Syscall) (calls []*Call) {
c := &Call{
Meta: meta,
- Ret: returnArg(meta.Ret),
+ Ret: MakeReturnArg(meta.Ret),
}
c.Args, calls = r.generateArgs(s, meta.Args)
assignSizesCall(c)
@@ -629,7 +532,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
}
}()
if r.recDepth[str.Name()] >= 3 {
- return pointerArg(typ, 0, 0, 0, nil), nil
+ return MakePointerArg(typ, 0, 0, 0, nil), nil
}
}
}
@@ -650,7 +553,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
}
}
if len(allres) != 0 {
- arg = resultArg(a, allres[r.Intn(len(allres))], 0)
+ arg = MakeResultArg(a, allres[r.Intn(len(allres))], 0)
} else {
arg, calls = r.createResource(s, a)
}
@@ -659,7 +562,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
arg, calls = r.createResource(s, a)
default:
special := a.SpecialValues()
- arg = resultArg(a, nil, special[r.Intn(len(special))])
+ arg = MakeResultArg(a, nil, special[r.Intn(len(special))])
}
return arg, calls
case *BufferType:
@@ -707,9 +610,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
arg := r.randPageAddr(s, a, npages, nil, true)
return arg, nil
case *FlagsType:
- return constArg(a, r.flags(a.Vals)), nil
+ return MakeConstArg(a, r.flags(a.Vals)), nil
case *ConstType:
- return constArg(a, a.Val), nil
+ return MakeConstArg(a, a.Val), nil
case *IntType:
v := r.randInt()
switch a.Kind {
@@ -725,9 +628,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
case IntRange:
v = r.randRangeInt(a.RangeBegin, a.RangeEnd)
}
- return constArg(a, v), nil
+ return MakeConstArg(a, v), nil
case *ProcType:
- return constArg(a, r.rand(int(a.ValuesPerProc))), nil
+ return MakeConstArg(a, r.rand(int(a.ValuesPerProc))), nil
case *ArrayType:
var count uint64
switch a.Kind {
@@ -743,14 +646,14 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
inner = append(inner, arg1)
calls = append(calls, calls1...)
}
- return groupArg(a, inner), calls
+ return MakeGroupArg(a, inner), calls
case *StructType:
- if ctor := isSpecialStruct(a); ctor != nil && a.Dir() != DirOut {
- arg, calls = ctor(r, s)
+ if gen := specialStructs[a.Name()]; gen != nil && a.Dir() != DirOut {
+ arg, calls = gen(&Gen{r, s}, a, nil)
return
}
args, calls := r.generateArgs(s, a.Fields)
- group := groupArg(a, args)
+ group := MakeGroupArg(a, args)
return group, calls
case *UnionType:
optType := a.Fields[r.Intn(len(a.Fields))]
@@ -763,7 +666,7 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
// So try to reuse a previously used address.
addrs := s.resources["iocbptr"]
addr := addrs[r.Intn(len(addrs))].(*PointerArg)
- arg = pointerArg(a, addr.PageIndex, addr.PageOffset, addr.PagesNum, inner)
+ arg = MakePointerArg(a, addr.PageIndex, addr.PageOffset, addr.PagesNum, inner)
return arg, calls
}
arg, calls1 := r.addr(s, a, inner.Size(), inner)
@@ -771,9 +674,9 @@ func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
return arg, calls
case *LenType:
// Return placeholder value of 0 while generating len arg.
- return constArg(a, 0), nil
+ return MakeConstArg(a, 0), nil
case *CsumType:
- return constArg(a, 0), nil
+ return MakeConstArg(a, 0), nil
default:
panic("unknown argument type")
}
diff --git a/prog/size.go b/prog/size.go
index b715f6f26..b9920c19b 100644
--- a/prog/size.go
+++ b/prog/size.go
@@ -5,32 +5,30 @@ package prog
import (
"fmt"
-
- . "github.com/google/syzkaller/sys"
)
func generateSize(arg Arg, lenType *LenType) Arg {
if arg == nil {
// Arg is an optional pointer, set size to 0.
- return constArg(lenType, 0)
+ return MakeConstArg(lenType, 0)
}
switch arg.Type().(type) {
case *VmaType:
a := arg.(*PointerArg)
- return constArg(lenType, a.PagesNum*pageSize)
+ return MakeConstArg(lenType, a.PagesNum*pageSize)
case *ArrayType:
a := arg.(*GroupArg)
if lenType.ByteSize != 0 {
- return constArg(lenType, a.Size()/lenType.ByteSize)
+ return MakeConstArg(lenType, a.Size()/lenType.ByteSize)
} else {
- return constArg(lenType, uint64(len(a.Inner)))
+ return MakeConstArg(lenType, uint64(len(a.Inner)))
}
default:
if lenType.ByteSize != 0 {
- return constArg(lenType, arg.Size()/lenType.ByteSize)
+ return MakeConstArg(lenType, arg.Size()/lenType.ByteSize)
} else {
- return constArg(lenType, arg.Size())
+ return MakeConstArg(lenType, arg.Size())
}
}
}
diff --git a/prog/size_test.go b/prog/size_test.go
index c72e5283f..778725d49 100644
--- a/prog/size_test.go
+++ b/prog/size_test.go
@@ -1,21 +1,24 @@
// Copyright 2016 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 prog
+package prog_test
import (
"bytes"
"strings"
"testing"
+
+ . "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func TestAssignSizeRandom(t *testing.T) {
- rs, iters := initTest(t)
+ rs, iters := InitTest(t)
for i := 0; i < iters; i++ {
p := Generate(rs, 10, nil)
data0 := p.Serialize()
for _, call := range p.Calls {
- assignSizesCall(call)
+ AssignSizesCall(call)
}
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
t.Fatalf("different lens assigned, initial: %v, new: %v", data0, data1)
@@ -23,7 +26,7 @@ func TestAssignSizeRandom(t *testing.T) {
p.Mutate(rs, 10, nil, nil)
data0 = p.Serialize()
for _, call := range p.Calls {
- assignSizesCall(call)
+ AssignSizesCall(call)
}
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
t.Fatalf("different lens assigned, initial: %v, new: %v", data0, data1)
@@ -128,7 +131,7 @@ func TestAssignSize(t *testing.T) {
t.Fatalf("failed to deserialize prog %v: %v", i, err)
}
for _, call := range p.Calls {
- assignSizesCall(call)
+ AssignSizesCall(call)
}
p1 := strings.TrimSpace(string(p.Serialize()))
if p1 != test.sizedProg {
diff --git a/prog/target.go b/prog/target.go
new file mode 100644
index 000000000..f5dde79f4
--- /dev/null
+++ b/prog/target.go
@@ -0,0 +1,117 @@
+// Copyright 2017 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 prog
+
+import (
+ "fmt"
+)
+
+// Target describes target OS/arch pair.
+type Target struct {
+ OS string
+ Arch string
+ PtrSize uint64
+ PageSize uint64
+ DataOffset uint64
+
+ Syscalls []*Syscall
+ Resources []*ResourceDesc
+
+ // MakeMmap creates call that maps [start, start+npages) page range.
+ MakeMmap func(start, npages uint64) *Call
+
+ // AnalyzeMmap analyzes the call c regarding mapping/unmapping memory.
+ // If it maps/unmaps any memory returns [start, start+npages) range,
+ // otherwise returns npages = 0.
+ AnalyzeMmap func(c *Call) (start, npages uint64, mapped bool)
+
+ // SanitizeCall neutralizes harmful calls.
+ SanitizeCall func(c *Call)
+
+ // SpecialStructs allows target to do custom generation/mutation for some struct types.
+ // Map key is struct name for which custom generation/mutation is required.
+ // Map value is custom generation/mutation function that will be called
+ // for the corresponding structs. g is helper object that allows generate random numbers,
+ // allocate memory, etc. typ is the struct type. old is the old value of the struct
+ // for mutation, or nil for generation. The function returns a new value of the struct,
+ // and optionally any calls that need to be inserted before the arg reference.
+ SpecialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
+
+ resourceMap map[string]*ResourceDesc
+ syscallMap map[string]*Syscall
+ resourceCtors map[string][]*Syscall
+}
+
+type StructGen func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
+
+var targets = make(map[string]*Target)
+
+func RegisterTarget(target *Target) {
+ key := target.OS + "/" + target.Arch
+ if targets[key] != nil {
+ panic(fmt.Sprintf("duplicate target %v", key))
+ }
+ initTarget(target)
+ targets[key] = target
+
+ // For now we copy target to global vars
+ // because majority of the code is not prepared for multiple targets.
+ if len(targets) > 1 {
+ panic("only 1 target is supported")
+ }
+ Syscalls = target.Syscalls
+ SyscallMap = target.syscallMap
+ Resources = target.resourceMap
+ resourceCtors = target.resourceCtors
+ ptrSize = target.PtrSize
+ pageSize = target.PageSize
+ dataOffset = target.DataOffset
+
+ makeMmap = target.MakeMmap
+ analyzeMmap = target.AnalyzeMmap
+ sanitizeCall = target.SanitizeCall
+ specialStructs = target.SpecialStructs
+}
+
+func initTarget(target *Target) {
+ target.syscallMap = make(map[string]*Syscall)
+ for _, c := range target.Syscalls {
+ target.syscallMap[c.Name] = c
+ }
+ target.resourceMap = make(map[string]*ResourceDesc)
+ target.resourceCtors = make(map[string][]*Syscall)
+ for _, r := range target.Resources {
+ target.resourceMap[r.Name] = r
+ target.resourceCtors[r.Name] = calcResourceCtors(r.Kind, false)
+ }
+}
+
+type Gen struct {
+ r *randGen
+ s *state
+}
+
+func (g *Gen) NOutOf(n, outOf int) bool {
+ return g.r.nOutOf(n, outOf)
+}
+
+func (g *Gen) Alloc(ptrType Type, data Arg) (Arg, []*Call) {
+ return g.r.addr(g.s, ptrType, data.Size(), data)
+}
+
+var (
+ ptrSize uint64
+ pageSize uint64
+ dataOffset uint64
+
+ Syscalls []*Syscall
+ SyscallMap map[string]*Syscall
+ Resources map[string]*ResourceDesc
+ resourceCtors map[string][]*Syscall
+
+ makeMmap func(start, npages uint64) *Call
+ analyzeMmap func(c *Call) (start, npages uint64, mapped bool)
+ sanitizeCall func(c *Call)
+ specialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
+)
diff --git a/sys/decl.go b/prog/types.go
index 82d27e915..6fdc0d975 100644
--- a/sys/decl.go
+++ b/prog/types.go
@@ -1,7 +1,7 @@
// Copyright 2015/2016 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 sys
+package prog
import (
"fmt"
@@ -95,10 +95,6 @@ func (t TypeCommon) Dir() Dir {
return t.ArgDir
}
-const (
- InvalidFD = ^uint64(0)
-)
-
type ResourceDesc struct {
Name string
Type Type
@@ -267,12 +263,6 @@ func (t *UnionType) FieldName() string {
return t.FldName
}
-var (
- SyscallMap = make(map[string]*Syscall)
- Resources map[string]*ResourceDesc
- ctors = make(map[string][]*Syscall)
-)
-
type StructDesc struct {
TypeCommon
Fields []Type
@@ -293,53 +283,12 @@ type KeyedStruct struct {
Desc *StructDesc
}
-func initStructFields() {
- keyedStructs := make(map[StructKey]*StructDesc)
- for _, desc := range structDescs {
- keyedStructs[desc.Key] = desc.Desc
- }
-
- for _, c := range Syscalls {
- ForeachType(c, func(t Type) {
- switch s := t.(type) {
- case *StructType:
- s.StructDesc = keyedStructs[s.Key]
- if s.StructDesc == nil {
- panic("no struct desc")
- }
- case *UnionType:
- s.StructDesc = keyedStructs[s.Key]
- if s.StructDesc == nil {
- panic("no union desc")
- }
- }
- })
- }
-}
-
// ResourceConstructors returns a list of calls that can create a resource of the given kind.
func ResourceConstructors(name string) []*Syscall {
- return ctors[name]
+ return resourceCtors[name]
}
-func initResources() {
- Resources = make(map[string]*ResourceDesc)
- for _, res := range resourceArray {
- Resources[res.Name] = res
- }
- for _, c := range Syscalls {
- ForeachType(c, func(t Type) {
- if r, ok := t.(*ResourceType); ok {
- r.Desc = Resources[r.TypeName]
- }
- })
- }
- for _, res := range resourceArray {
- ctors[res.Name] = resourceCtors(res.Kind, false)
- }
-}
-
-func resourceCtors(kind []string, precise bool) []*Syscall {
+func calcResourceCtors(kind []string, precise bool) []*Syscall {
// Find calls that produce the necessary resources.
var metas []*Syscall
for _, meta := range Syscalls {
@@ -426,7 +375,7 @@ func TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*Syscall]bool {
if _, ok := ctors[res.Desc.Name]; ok {
continue
}
- ctors[res.Desc.Name] = resourceCtors(res.Desc.Kind, true)
+ ctors[res.Desc.Name] = calcResourceCtors(res.Desc.Kind, true)
}
}
for {
@@ -506,17 +455,3 @@ func ForeachType(meta *Syscall, f func(Type)) {
rec(meta.Ret)
}
}
-
-func init() {
- initStructFields()
- initResources()
- structDescs = nil
-
- for _, c := range Syscalls {
- if SyscallMap[c.Name] != nil {
- println(c.Name)
- panic("duplicate syscall")
- }
- SyscallMap[c.Name] = c
- }
-}
diff --git a/prog/validation.go b/prog/validation.go
index 51520b29b..d5b4a4c04 100644
--- a/prog/validation.go
+++ b/prog/validation.go
@@ -5,8 +5,6 @@ package prog
import (
"fmt"
-
- . "github.com/google/syzkaller/sys"
)
var debug = false // enabled in tests
diff --git a/sys/init.go b/sys/init.go
new file mode 100644
index 000000000..edefe3a52
--- /dev/null
+++ b/sys/init.go
@@ -0,0 +1,257 @@
+// Copyright 2017 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 sys
+
+import (
+ "runtime"
+
+ "github.com/google/syzkaller/prog"
+)
+
+func init() {
+ lazyInit()
+ target := &prog.Target{
+ OS: runtime.GOOS,
+ Arch: runtime.GOARCH,
+ PtrSize: ptrSize,
+ PageSize: pageSize,
+ DataOffset: dataOffset,
+ Syscalls: syscalls,
+ Resources: resources,
+ MakeMmap: makeMmap,
+ AnalyzeMmap: analyzeMmap,
+ SanitizeCall: sanitizeCall,
+ SpecialStructs: map[string]func(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (prog.Arg, []*prog.Call){
+ "timespec": generateTimespec,
+ "timeval": generateTimespec,
+ },
+ }
+ prog.RegisterTarget(target)
+}
+
+const (
+ // TODO(dvyukov): dehardcode
+ ptrSize = 8
+ pageSize = 4 << 10
+ dataOffset = 512 << 20
+ invalidFD = ^uint64(0)
+)
+
+var (
+ mmapSyscall *prog.Syscall
+ clockGettimeSyscall *prog.Syscall
+)
+
+// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
+func makeMmap(start, npages uint64) *prog.Call {
+ return &prog.Call{
+ Meta: mmapSyscall,
+ Args: []prog.Arg{
+ prog.MakePointerArg(mmapSyscall.Args[0], start, 0, npages, nil),
+ prog.MakeConstArg(mmapSyscall.Args[1], npages*pageSize),
+ prog.MakeConstArg(mmapSyscall.Args[2], PROT_READ|PROT_WRITE),
+ prog.MakeConstArg(mmapSyscall.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED),
+ prog.MakeResultArg(mmapSyscall.Args[4], nil, invalidFD),
+ prog.MakeConstArg(mmapSyscall.Args[5], 0),
+ },
+ Ret: prog.MakeReturnArg(mmapSyscall.Ret),
+ }
+}
+
+func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) {
+ switch c.Meta.Name {
+ case "mmap":
+ // Filter out only very wrong arguments.
+ npages = c.Args[1].(*prog.ConstArg).Val / pageSize
+ if npages == 0 {
+ return
+ }
+ flags := c.Args[3].(*prog.ConstArg).Val
+ fd := c.Args[4].(*prog.ResultArg).Val
+ if flags&MAP_ANONYMOUS == 0 && fd == invalidFD {
+ return
+ }
+ start = c.Args[0].(*prog.PointerArg).PageIndex
+ mapped = true
+ return
+ case "munmap":
+ start = c.Args[0].(*prog.PointerArg).PageIndex
+ npages = c.Args[1].(*prog.ConstArg).Val / pageSize
+ mapped = false
+ return
+ case "mremap":
+ start = c.Args[4].(*prog.PointerArg).PageIndex
+ npages = c.Args[2].(*prog.ConstArg).Val / pageSize
+ mapped = true
+ return
+ default:
+ return
+ }
+}
+
+func sanitizeCall(c *prog.Call) {
+ switch c.Meta.CallName {
+ case "mmap":
+ // Add MAP_FIXED flag, otherwise it produces non-deterministic results.
+ c.Args[3].(*prog.ConstArg).Val |= MAP_FIXED
+ case "mremap":
+ // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
+ flags := c.Args[3].(*prog.ConstArg)
+ if flags.Val&MREMAP_MAYMOVE != 0 {
+ flags.Val |= MREMAP_FIXED
+ }
+ case "mknod", "mknodat":
+ pos := 1
+ if c.Meta.CallName == "mknodat" {
+ pos = 2
+ }
+ mode := c.Args[pos].(*prog.ConstArg)
+ dev := c.Args[pos+1].(*prog.ConstArg)
+ // Char and block devices read/write io ports, kernel memory and do other nasty things.
+ // TODO: not required if executor drops privileges.
+ switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) {
+ case S_IFREG, S_IFIFO, S_IFSOCK:
+ case S_IFBLK:
+ if dev.Val>>8 == 7 {
+ break // loop
+ }
+ mode.Val &^= S_IFBLK
+ mode.Val |= S_IFREG
+ case S_IFCHR:
+ mode.Val &^= S_IFCHR
+ mode.Val |= S_IFREG
+ }
+ case "syslog":
+ cmd := c.Args[0].(*prog.ConstArg)
+ // These disable console output, but we need it.
+ if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON {
+ cmd.Val = SYSLOG_ACTION_SIZE_UNREAD
+ }
+ case "ioctl":
+ cmd := c.Args[1].(*prog.ConstArg)
+ // Freeze kills machine. Though, it is an interesting functions,
+ // so we need to test it somehow.
+ // TODO: not required if executor drops privileges.
+ if uint32(cmd.Val) == FIFREEZE {
+ cmd.Val = FITHAW
+ }
+ case "ptrace":
+ req := c.Args[0].(*prog.ConstArg)
+ // PTRACE_TRACEME leads to unkillable processes, see:
+ // https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
+ if req.Val == PTRACE_TRACEME {
+ req.Val = ^uint64(0)
+ }
+ case "exit", "exit_group":
+ code := c.Args[0].(*prog.ConstArg)
+ // These codes are reserved by executor.
+ if code.Val%128 == 67 || code.Val%128 == 68 {
+ code.Val = 1
+ }
+ }
+}
+
+func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (arg prog.Arg, calls []*prog.Call) {
+ // We need to generate timespec/timeval that are either
+ // (1) definitely in the past, or
+ // (2) definitely in unreachable fututre, or
+ // (3) few ms ahead of now.
+ // Note timespec/timeval can be absolute or relative to now.
+ usec := typ.Name() == "timeval"
+ switch {
+ case g.NOutOf(1, 4):
+ // Now for relative, past for absolute.
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 0),
+ prog.MakeResultArg(typ.Fields[1], nil, 0),
+ })
+ case g.NOutOf(1, 3):
+ // Few ms ahead for relative, past for absolute
+ nsec := uint64(10 * 1e6)
+ if usec {
+ nsec /= 1e3
+ }
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 0),
+ prog.MakeResultArg(typ.Fields[1], nil, nsec),
+ })
+ case g.NOutOf(1, 2):
+ // Unreachable fututre for both relative and absolute
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 2e9),
+ prog.MakeResultArg(typ.Fields[1], nil, 0),
+ })
+ default:
+ // Few ms ahead for absolute.
+ meta := clockGettimeSyscall
+ ptrArgType := meta.Args[1].(*prog.PtrType)
+ argType := ptrArgType.Type.(*prog.StructType)
+ tp := prog.MakeGroupArg(argType, []prog.Arg{
+ prog.MakeResultArg(argType.Fields[0], nil, 0),
+ prog.MakeResultArg(argType.Fields[1], nil, 0),
+ })
+ var tpaddr prog.Arg
+ tpaddr, calls = g.Alloc(ptrArgType, tp)
+ gettime := &prog.Call{
+ Meta: meta,
+ Args: []prog.Arg{
+ prog.MakeConstArg(meta.Args[0], CLOCK_REALTIME),
+ tpaddr,
+ },
+ Ret: prog.MakeReturnArg(meta.Ret),
+ }
+ calls = append(calls, gettime)
+ sec := prog.MakeResultArg(typ.Fields[0], tp.(*prog.GroupArg).Inner[0], 0)
+ nsec := prog.MakeResultArg(typ.Fields[1], tp.(*prog.GroupArg).Inner[1], 0)
+ if usec {
+ nsec.(*prog.ResultArg).OpDiv = 1e3
+ nsec.(*prog.ResultArg).OpAdd = 10 * 1e3
+ } else {
+ nsec.(*prog.ResultArg).OpAdd = 10 * 1e6
+ }
+ arg = prog.MakeGroupArg(typ, []prog.Arg{sec, nsec})
+ }
+ return
+}
+
+func lazyInit() {
+ resourceMap := make(map[string]*prog.ResourceDesc)
+ for _, res := range resources {
+ resourceMap[res.Name] = res
+ }
+
+ keyedStructs := make(map[prog.StructKey]*prog.StructDesc)
+ for _, desc := range structDescs {
+ keyedStructs[desc.Key] = desc.Desc
+ }
+ structDescs = nil
+
+ for _, c := range syscalls {
+ prog.ForeachType(c, func(t0 prog.Type) {
+ switch t := t0.(type) {
+ case *prog.ResourceType:
+ t.Desc = resourceMap[t.TypeName]
+ if t.Desc == nil {
+ panic("no resource desc")
+ }
+ case *prog.StructType:
+ t.StructDesc = keyedStructs[t.Key]
+ if t.StructDesc == nil {
+ panic("no struct desc")
+ }
+ case *prog.UnionType:
+ t.StructDesc = keyedStructs[t.Key]
+ if t.StructDesc == nil {
+ panic("no union desc")
+ }
+ }
+ })
+ switch c.Name {
+ case "mmap":
+ mmapSyscall = c
+ case "clock_gettime":
+ clockGettimeSyscall = c
+ }
+ }
+}
diff --git a/sys/sys_386.go b/sys/sys_386.go
index f0eebd212..a699a8893 100644
--- a/sys/sys_386.go
+++ b/sys/sys_386.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 18446744073709551615, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_amd64.go b/sys/sys_amd64.go
index 0b85dda44..5325d7f13 100644
--- a/sys/sys_amd64.go
+++ b/sys/sys_amd64.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 43, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_arm.go b/sys/sys_arm.go
index adcd5dbef..128fd836d 100644
--- a/sys/sys_arm.go
+++ b/sys/sys_arm.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 9437469, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_arm64.go b/sys/sys_arm64.go
index 435eb92b6..bfc975594 100644
--- a/sys/sys_arm64.go
+++ b/sys/sys_arm64.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 202, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_ppc64le.go b/sys/sys_ppc64le.go
index 52a8bca35..332c3e6b2 100644
--- a/sys/sys_ppc64le.go
+++ b/sys/sys_ppc64le.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 330, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/syz-sysgen/syscallnr.go b/sys/syz-sysgen/syscallnr.go
index 02c676cf0..da427a553 100644
--- a/sys/syz-sysgen/syscallnr.go
+++ b/sys/syz-sysgen/syscallnr.go
@@ -9,7 +9,7 @@ import (
"strings"
"text/template"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
type Arch struct {
@@ -26,7 +26,7 @@ var archs = []*Arch{
{"ppc64le", 8, []string{"__ppc64__", "__PPC64__", "__powerpc64__"}},
}
-func generateExecutorSyscalls(arch *Arch, syscalls []*sys.Syscall) []byte {
+func generateExecutorSyscalls(arch *Arch, syscalls []*prog.Syscall) []byte {
data := ArchData{
CARCH: arch.CARCH,
}
diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go
index 7381f1edb..f09835aef 100644
--- a/sys/syz-sysgen/sysgen.go
+++ b/sys/syz-sysgen/sysgen.go
@@ -116,8 +116,9 @@ func main() {
func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io.Writer) {
fmt.Fprintf(out, "// AUTOGENERATED FILE\n")
fmt.Fprintf(out, "package sys\n\n")
+ fmt.Fprintf(out, "import . \"github.com/google/syzkaller/prog\"\n\n")
- fmt.Fprintf(out, "var resourceArray = ")
+ fmt.Fprintf(out, "var resources = ")
serializer.Write(out, prog.Resources)
fmt.Fprintf(out, "\n\n")
@@ -133,7 +134,7 @@ func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io
serializer.Write(out, prog.StructDescs)
fmt.Fprintf(out, "\n\n")
- fmt.Fprintf(out, "var Syscalls = ")
+ fmt.Fprintf(out, "var syscalls = ")
serializer.Write(out, prog.Syscalls)
fmt.Fprintf(out, "\n\n")
diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go
index 8f8a62829..8c9e5fbdf 100644
--- a/syz-fuzzer/fuzzer.go
+++ b/syz-fuzzer/fuzzer.go
@@ -202,10 +202,10 @@ func main() {
if err != nil {
panic(err)
}
- if _, ok := calls[sys.SyscallMap["syz_emit_ethernet"]]; ok {
+ if _, ok := calls[prog.SyscallMap["syz_emit_ethernet"]]; ok {
config.Flags |= ipc.FlagEnableTun
}
- if _, ok := calls[sys.SyscallMap["syz_extract_tcp_res"]]; ok {
+ if _, ok := calls[prog.SyscallMap["syz_extract_tcp_res"]]; ok {
config.Flags |= ipc.FlagEnableTun
}
if faultInjectionEnabled {
@@ -407,18 +407,18 @@ func main() {
}
}
-func buildCallList(enabledCalls string) map[*sys.Syscall]bool {
- calls := make(map[*sys.Syscall]bool)
+func buildCallList(enabledCalls string) map[*prog.Syscall]bool {
+ calls := make(map[*prog.Syscall]bool)
if enabledCalls != "" {
for _, id := range strings.Split(enabledCalls, ",") {
n, err := strconv.ParseUint(id, 10, 64)
- if err != nil || n >= uint64(len(sys.Syscalls)) {
+ if err != nil || n >= uint64(len(prog.Syscalls)) {
panic(fmt.Sprintf("invalid syscall in -calls flag: '%v", id))
}
- calls[sys.Syscalls[n]] = true
+ calls[prog.Syscalls[n]] = true
}
} else {
- for _, c := range sys.Syscalls {
+ for _, c := range prog.Syscalls {
calls[c] = true
}
}
@@ -434,7 +434,7 @@ func buildCallList(enabledCalls string) map[*sys.Syscall]bool {
}
}
- trans := sys.TransitivelyEnabledCalls(calls)
+ trans := prog.TransitivelyEnabledCalls(calls)
for c := range calls {
if !trans[c] {
Logf(1, "disabling transitively unsupported syscall: %v", c.Name)
diff --git a/syz-manager/html.go b/syz-manager/html.go
index 566809457..a9a9b641a 100644
--- a/syz-manager/html.go
+++ b/syz-manager/html.go
@@ -24,7 +24,6 @@ import (
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/report"
"github.com/google/syzkaller/prog"
- "github.com/google/syzkaller/sys"
)
const dateFormat = "Jan 02 2006 15:04:05 MST"
@@ -196,7 +195,7 @@ func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
mgr.minimizeCorpus()
call := r.FormValue("call")
idx := -1
- for i, c := range sys.Syscalls {
+ for i, c := range prog.Syscalls {
if c.CallName == call {
idx = i
break
@@ -209,7 +208,7 @@ func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
data := &UIPrioData{Call: call}
for i, p := range mgr.prios[idx] {
- data.Prios = append(data.Prios, UIPrio{sys.Syscalls[i].Name, p})
+ data.Prios = append(data.Prios, UIPrio{prog.Syscalls[i].Name, p})
}
sort.Sort(UIPrioArray(data.Prios))
diff --git a/syz-manager/manager.go b/syz-manager/manager.go
index 653e0b428..16bd7edbd 100644
--- a/syz-manager/manager.go
+++ b/syz-manager/manager.go
@@ -29,6 +29,7 @@ import (
"github.com/google/syzkaller/pkg/repro"
. "github.com/google/syzkaller/pkg/rpctype"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
"github.com/google/syzkaller/syz-manager/mgrconfig"
"github.com/google/syzkaller/vm"
)
diff --git a/syz-manager/mgrconfig/mgrconfig.go b/syz-manager/mgrconfig/mgrconfig.go
index 4eacbfd7f..8423ddd46 100644
--- a/syz-manager/mgrconfig/mgrconfig.go
+++ b/syz-manager/mgrconfig/mgrconfig.go
@@ -12,7 +12,8 @@ import (
"github.com/google/syzkaller/pkg/config"
"github.com/google/syzkaller/pkg/osutil"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
"github.com/google/syzkaller/vm"
)
@@ -149,7 +150,7 @@ func load(data []byte, filename string) (*Config, map[int]bool, error) {
}
func parseSyscalls(cfg *Config) (map[int]bool, error) {
- match := func(call *sys.Syscall, str string) bool {
+ match := func(call *prog.Syscall, str string) bool {
if str == call.CallName || str == call.Name {
return true
}
@@ -163,7 +164,7 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
if len(cfg.Enable_Syscalls) != 0 {
for _, c := range cfg.Enable_Syscalls {
n := 0
- for _, call := range sys.Syscalls {
+ for _, call := range prog.Syscalls {
if match(call, c) {
syscalls[call.ID] = true
n++
@@ -174,13 +175,13 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
}
}
} else {
- for _, call := range sys.Syscalls {
+ for _, call := range prog.Syscalls {
syscalls[call.ID] = true
}
}
for _, c := range cfg.Disable_Syscalls {
n := 0
- for _, call := range sys.Syscalls {
+ for _, call := range prog.Syscalls {
if match(call, c) {
delete(syscalls, call.ID)
n++
@@ -191,7 +192,7 @@ func parseSyscalls(cfg *Config) (map[int]bool, error) {
}
}
// mmap is used to allocate memory.
- syscalls[sys.SyscallMap["mmap"].ID] = true
+ syscalls[prog.SyscallMap["mmap"].ID] = true
return syscalls, nil
}
diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go
index de2e1f7f3..1bedc09ea 100644
--- a/tools/syz-execprog/execprog.go
+++ b/tools/syz-execprog/execprog.go
@@ -23,6 +23,7 @@ import (
. "github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
var (
diff --git a/tools/syz-mutate/mutate.go b/tools/syz-mutate/mutate.go
index 9824db0b1..adda12df7 100644
--- a/tools/syz-mutate/mutate.go
+++ b/tools/syz-mutate/mutate.go
@@ -13,6 +13,7 @@ import (
"time"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
var (
diff --git a/tools/syz-stress/stress.go b/tools/syz-stress/stress.go
index d3ad6e9ed..159e7ddde 100644
--- a/tools/syz-stress/stress.go
+++ b/tools/syz-stress/stress.go
@@ -18,7 +18,7 @@ import (
"github.com/google/syzkaller/pkg/ipc"
. "github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/prog"
- "github.com/google/syzkaller/sys"
+ _ "github.com/google/syzkaller/sys"
)
var (
@@ -129,21 +129,21 @@ func readCorpus() []*prog.Prog {
return progs
}
-func buildCallList() map[*sys.Syscall]bool {
+func buildCallList() map[*prog.Syscall]bool {
calls, err := host.DetectSupportedSyscalls()
if err != nil {
Logf(0, "failed to detect host supported syscalls: %v", err)
- calls = make(map[*sys.Syscall]bool)
- for _, c := range sys.Syscalls {
+ calls = make(map[*prog.Syscall]bool)
+ for _, c := range prog.Syscalls {
calls[c] = true
}
}
- for _, c := range sys.Syscalls {
+ for _, c := range prog.Syscalls {
if !calls[c] {
Logf(0, "disabling unsupported syscall: %v", c.Name)
}
}
- trans := sys.TransitivelyEnabledCalls(calls)
+ trans := prog.TransitivelyEnabledCalls(calls)
for c := range calls {
if !trans[c] {
Logf(0, "disabling transitively unsupported syscall: %v", c.Name)
diff --git a/tools/syz-upgrade/upgrade.go b/tools/syz-upgrade/upgrade.go
index 0d7c42112..0a28a27fb 100644
--- a/tools/syz-upgrade/upgrade.go
+++ b/tools/syz-upgrade/upgrade.go
@@ -18,6 +18,7 @@ import (
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/prog"
+ _ "github.com/google/syzkaller/sys"
)
func main() {