aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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() {