prog: dot-import sys

In preparation for moving sys types to prog to reduce later diffs.
This commit is contained in:
Dmitry Vyukov 2017-09-05 10:46:34 +02:00
parent 5db39ab953
commit 4fc4702694
14 changed files with 276 additions and 282 deletions

View File

@ -11,7 +11,7 @@ package prog
import (
"fmt"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
const (
@ -51,18 +51,18 @@ func newState(ct *ChoiceTable) *state {
func (s *state) analyze(c *Call) {
foreachArgArray(&c.Args, c.Ret, func(arg, base Arg, _ *[]Arg) {
switch typ := arg.Type().(type) {
case *sys.ResourceType:
if typ.Dir() != sys.DirIn {
case *ResourceType:
if typ.Dir() != DirIn {
s.resources[typ.Desc.Name] = append(s.resources[typ.Desc.Name], arg)
// TODO: negative PIDs and add them as well (that's process groups).
}
case *sys.BufferType:
case *BufferType:
a := arg.(*DataArg)
if typ.Dir() != sys.DirOut && len(a.Data) != 0 {
if typ.Dir() != DirOut && len(a.Data) != 0 {
switch typ.Kind {
case sys.BufferString:
case BufferString:
s.strings[string(a.Data)] = true
case sys.BufferFilename:
case BufferFilename:
s.files[string(a.Data)] = true
}
}
@ -77,7 +77,7 @@ func (s *state) analyze(c *Call) {
}
flags := c.Args[3].(*ConstArg)
fd := c.Args[4].(*ResultArg)
if flags.Val&sys.MAP_ANONYMOUS == 0 && fd.Val == sys.InvalidFD {
if flags.Val&MAP_ANONYMOUS == 0 && fd.Val == InvalidFD {
break
}
s.addressable(c.Args[0].(*PointerArg), length, true)
@ -116,7 +116,7 @@ func foreachSubargImpl(arg Arg, parent *[]Arg, f func(arg, base Arg, parent *[]A
case *GroupArg:
for _, arg1 := range a.Inner {
parent1 := parent
if _, ok := arg.Type().(*sys.StructType); ok {
if _, ok := arg.Type().(*StructType); ok {
parent1 = &a.Inner
}
rec(arg1, base, parent1)
@ -197,15 +197,15 @@ func sanitizeCall(c *Call) {
if !ok {
panic("mmap flag arg is not const")
}
flags.Val |= sys.MAP_FIXED
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&sys.MREMAP_MAYMOVE != 0 {
flags.Val |= sys.MREMAP_FIXED
if flags.Val&MREMAP_MAYMOVE != 0 {
flags.Val |= MREMAP_FIXED
}
case "mknod", "mknodat":
mode, ok1 := c.Args[1].(*ConstArg)
@ -219,37 +219,37 @@ func sanitizeCall(c *Call) {
}
// 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 & (sys.S_IFREG | sys.S_IFCHR | sys.S_IFBLK | sys.S_IFIFO | sys.S_IFSOCK) {
case sys.S_IFREG, sys.S_IFIFO, sys.S_IFSOCK:
case sys.S_IFBLK:
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 &^= sys.S_IFBLK
mode.Val |= sys.S_IFREG
case sys.S_IFCHR:
mode.Val &^= sys.S_IFCHR
mode.Val |= sys.S_IFREG
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 == sys.SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == sys.SYSLOG_ACTION_CONSOLE_ON {
cmd.Val = sys.SYSLOG_ACTION_SIZE_UNREAD
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) == sys.FIFREEZE {
cmd.Val = sys.FITHAW
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 == sys.PTRACE_TRACEME {
if req.Val == PTRACE_TRACEME {
req.Val = ^uint64(0)
}
case "exit", "exit_group":
@ -279,7 +279,7 @@ func RequiresChecksums(p *Prog) bool {
result := false
for _, c := range p.Calls {
foreachArg(c, func(arg, _ Arg, _ *[]Arg) {
if _, ok := arg.Type().(*sys.CsumType); ok {
if _, ok := arg.Type().(*CsumType); ok {
result = true
}
})

View File

@ -6,13 +6,7 @@ package prog
import (
"fmt"
"github.com/google/syzkaller/sys"
)
type CsumKind int
const (
CsumInet CsumKind = iota
. "github.com/google/syzkaller/sys"
)
type CsumChunkKind int
@ -87,7 +81,7 @@ func composePseudoCsumIPv6(tcpPacket, srcAddr, dstAddr Arg, protocol uint8, pid
return info
}
func findCsummedArg(arg Arg, typ *sys.CsumType, parentsMap map[Arg]Arg) Arg {
func findCsummedArg(arg Arg, typ *CsumType, parentsMap map[Arg]Arg) Arg {
if typ.Buf == "parent" {
if csummedArg, ok := parentsMap[arg]; ok {
return csummedArg
@ -109,11 +103,11 @@ func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
// Find all csum fields.
foreachArgArray(&c.Args, nil, func(arg, base Arg, _ *[]Arg) {
if typ, ok := arg.Type().(*sys.CsumType); ok {
if typ, ok := arg.Type().(*CsumType); ok {
switch typ.Kind {
case sys.CsumInet:
case CsumInet:
inetCsumFields = append(inetCsumFields, arg)
case sys.CsumPseudo:
case CsumPseudo:
pseudoCsumFields = append(pseudoCsumFields, arg)
default:
panic(fmt.Sprintf("unknown csum kind %v\n", typ.Kind))
@ -129,7 +123,7 @@ func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
// Build map of each field to its parent struct.
parentsMap := make(map[Arg]Arg)
foreachArgArray(&c.Args, nil, func(arg, base Arg, _ *[]Arg) {
if _, ok := arg.Type().(*sys.StructType); ok {
if _, ok := arg.Type().(*StructType); ok {
for _, field := range arg.(*GroupArg).Inner {
parentsMap[InnerArg(field)] = arg
}
@ -140,7 +134,7 @@ func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
// Calculate generic inet checksums.
for _, arg := range inetCsumFields {
typ, _ := arg.Type().(*sys.CsumType)
typ, _ := arg.Type().(*CsumType)
csummedArg := findCsummedArg(arg, typ, parentsMap)
chunk := CsumChunk{CsumChunkArg, csummedArg, 0, 0}
info := CsumInfo{Kind: CsumInet, Chunks: make([]CsumChunk, 0)}
@ -175,7 +169,7 @@ func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
// Calculate pseudo checksums.
for _, arg := range pseudoCsumFields {
typ, _ := arg.Type().(*sys.CsumType)
typ, _ := arg.Type().(*CsumType)
csummedArg := findCsummedArg(arg, typ, parentsMap)
protocol := uint8(typ.Protocol)
var info CsumInfo

View File

@ -11,7 +11,7 @@ import (
"io"
"strconv"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
// String generates a very compact program description (mostly for debug output).
@ -43,7 +43,7 @@ func (p *Prog) Serialize() []byte {
}
fmt.Fprintf(buf, "%v(", c.Meta.Name)
for i, a := range c.Args {
if sys.IsPad(a.Type()) {
if IsPad(a.Type()) {
continue
}
if i != 0 {
@ -81,16 +81,16 @@ func serialize(arg Arg, buf io.Writer, vars map[Arg]int, varSeq *int) {
case *GroupArg:
var delims []byte
switch arg.Type().(type) {
case *sys.StructType:
case *StructType:
delims = []byte{'{', '}'}
case *sys.ArrayType:
case *ArrayType:
delims = []byte{'[', ']'}
default:
panic("unknown group type")
}
buf.Write([]byte{delims[0]})
for i, arg1 := range a.Inner {
if arg1 != nil && sys.IsPad(arg1.Type()) {
if arg1 != nil && IsPad(arg1.Type()) {
continue
}
if i != 0 {
@ -140,7 +140,7 @@ func Deserialize(data []byte) (prog *Prog, err error) {
name = p.Ident()
}
meta := sys.SyscallMap[name]
meta := SyscallMap[name]
if meta == nil {
return nil, fmt.Errorf("unknown syscall %v", name)
}
@ -155,7 +155,7 @@ func Deserialize(data []byte) (prog *Prog, err error) {
return nil, fmt.Errorf("wrong call arg count: %v, want %v", i+1, len(meta.Args))
}
typ := meta.Args[i]
if sys.IsPad(typ) {
if IsPad(typ) {
return nil, fmt.Errorf("padding in syscall %v arguments", name)
}
arg, err := parseArg(typ, p, vars)
@ -195,7 +195,7 @@ func Deserialize(data []byte) (prog *Prog, err error) {
return
}
func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
func parseArg(typ Type, p *parser, vars map[string]Arg) (Arg, error) {
r := ""
if p.Char() == '<' {
p.Parse('<')
@ -212,13 +212,13 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
return nil, fmt.Errorf("wrong arg value '%v': %v", val, err)
}
switch typ.(type) {
case *sys.ConstType, *sys.IntType, *sys.FlagsType, *sys.ProcType, *sys.LenType, *sys.CsumType:
case *ConstType, *IntType, *FlagsType, *ProcType, *LenType, *CsumType:
arg = constArg(typ, v)
case *sys.ResourceType:
case *ResourceType:
arg = resultArg(typ, nil, v)
case *sys.PtrType:
case *PtrType:
arg = pointerArg(typ, 0, 0, 0, nil)
case *sys.VmaType:
case *VmaType:
arg = pointerArg(typ, 0, 0, 0, nil)
default:
return nil, fmt.Errorf("bad const type %+v", typ)
@ -249,11 +249,11 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
arg.(*ResultArg).OpAdd = v
}
case '&':
var typ1 sys.Type
var typ1 Type
switch t1 := typ.(type) {
case *sys.PtrType:
case *PtrType:
typ1 = t1.Type
case *sys.VmaType:
case *VmaType:
default:
return nil, fmt.Errorf("& arg is not a pointer: %#v", typ)
}
@ -289,7 +289,7 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
}
arg = dataArg(typ, data)
case '{':
t1, ok := typ.(*sys.StructType)
t1, ok := typ.(*StructType)
if !ok {
return nil, fmt.Errorf("'{' arg is not a struct: %#v", typ)
}
@ -300,7 +300,7 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
return nil, fmt.Errorf("wrong struct arg count: %v, want %v", i+1, len(t1.Fields))
}
fld := t1.Fields[i]
if sys.IsPad(fld) {
if IsPad(fld) {
inner = append(inner, constArg(fld, 0))
} else {
arg, err := parseArg(fld, p, vars)
@ -319,7 +319,7 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
}
arg = groupArg(typ, inner)
case '[':
t1, ok := typ.(*sys.ArrayType)
t1, ok := typ.(*ArrayType)
if !ok {
return nil, fmt.Errorf("'[' arg is not an array: %#v", typ)
}
@ -338,14 +338,14 @@ func parseArg(typ sys.Type, p *parser, vars map[string]Arg) (Arg, error) {
p.Parse(']')
arg = groupArg(typ, inner)
case '@':
t1, ok := typ.(*sys.UnionType)
t1, ok := typ.(*UnionType)
if !ok {
return nil, fmt.Errorf("'@' arg is not a union: %#v", typ)
}
p.Parse('@')
name := p.Ident()
p.Parse('=')
var optType sys.Type
var optType Type
for _, t2 := range t1.Fields {
if name == t2.FieldName() {
optType = t2

View File

@ -10,7 +10,7 @@ import (
"fmt"
"sort"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
const (
@ -110,7 +110,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
if a1, ok := arg1.(*DataArg); ok && len(a1.Data) == 0 {
return
}
if !sys.IsPad(arg1.Type()) && arg1.Type().Dir() != sys.DirOut {
if !IsPad(arg1.Type()) && arg1.Type().Dir() != DirOut {
w.write(ExecInstrCopyin)
w.write(physicalAddr(arg) + offset)
w.writeArg(arg1, pid, csumMap)
@ -129,7 +129,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
sort.Sort(ByPhysicalAddr{Args: csumArgs, Context: w})
for i := len(csumArgs) - 1; i >= 0; i-- {
arg := csumArgs[i]
if _, ok := arg.Type().(*sys.CsumType); !ok {
if _, ok := arg.Type().(*CsumType); !ok {
panic("csum arg is not csum type")
}
w.write(ExecInstrCopyin)

View File

@ -9,7 +9,7 @@ import (
"fmt"
"testing"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
const ptrSize = 8
@ -47,7 +47,7 @@ func TestSerializeForExec(t *testing.T) {
argData = uint64(ExecArgData)
)
callID := func(name string) uint64 {
c := sys.SyscallMap[name]
c := SyscallMap[name]
if c == nil {
t.Fatalf("unknown syscall %v", name)
}

View File

@ -21,7 +21,7 @@ package prog
import (
"encoding/binary"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
type uint64Set map[uint64]bool
@ -110,7 +110,7 @@ func checkConstArg(arg *ConstArg, compMap CompMap, cb func(newArg Arg)) {
}
func checkDataArg(arg *DataArg, compMap CompMap, cb func(newArg Arg)) {
if arg.Type().Dir() != sys.DirIn && arg.Type().Dir() != sys.DirInOut {
if arg.Type().Dir() != DirIn && arg.Type().Dir() != DirInOut {
// We only want to scan userspace->kernel data.
return
}

View File

@ -8,7 +8,7 @@ import (
"reflect"
"testing"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
type ConstArgTest struct {
@ -157,8 +157,8 @@ func TestHintsCheckDataArg(t *testing.T) {
t.Run(fmt.Sprintf("%v", test.name), func(t *testing.T) {
res := make(map[string]bool)
// Whatever type here. It's just needed to pass the
// dataArg.Type().Dir() == sys.DirIn check.
typ := sys.ArrayType{sys.TypeCommon{"", "", 0, sys.DirIn, false}, nil, 0, 0, 0}
// dataArg.Type().Dir() == DirIn check.
typ := ArrayType{TypeCommon{"", "", 0, DirIn, false}, nil, 0, 0, 0}
argCommon := ArgCommon{&typ}
dataArg := &DataArg{argCommon, []byte(test.in)}
checkDataArg(dataArg, test.comps, func(arg Arg) {

View File

@ -8,7 +8,7 @@ import (
"math/rand"
"unsafe"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Prog) {
@ -79,7 +79,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
baseSize = b.Res.Size()
}
switch t := arg.Type().(type) {
case *sys.IntType, *sys.FlagsType:
case *IntType, *FlagsType:
a := arg.(*ConstArg)
if r.bin() {
arg1, calls1 := r.generateArg(s, arg.Type())
@ -94,23 +94,23 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
a.Val ^= 1 << uint64(r.Intn(64))
}
}
case *sys.ResourceType, *sys.VmaType, *sys.ProcType:
case *ResourceType, *VmaType, *ProcType:
arg1, calls1 := r.generateArg(s, arg.Type())
p.replaceArg(c, arg, arg1, calls1)
case *sys.BufferType:
case *BufferType:
a := arg.(*DataArg)
switch t.Kind {
case sys.BufferBlobRand, sys.BufferBlobRange:
case BufferBlobRand, BufferBlobRange:
var data []byte
data = append([]byte{}, a.Data...)
var minLen uint64
maxLen := ^uint64(0)
if t.Kind == sys.BufferBlobRange {
if t.Kind == BufferBlobRange {
minLen = t.RangeBegin
maxLen = t.RangeEnd
}
a.Data = mutateData(r, data, minLen, maxLen)
case sys.BufferString:
case BufferString:
if r.bin() {
minLen, maxLen := uint64(0), ^uint64(0)
if t.TypeSize != 0 {
@ -120,22 +120,22 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
} else {
a.Data = r.randString(s, t.Values, t.Dir())
}
case sys.BufferFilename:
case BufferFilename:
a.Data = []byte(r.filename(s))
case sys.BufferText:
case BufferText:
a.Data = r.mutateText(t.Text, a.Data)
default:
panic("unknown buffer kind")
}
case *sys.ArrayType:
case *ArrayType:
a := arg.(*GroupArg)
count := uint64(0)
switch t.Kind {
case sys.ArrayRandLen:
case ArrayRandLen:
for count == uint64(len(a.Inner)) {
count = r.randArrayLen()
}
case sys.ArrayRangeLen:
case ArrayRangeLen:
if t.RangeBegin == t.RangeEnd {
panic("trying to mutate fixed length array")
}
@ -165,7 +165,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
a.Inner = a.Inner[:count]
}
// TODO: swap elements of the array
case *sys.PtrType:
case *PtrType:
a, ok := arg.(*PointerArg)
if !ok {
break
@ -177,7 +177,7 @@ 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 *sys.StructType:
case *StructType:
ctor := isSpecialStruct(t)
if ctor == nil {
panic("bad arg returned by mutationArgs: StructType")
@ -187,7 +187,7 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
p.replaceArg(c, arg.(*GroupArg).Inner[i], f, calls1)
calls1 = nil
}
case *sys.UnionType:
case *UnionType:
a := arg.(*UnionArg)
optType := t.Fields[r.Intn(len(t.Fields))]
maxIters := 1000
@ -201,11 +201,11 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro
opt, calls := r.generateArg(s, optType)
arg1 := unionArg(t, opt, optType)
p.replaceArg(c, arg, arg1, calls)
case *sys.LenType:
case *LenType:
panic("bad arg returned by mutationArgs: LenType")
case *sys.CsumType:
case *CsumType:
panic("bad arg returned by mutationArgs: CsumType")
case *sys.ConstType:
case *ConstType:
panic("bad arg returned by mutationArgs: ConstType")
default:
panic(fmt.Sprintf("bad arg returned by mutationArgs: %#v, type=%#v", arg, arg.Type()))
@ -326,19 +326,19 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
rec = func(p *Prog, call *Call, arg Arg, path string) bool {
path += fmt.Sprintf("-%v", arg.Type().FieldName())
switch typ := arg.Type().(type) {
case *sys.StructType:
case *StructType:
a := arg.(*GroupArg)
for _, innerArg := range a.Inner {
if rec(p, call, innerArg, path) {
return true
}
}
case *sys.UnionType:
case *UnionType:
a := arg.(*UnionArg)
if rec(p, call, a.Option, path) {
return true
}
case *sys.PtrType:
case *PtrType:
// TODO: try to remove optional ptrs
a, ok := arg.(*PointerArg)
if !ok {
@ -348,13 +348,13 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
if a.Res != nil {
return rec(p, call, a.Res, path)
}
case *sys.ArrayType:
case *ArrayType:
a := arg.(*GroupArg)
for i, innerArg := range a.Inner {
innerPath := fmt.Sprintf("%v-%v", path, i)
if !triedPaths[innerPath] && !crash {
if (typ.Kind == sys.ArrayRangeLen && len(a.Inner) > int(typ.RangeBegin)) ||
(typ.Kind == sys.ArrayRandLen) {
if (typ.Kind == ArrayRangeLen && len(a.Inner) > int(typ.RangeBegin)) ||
(typ.Kind == ArrayRandLen) {
copy(a.Inner[i:], a.Inner[i+1:])
a.Inner = a.Inner[:len(a.Inner)-1]
p.removeArg(call, innerArg)
@ -373,7 +373,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
return true
}
}
case *sys.IntType, *sys.FlagsType, *sys.ProcType:
case *IntType, *FlagsType, *ProcType:
// TODO: try to reset bits in ints
// TODO: try to set separate flags
if crash {
@ -395,7 +395,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
} else {
a.Val = v0
}
case *sys.ResourceType:
case *ResourceType:
if crash {
return false
}
@ -417,13 +417,13 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
a.Res = r0
a.Val = 0
}
case *sys.BufferType:
case *BufferType:
// TODO: try to set individual bytes to 0
if triedPaths[path] {
return false
}
triedPaths[path] = true
if typ.Kind != sys.BufferBlobRand && typ.Kind != sys.BufferBlobRange {
if typ.Kind != BufferBlobRand && typ.Kind != BufferBlobRange {
return false
}
a := arg.(*DataArg)
@ -444,7 +444,7 @@ func Minimize(p0 *Prog, callIndex0 int, pred func(*Prog, int) bool, crash bool)
}
}
p0 = p
case *sys.VmaType, *sys.LenType, *sys.CsumType, *sys.ConstType:
case *VmaType, *LenType, *CsumType, *ConstType:
// TODO: try to remove offset from vma
return false
default:
@ -495,36 +495,36 @@ func (p *Prog) TrimAfter(idx int) {
func mutationArgs(c *Call) (args, bases []Arg) {
foreachArg(c, func(arg, base Arg, _ *[]Arg) {
switch typ := arg.Type().(type) {
case *sys.StructType:
case *StructType:
if isSpecialStruct(typ) == nil {
// For structs only individual fields are updated.
return
}
// These special structs are mutated as a whole.
case *sys.ArrayType:
case *ArrayType:
// Don't mutate fixed-size arrays.
if typ.Kind == sys.ArrayRangeLen && typ.RangeBegin == typ.RangeEnd {
if typ.Kind == ArrayRangeLen && typ.RangeBegin == typ.RangeEnd {
return
}
case *sys.LenType:
case *LenType:
// Size is updated when the size-of arg change.
return
case *sys.CsumType:
case *CsumType:
// Checksum is updated when the checksummed data changes.
return
case *sys.ConstType:
case *ConstType:
// Well, this is const.
return
case *sys.BufferType:
if typ.Kind == sys.BufferString && len(typ.Values) == 1 {
case *BufferType:
if typ.Kind == BufferString && len(typ.Values) == 1 {
return // string const
}
}
if arg.Type().Dir() == sys.DirOut {
if arg.Type().Dir() == DirOut {
return
}
if base != nil {
if _, ok := base.Type().(*sys.StructType); ok && isSpecialStruct(base.Type()) != nil {
if _, ok := base.Type().(*StructType); ok && isSpecialStruct(base.Type()) != nil {
// These special structs are mutated as a whole.
return
}

View File

@ -8,7 +8,7 @@ import (
"math/rand"
"sort"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
// Calulation of call-to-call priorities.
@ -39,7 +39,7 @@ func CalculatePriorities(corpus []*Prog) [][]float32 {
func calcStaticPriorities() [][]float32 {
uses := make(map[string]map[int]float32)
for _, c := range sys.Syscalls {
for _, c := range Syscalls {
noteUsage := func(weight float32, str string, args ...interface{}) {
id := fmt.Sprintf(str, args...)
if uses[id] == nil {
@ -50,9 +50,9 @@ func calcStaticPriorities() [][]float32 {
uses[id][c.ID] = weight
}
}
sys.ForeachType(c, func(t sys.Type) {
ForeachType(c, func(t Type) {
switch a := t.(type) {
case *sys.ResourceType:
case *ResourceType:
if a.Desc.Name == "pid" || a.Desc.Name == "uid" || a.Desc.Name == "gid" {
// Pid/uid/gid usually play auxiliary role,
// but massively happen in some structs.
@ -68,42 +68,42 @@ func calcStaticPriorities() [][]float32 {
noteUsage(float32(w), str)
}
}
case *sys.PtrType:
if _, ok := a.Type.(*sys.StructType); ok {
case *PtrType:
if _, ok := a.Type.(*StructType); ok {
noteUsage(1.0, "ptrto-%v", a.Type.Name())
}
if _, ok := a.Type.(*sys.UnionType); ok {
if _, ok := a.Type.(*UnionType); ok {
noteUsage(1.0, "ptrto-%v", a.Type.Name())
}
if arr, ok := a.Type.(*sys.ArrayType); ok {
if arr, ok := a.Type.(*ArrayType); ok {
noteUsage(1.0, "ptrto-%v", arr.Type.Name())
}
case *sys.BufferType:
case *BufferType:
switch a.Kind {
case sys.BufferBlobRand, sys.BufferBlobRange, sys.BufferText:
case sys.BufferString:
case BufferBlobRand, BufferBlobRange, BufferText:
case BufferString:
if a.SubKind != "" {
noteUsage(0.2, fmt.Sprintf("str-%v", a.SubKind))
}
case sys.BufferFilename:
case BufferFilename:
noteUsage(1.0, "filename")
default:
panic("unknown buffer kind")
}
case *sys.VmaType:
case *VmaType:
noteUsage(0.5, "vma")
case *sys.IntType:
case *IntType:
switch a.Kind {
case sys.IntPlain, sys.IntFileoff, sys.IntRange:
case IntPlain, IntFileoff, IntRange:
default:
panic("unknown int kind")
}
}
})
}
prios := make([][]float32, len(sys.Syscalls))
prios := make([][]float32, len(Syscalls))
for i := range prios {
prios[i] = make([]float32, len(sys.Syscalls))
prios[i] = make([]float32, len(Syscalls))
}
for _, calls := range uses {
for c0, w0 := range calls {
@ -133,9 +133,9 @@ func calcStaticPriorities() [][]float32 {
}
func calcDynamicPrio(corpus []*Prog) [][]float32 {
prios := make([][]float32, len(sys.Syscalls))
prios := make([][]float32, len(Syscalls))
for i := range prios {
prios[i] = make([]float32, len(sys.Syscalls))
prios[i] = make([]float32, len(Syscalls))
}
for _, p := range corpus {
for _, c0 := range p.Calls {
@ -196,30 +196,30 @@ func normalizePrio(prios [][]float32) {
// based on call-to-call priorities and a set of enabled syscalls.
type ChoiceTable struct {
run [][]int
enabledCalls []*sys.Syscall
enabled map[*sys.Syscall]bool
enabledCalls []*Syscall
enabled map[*Syscall]bool
}
func BuildChoiceTable(prios [][]float32, enabled map[*sys.Syscall]bool) *ChoiceTable {
func BuildChoiceTable(prios [][]float32, enabled map[*Syscall]bool) *ChoiceTable {
if enabled == nil {
enabled = make(map[*sys.Syscall]bool)
for _, c := range sys.Syscalls {
enabled = make(map[*Syscall]bool)
for _, c := range Syscalls {
enabled[c] = true
}
}
var enabledCalls []*sys.Syscall
var enabledCalls []*Syscall
for c := range enabled {
enabledCalls = append(enabledCalls, c)
}
run := make([][]int, len(sys.Syscalls))
run := make([][]int, len(Syscalls))
for i := range run {
if !enabled[sys.Syscalls[i]] {
if !enabled[Syscalls[i]] {
continue
}
run[i] = make([]int, len(sys.Syscalls))
run[i] = make([]int, len(Syscalls))
sum := 0
for j := range run[i] {
if enabled[sys.Syscalls[j]] {
if enabled[Syscalls[j]] {
sum += int(prios[i][j] * 1000)
}
run[i][j] = sum
@ -230,7 +230,7 @@ func BuildChoiceTable(prios [][]float32, enabled map[*sys.Syscall]bool) *ChoiceT
func (ct *ChoiceTable) Choose(r *rand.Rand, call int) int {
if ct == nil {
return r.Intn(len(sys.Syscalls))
return r.Intn(len(Syscalls))
}
if call < 0 {
return ct.enabledCalls[r.Intn(len(ct.enabledCalls))].ID
@ -242,7 +242,7 @@ func (ct *ChoiceTable) Choose(r *rand.Rand, call int) int {
for {
x := r.Intn(run[len(run)-1])
i := sort.SearchInts(run, x)
if !ct.enabled[sys.Syscalls[i]] {
if !ct.enabled[Syscalls[i]] {
continue
}
return i

View File

@ -6,7 +6,7 @@ package prog
import (
"fmt"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
type Prog struct {
@ -14,21 +14,21 @@ type Prog struct {
}
type Call struct {
Meta *sys.Syscall
Meta *Syscall
Args []Arg
Ret Arg
}
type Arg interface {
Type() sys.Type
Type() Type
Size() uint64
}
type ArgCommon struct {
typ sys.Type
typ Type
}
func (arg *ArgCommon) Type() sys.Type {
func (arg *ArgCommon) Type() Type {
return arg.typ
}
@ -45,24 +45,24 @@ func (arg *ConstArg) Size() uint64 {
// Returns value taking endianness and executor pid into consideration.
func (arg *ConstArg) Value(pid int) uint64 {
switch typ := (*arg).Type().(type) {
case *sys.IntType:
case *IntType:
return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
case *sys.ConstType:
case *ConstType:
return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
case *sys.FlagsType:
case *FlagsType:
return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
case *sys.LenType:
case *LenType:
return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
case *sys.CsumType:
case *CsumType:
// Checksums are computed dynamically in executor.
return 0
case *sys.ResourceType:
if t, ok := typ.Desc.Type.(*sys.IntType); ok {
case *ResourceType:
if t, ok := typ.Desc.Type.(*IntType); ok {
return encodeValue(arg.Val, t.Size(), t.BigEndian)
} else {
panic(fmt.Sprintf("bad base type for a resource: %v", t))
}
case *sys.ProcType:
case *ProcType:
val := typ.ValuesStart + typ.ValuesPerProc*uint64(pid) + arg.Val
return encodeValue(val, typ.Size(), typ.BigEndian)
}
@ -107,7 +107,7 @@ func (arg *GroupArg) Size() uint64 {
return typ0.Size()
}
switch typ := typ0.(type) {
case *sys.StructType:
case *StructType:
var size uint64
for _, fld := range arg.Inner {
if !fld.Type().BitfieldMiddle() {
@ -118,7 +118,7 @@ func (arg *GroupArg) Size() uint64 {
size += typ.AlignAttr - size%typ.AlignAttr
}
return size
case *sys.ArrayType:
case *ArrayType:
var size uint64
for _, elem := range arg.Inner {
size += elem.Size()
@ -133,7 +133,7 @@ func (arg *GroupArg) Size() uint64 {
type UnionArg struct {
ArgCommon
Option Arg
OptionType sys.Type
OptionType Type
}
func (arg *UnionArg) Size() uint64 {
@ -192,7 +192,7 @@ func (arg *ResultArg) Uses() *Arg {
// Returns inner arg for pointer args.
func InnerArg(arg Arg) Arg {
if t, ok := arg.Type().(*sys.PtrType); ok {
if t, ok := arg.Type().(*PtrType); ok {
if a, ok := arg.(*PointerArg); ok {
if a.Res == nil {
if !t.Optional() {
@ -224,11 +224,11 @@ func encodeValue(value uint64, size uint64, bigEndian bool) uint64 {
}
}
func constArg(t sys.Type, v uint64) Arg {
func constArg(t Type, v uint64) Arg {
return &ConstArg{ArgCommon: ArgCommon{typ: t}, Val: v}
}
func resultArg(t sys.Type, r Arg, v uint64) Arg {
func resultArg(t Type, r Arg, v uint64) Arg {
arg := &ResultArg{ArgCommon: ArgCommon{typ: t}, Res: r, Val: v}
if r == nil {
return arg
@ -245,53 +245,53 @@ func resultArg(t sys.Type, r Arg, v uint64) Arg {
return arg
}
func dataArg(t sys.Type, data []byte) Arg {
func dataArg(t Type, data []byte) Arg {
return &DataArg{ArgCommon: ArgCommon{typ: t}, Data: append([]byte{}, data...)}
}
func pointerArg(t sys.Type, page uint64, off int, npages uint64, obj Arg) Arg {
func pointerArg(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 sys.Type, inner []Arg) Arg {
func groupArg(t Type, inner []Arg) Arg {
return &GroupArg{ArgCommon: ArgCommon{typ: t}, Inner: inner}
}
func unionArg(t sys.Type, opt Arg, typ sys.Type) Arg {
func unionArg(t Type, opt Arg, typ Type) Arg {
return &UnionArg{ArgCommon: ArgCommon{typ: t}, Option: opt, OptionType: typ}
}
func returnArg(t sys.Type) Arg {
func returnArg(t Type) Arg {
return &ReturnArg{ArgCommon: ArgCommon{typ: t}}
}
func defaultArg(t sys.Type) Arg {
func defaultArg(t Type) Arg {
switch typ := t.(type) {
case *sys.IntType, *sys.ConstType, *sys.FlagsType, *sys.LenType, *sys.ProcType, *sys.CsumType:
case *IntType, *ConstType, *FlagsType, *LenType, *ProcType, *CsumType:
return constArg(t, t.Default())
case *sys.ResourceType:
case *ResourceType:
return resultArg(t, nil, typ.Desc.Type.Default())
case *sys.BufferType:
case *BufferType:
var data []byte
if typ.Kind == sys.BufferString && typ.TypeSize != 0 {
if typ.Kind == BufferString && typ.TypeSize != 0 {
data = make([]byte, typ.TypeSize)
}
return dataArg(t, data)
case *sys.ArrayType:
case *ArrayType:
return groupArg(t, nil)
case *sys.StructType:
case *StructType:
var inner []Arg
for _, field := range typ.Fields {
inner = append(inner, defaultArg(field))
}
return groupArg(t, inner)
case *sys.UnionType:
case *UnionType:
return unionArg(t, defaultArg(typ.Fields[0]), typ.Fields[0])
case *sys.VmaType:
case *VmaType:
return pointerArg(t, 0, 0, 1, nil)
case *sys.PtrType:
case *PtrType:
var res Arg
if !t.Optional() && t.Dir() != sys.DirOut {
if !t.Optional() && t.Dir() != DirOut {
res = defaultArg(typ.Type)
}
return pointerArg(t, 0, 0, 0, res)

View File

@ -10,7 +10,7 @@ import (
"testing"
"time"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
func init() {
@ -38,7 +38,7 @@ func TestGeneration(t *testing.T) {
func TestDefault(t *testing.T) {
initTest(t)
for _, meta := range sys.SyscallMap {
for _, meta := range SyscallMap {
for _, t := range meta.Args {
defaultArg(t)
}
@ -47,7 +47,7 @@ func TestDefault(t *testing.T) {
func TestDefaultCallArgs(t *testing.T) {
initTest(t)
for _, meta := range sys.SyscallMap {
for _, meta := range SyscallMap {
// Ensure that we can restore all arguments of all calls.
prog := fmt.Sprintf("%v()", meta.Name)
p, err := Deserialize([]byte(prog))
@ -84,7 +84,7 @@ func TestSerialize(t *testing.T) {
func TestVmaType(t *testing.T) {
rs, iters := initTest(t)
meta := sys.SyscallMap["syz_test$vma0"]
meta := SyscallMap["syz_test$vma0"]
r := newRand(rs)
for i := 0; i < iters; i++ {
s := newState(nil)

View File

@ -12,7 +12,7 @@ import (
"sync"
"github.com/google/syzkaller/pkg/ifuzz"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
var pageStartPool = sync.Pool{New: func() interface{} { return new([]uint64) }}
@ -178,9 +178,9 @@ func (r *randGen) filename(s *state) string {
return files[r.Intn(len(files))]
}
func (r *randGen) randString(s *state, vals []string, dir sys.Dir) []byte {
func (r *randGen) randString(s *state, vals []string, dir Dir) []byte {
data := r.randStringImpl(s, vals)
if dir == sys.DirOut {
if dir == DirOut {
for i := range data {
data[i] = 0
}
@ -224,8 +224,8 @@ func (r *randGen) randStringImpl(s *state, vals []string) []byte {
return buf.Bytes()
}
func isSpecialStruct(typ sys.Type) func(r *randGen, s *state) (Arg, []*Call) {
a, ok := typ.(*sys.StructType)
func isSpecialStruct(typ Type) func(r *randGen, s *state) (Arg, []*Call) {
a, ok := typ.(*StructType)
if !ok {
panic("must be a struct")
}
@ -242,7 +242,7 @@ func isSpecialStruct(typ sys.Type) func(r *randGen, s *state) (Arg, []*Call) {
return nil
}
func (r *randGen) timespec(s *state, typ *sys.StructType, usec bool) (arg Arg, calls []*Call) {
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.
@ -271,9 +271,9 @@ func (r *randGen) timespec(s *state, typ *sys.StructType, usec bool) (arg Arg, c
})
default:
// few ms ahead for absolute
meta := sys.SyscallMap["clock_gettime"]
ptrArgType := meta.Args[1].(*sys.PtrType)
argType := ptrArgType.Type.(*sys.StructType)
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),
@ -283,7 +283,7 @@ func (r *randGen) timespec(s *state, typ *sys.StructType, usec bool) (arg Arg, c
gettime := &Call{
Meta: meta,
Args: []Arg{
constArg(meta.Args[0], sys.CLOCK_REALTIME),
constArg(meta.Args[0], CLOCK_REALTIME),
tpaddr,
},
Ret: returnArg(meta.Ret),
@ -304,15 +304,15 @@ func (r *randGen) timespec(s *state, typ *sys.StructType, usec bool) (arg Arg, c
// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
func createMmapCall(start, npages uint64) *Call {
meta := sys.SyscallMap["mmap"]
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], sys.PROT_READ|sys.PROT_WRITE),
constArg(meta.Args[3], sys.MAP_ANONYMOUS|sys.MAP_PRIVATE|sys.MAP_FIXED),
resultArg(meta.Args[4], nil, sys.InvalidFD),
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),
@ -320,7 +320,7 @@ func createMmapCall(start, npages uint64) *Call {
return mmap
}
func (r *randGen) addr1(s *state, typ sys.Type, size uint64, data Arg) (Arg, []*Call) {
func (r *randGen) addr1(s *state, typ Type, size uint64, data Arg) (Arg, []*Call) {
npages := (size + pageSize - 1) / pageSize
if npages == 0 {
npages = 1
@ -345,7 +345,7 @@ func (r *randGen) addr1(s *state, typ sys.Type, size uint64, data Arg) (Arg, []*
return r.randPageAddr(s, typ, npages, data, false), nil
}
func (r *randGen) addr(s *state, typ sys.Type, size uint64, data Arg) (Arg, []*Call) {
func (r *randGen) addr(s *state, typ Type, size uint64, data Arg) (Arg, []*Call) {
arg, calls := r.addr1(s, typ, size, data)
a, ok := arg.(*PointerArg)
if !ok {
@ -366,7 +366,7 @@ func (r *randGen) addr(s *state, typ sys.Type, size uint64, data Arg) (Arg, []*C
return arg, calls
}
func (r *randGen) randPageAddr(s *state, typ sys.Type, npages uint64, data Arg, vma bool) Arg {
func (r *randGen) randPageAddr(s *state, typ Type, npages uint64, data Arg, vma bool) Arg {
poolPtr := pageStartPool.Get().(*[]uint64)
starts := (*poolPtr)[:0]
for i := uint64(0); i < maxPages-npages; i++ {
@ -398,7 +398,7 @@ func (r *randGen) randPageAddr(s *state, typ sys.Type, npages uint64, data Arg,
return pointerArg(typ, page, 0, npages, data)
}
func (r *randGen) createResource(s *state, res *sys.ResourceType) (arg Arg, calls []*Call) {
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
@ -410,17 +410,17 @@ func (r *randGen) createResource(s *state, res *sys.ResourceType) (arg Arg, call
if r.oneOf(1000) {
// Spoof resource subkind.
var all []string
for kind1 := range sys.Resources {
if sys.IsCompatibleResource(res.Desc.Kind[0], kind1) {
for kind1 := range Resources {
if IsCompatibleResource(res.Desc.Kind[0], kind1) {
all = append(all, kind1)
}
}
kind = all[r.Intn(len(all))]
}
// Find calls that produce the necessary resources.
metas0 := sys.ResourceConstructors(kind)
metas0 := ResourceConstructors(kind)
// TODO: reduce priority of less specialized ctors.
var metas []*sys.Syscall
var metas []*Syscall
for _, meta := range metas0 {
if s.ct == nil || s.ct.run[meta.ID] == nil {
continue
@ -441,7 +441,7 @@ func (r *randGen) createResource(s *state, res *sys.ResourceType) (arg Arg, call
// Now see if we have what we want.
var allres []Arg
for kind1, res1 := range s1.resources {
if sys.IsCompatibleResource(kind, kind1) {
if IsCompatibleResource(kind, kind1) {
allres = append(allres, res1...)
}
}
@ -465,9 +465,9 @@ func (r *randGen) createResource(s *state, res *sys.ResourceType) (arg Arg, call
panic("failed to create a resource")
}
func (r *randGen) generateText(kind sys.TextKind) []byte {
func (r *randGen) generateText(kind TextKind) []byte {
switch kind {
case sys.Text_arm64:
case Text_arm64:
// Just a stub, need something better.
text := make([]byte, 50)
for i := range text {
@ -480,9 +480,9 @@ func (r *randGen) generateText(kind sys.TextKind) []byte {
}
}
func (r *randGen) mutateText(kind sys.TextKind, text []byte) []byte {
func (r *randGen) mutateText(kind TextKind, text []byte) []byte {
switch kind {
case sys.Text_arm64:
case Text_arm64:
return mutateData(r, text, 40, 60)
default:
cfg := createIfuzzConfig(kind)
@ -490,7 +490,7 @@ func (r *randGen) mutateText(kind sys.TextKind, text []byte) []byte {
}
}
func createIfuzzConfig(kind sys.TextKind) *ifuzz.Config {
func createIfuzzConfig(kind TextKind) *ifuzz.Config {
cfg := &ifuzz.Config{
Len: 10,
Priv: true,
@ -510,13 +510,13 @@ func createIfuzzConfig(kind sys.TextKind) *ifuzz.Config {
},
}
switch kind {
case sys.Text_x86_real:
case Text_x86_real:
cfg.Mode = ifuzz.ModeReal16
case sys.Text_x86_16:
case Text_x86_16:
cfg.Mode = ifuzz.ModeProt16
case sys.Text_x86_32:
case Text_x86_32:
cfg.Mode = ifuzz.ModeProt32
case sys.Text_x86_64:
case Text_x86_64:
cfg.Mode = ifuzz.ModeLong64
}
return cfg
@ -543,11 +543,11 @@ func (r *randGen) generateCall(s *state, p *Prog) []*Call {
}
}
}
meta := sys.Syscalls[s.ct.Choose(r.Rand, call)]
meta := Syscalls[s.ct.Choose(r.Rand, call)]
return r.generateParticularCall(s, meta)
}
func (r *randGen) generateParticularCall(s *state, meta *sys.Syscall) (calls []*Call) {
func (r *randGen) generateParticularCall(s *state, meta *Syscall) (calls []*Call) {
c := &Call{
Meta: meta,
Ret: returnArg(meta.Ret),
@ -567,7 +567,7 @@ func GenerateAllSyzProg(rs rand.Source) *Prog {
r := newRand(rs)
s := newState(nil)
handled := make(map[string]bool)
for _, meta := range sys.Syscalls {
for _, meta := range Syscalls {
if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] {
continue
}
@ -584,7 +584,7 @@ func GenerateAllSyzProg(rs rand.Source) *Prog {
return p
}
func (r *randGen) generateArgs(s *state, types []sys.Type) ([]Arg, []*Call) {
func (r *randGen) generateArgs(s *state, types []Type) ([]Arg, []*Call) {
var calls []*Call
args := make([]Arg, len(types))
@ -601,15 +601,15 @@ func (r *randGen) generateArgs(s *state, types []sys.Type) ([]Arg, []*Call) {
return args, calls
}
func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
if typ.Dir() == sys.DirOut {
func (r *randGen) generateArg(s *state, typ Type) (arg Arg, calls []*Call) {
if typ.Dir() == DirOut {
// No need to generate something interesting for output scalar arguments.
// But we still need to generate the argument itself so that it can be referenced
// in subsequent calls. For the same reason we do generate pointer/array/struct
// output arguments (their elements can be referenced in subsequent calls).
switch typ.(type) {
case *sys.IntType, *sys.FlagsType, *sys.ConstType, *sys.ProcType,
*sys.VmaType, *sys.ResourceType:
case *IntType, *FlagsType, *ConstType, *ProcType,
*VmaType, *ResourceType:
return defaultArg(typ), nil
}
}
@ -619,8 +619,8 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
}
// Allow infinite recursion for optional pointers.
if pt, ok := typ.(*sys.PtrType); ok && typ.Optional() {
if str, ok := pt.Type.(*sys.StructType); ok {
if pt, ok := typ.(*PtrType); ok && typ.Optional() {
if str, ok := pt.Type.(*StructType); ok {
r.recDepth[str.Name()] += 1
defer func() {
r.recDepth[str.Name()] -= 1
@ -635,7 +635,7 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
}
switch a := typ.(type) {
case *sys.ResourceType:
case *ResourceType:
switch {
case r.nOutOf(1000, 1011):
// Get an existing resource.
@ -644,8 +644,8 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
if name1 == "iocbptr" {
continue
}
if sys.IsCompatibleResource(a.Desc.Name, name1) ||
r.oneOf(20) && sys.IsCompatibleResource(a.Desc.Kind[0], name1) {
if IsCompatibleResource(a.Desc.Name, name1) ||
r.oneOf(20) && IsCompatibleResource(a.Desc.Kind[0], name1) {
allres = append(allres, res1...)
}
}
@ -662,26 +662,26 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
arg = resultArg(a, nil, special[r.Intn(len(special))])
}
return arg, calls
case *sys.BufferType:
case *BufferType:
switch a.Kind {
case sys.BufferBlobRand, sys.BufferBlobRange:
case BufferBlobRand, BufferBlobRange:
sz := r.randBufLen()
if a.Kind == sys.BufferBlobRange {
if a.Kind == BufferBlobRange {
sz = r.randRange(a.RangeBegin, a.RangeEnd)
}
data := make([]byte, sz)
if a.Dir() != sys.DirOut {
if a.Dir() != DirOut {
for i := range data {
data[i] = byte(r.Intn(256))
}
}
return dataArg(a, data), nil
case sys.BufferString:
case BufferString:
data := r.randString(s, a.Values, a.Dir())
return dataArg(a, data), nil
case sys.BufferFilename:
case BufferFilename:
var data []byte
if a.Dir() == sys.DirOut {
if a.Dir() == DirOut {
switch {
case r.nOutOf(1, 3):
data = make([]byte, r.Intn(100))
@ -694,26 +694,26 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
data = []byte(r.filename(s))
}
return dataArg(a, data), nil
case sys.BufferText:
case BufferText:
return dataArg(a, r.generateText(a.Text)), nil
default:
panic("unknown buffer kind")
}
case *sys.VmaType:
case *VmaType:
npages := r.randPageCount()
if a.RangeBegin != 0 || a.RangeEnd != 0 {
npages = a.RangeBegin + uint64(r.Intn(int(a.RangeEnd-a.RangeBegin+1)))
}
arg := r.randPageAddr(s, a, npages, nil, true)
return arg, nil
case *sys.FlagsType:
case *FlagsType:
return constArg(a, r.flags(a.Vals)), nil
case *sys.ConstType:
case *ConstType:
return constArg(a, a.Val), nil
case *sys.IntType:
case *IntType:
v := r.randInt()
switch a.Kind {
case sys.IntFileoff:
case IntFileoff:
switch {
case r.nOutOf(90, 101):
v = 0
@ -722,18 +722,18 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
default:
v = r.randInt()
}
case sys.IntRange:
case IntRange:
v = r.randRangeInt(a.RangeBegin, a.RangeEnd)
}
return constArg(a, v), nil
case *sys.ProcType:
case *ProcType:
return constArg(a, r.rand(int(a.ValuesPerProc))), nil
case *sys.ArrayType:
case *ArrayType:
var count uint64
switch a.Kind {
case sys.ArrayRandLen:
case ArrayRandLen:
count = r.randArrayLen()
case sys.ArrayRangeLen:
case ArrayRangeLen:
count = r.randRange(a.RangeBegin, a.RangeEnd)
}
var inner []Arg
@ -744,19 +744,19 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
calls = append(calls, calls1...)
}
return groupArg(a, inner), calls
case *sys.StructType:
if ctor := isSpecialStruct(a); ctor != nil && a.Dir() != sys.DirOut {
case *StructType:
if ctor := isSpecialStruct(a); ctor != nil && a.Dir() != DirOut {
arg, calls = ctor(r, s)
return
}
args, calls := r.generateArgs(s, a.Fields)
group := groupArg(a, args)
return group, calls
case *sys.UnionType:
case *UnionType:
optType := a.Fields[r.Intn(len(a.Fields))]
opt, calls := r.generateArg(s, optType)
return unionArg(a, opt, optType), calls
case *sys.PtrType:
case *PtrType:
inner, calls := r.generateArg(s, a.Type)
if a.Type.Name() == "iocb" && len(s.resources["iocbptr"]) != 0 {
// It is weird, but these are actually identified by kernel by address.
@ -769,10 +769,10 @@ func (r *randGen) generateArg(s *state, typ sys.Type) (arg Arg, calls []*Call) {
arg, calls1 := r.addr(s, a, inner.Size(), inner)
calls = append(calls, calls1...)
return arg, calls
case *sys.LenType:
case *LenType:
// Return placeholder value of 0 while generating len arg.
return constArg(a, 0), nil
case *sys.CsumType:
case *CsumType:
return constArg(a, 0), nil
default:
panic("unknown argument type")

View File

@ -6,20 +6,20 @@ package prog
import (
"fmt"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
func generateSize(arg Arg, lenType *sys.LenType) Arg {
func generateSize(arg Arg, lenType *LenType) Arg {
if arg == nil {
// Arg is an optional pointer, set size to 0.
return constArg(lenType, 0)
}
switch arg.Type().(type) {
case *sys.VmaType:
case *VmaType:
a := arg.(*PointerArg)
return constArg(lenType, a.PagesNum*pageSize)
case *sys.ArrayType:
case *ArrayType:
a := arg.(*GroupArg)
if lenType.ByteSize != 0 {
return constArg(lenType, a.Size()/lenType.ByteSize)
@ -39,7 +39,7 @@ func assignSizes(args []Arg, parentsMap map[Arg]Arg) {
// Create a map from field names to args.
argsMap := make(map[string]Arg)
for _, arg := range args {
if sys.IsPad(arg.Type()) {
if IsPad(arg.Type()) {
continue
}
argsMap[arg.Type().FieldName()] = arg
@ -50,7 +50,7 @@ func assignSizes(args []Arg, parentsMap map[Arg]Arg) {
if arg = InnerArg(arg); arg == nil {
continue // Pointer to optional len field, no need to fill in value.
}
if typ, ok := arg.Type().(*sys.LenType); ok {
if typ, ok := arg.Type().(*LenType); ok {
a := arg.(*ConstArg)
buf, ok := argsMap[typ.Buf]
@ -91,7 +91,7 @@ func assignSizes(args []Arg, parentsMap map[Arg]Arg) {
func assignSizesArray(args []Arg) {
parentsMap := make(map[Arg]Arg)
foreachArgArray(&args, nil, func(arg, base Arg, _ *[]Arg) {
if _, ok := arg.Type().(*sys.StructType); ok {
if _, ok := arg.Type().(*StructType); ok {
for _, field := range arg.(*GroupArg).Inner {
parentsMap[InnerArg(field)] = arg
}
@ -99,7 +99,7 @@ func assignSizesArray(args []Arg) {
})
assignSizes(args, parentsMap)
foreachArgArray(&args, nil, func(arg, base Arg, _ *[]Arg) {
if _, ok := arg.Type().(*sys.StructType); ok {
if _, ok := arg.Type().(*StructType); ok {
assignSizes(arg.(*GroupArg).Inner, parentsMap)
}
})

View File

@ -6,7 +6,7 @@ package prog
import (
"fmt"
"github.com/google/syzkaller/sys"
. "github.com/google/syzkaller/sys"
)
var debug = false // enabled in tests
@ -58,12 +58,12 @@ func (c *Call) validate(ctx *validCtx) error {
if arg.Type() == nil {
return fmt.Errorf("syscall %v: no type", c.Meta.Name)
}
if arg.Type().Dir() == sys.DirOut {
if arg.Type().Dir() == DirOut {
switch a := arg.(type) {
case *ConstArg:
// We generate output len arguments, which makes sense since it can be
// a length of a variable-length array which is not known otherwise.
if _, ok := a.Type().(*sys.LenType); ok {
if _, ok := a.Type().(*LenType); ok {
break
}
if a.Val != 0 && a.Val != a.Type().Default() {
@ -78,40 +78,40 @@ func (c *Call) validate(ctx *validCtx) error {
}
}
switch typ1 := arg.Type().(type) {
case *sys.IntType:
case *IntType:
switch a := arg.(type) {
case *ConstArg:
if a.Type().Dir() == sys.DirOut && (a.Val != 0 && a.Val != a.Type().Default()) {
if a.Type().Dir() == DirOut && (a.Val != 0 && a.Val != a.Type().Default()) {
return fmt.Errorf("syscall %v: out int arg '%v' has bad const value %v", c.Meta.Name, a.Type().Name(), a.Val)
}
case *ReturnArg:
default:
return fmt.Errorf("syscall %v: int arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.ResourceType:
case *ResourceType:
switch a := arg.(type) {
case *ResultArg:
if a.Type().Dir() == sys.DirOut && (a.Val != 0 && a.Val != a.Type().Default()) {
if a.Type().Dir() == DirOut && (a.Val != 0 && a.Val != a.Type().Default()) {
return fmt.Errorf("syscall %v: out resource arg '%v' has bad const value %v", c.Meta.Name, a.Type().Name(), a.Val)
}
case *ReturnArg:
default:
return fmt.Errorf("syscall %v: fd arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.StructType, *sys.ArrayType:
case *StructType, *ArrayType:
switch arg.(type) {
case *GroupArg:
default:
return fmt.Errorf("syscall %v: struct/array arg '%v' has bad kind %#v",
c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.UnionType:
case *UnionType:
switch arg.(type) {
case *UnionArg:
default:
return fmt.Errorf("syscall %v: union arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.ProcType:
case *ProcType:
switch a := arg.(type) {
case *ConstArg:
if a.Val >= typ1.ValuesPerProc {
@ -120,11 +120,11 @@ func (c *Call) validate(ctx *validCtx) error {
default:
return fmt.Errorf("syscall %v: proc arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.BufferType:
case *BufferType:
switch a := arg.(type) {
case *DataArg:
switch typ1.Kind {
case sys.BufferString:
case BufferString:
if typ1.TypeSize != 0 && uint64(len(a.Data)) != typ1.TypeSize {
return fmt.Errorf("syscall %v: string arg '%v' has size %v, which should be %v",
c.Meta.Name, a.Type().Name(), len(a.Data), typ1.TypeSize)
@ -133,7 +133,7 @@ func (c *Call) validate(ctx *validCtx) error {
default:
return fmt.Errorf("syscall %v: buffer arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.CsumType:
case *CsumType:
switch a := arg.(type) {
case *ConstArg:
if a.Val != 0 {
@ -142,10 +142,10 @@ func (c *Call) validate(ctx *validCtx) error {
default:
return fmt.Errorf("syscall %v: csum arg '%v' has bad kind %v", c.Meta.Name, arg.Type().Name(), arg)
}
case *sys.PtrType:
case *PtrType:
switch a := arg.(type) {
case *PointerArg:
if a.Type().Dir() == sys.DirOut {
if a.Type().Dir() == DirOut {
return fmt.Errorf("syscall %v: pointer arg '%v' has output direction", c.Meta.Name, a.Type().Name())
}
if a.Res == nil && !a.Type().Optional() {
@ -159,14 +159,14 @@ func (c *Call) validate(ctx *validCtx) error {
case *ConstArg:
case *PointerArg:
switch t := a.Type().(type) {
case *sys.VmaType:
case *VmaType:
if a.Res != nil {
return fmt.Errorf("syscall %v: vma arg '%v' has data", c.Meta.Name, a.Type().Name())
}
if a.PagesNum == 0 && t.Dir() != sys.DirOut && !t.Optional() {
if a.PagesNum == 0 && t.Dir() != DirOut && !t.Optional() {
return fmt.Errorf("syscall %v: vma arg '%v' has size 0", c.Meta.Name, a.Type().Name())
}
case *sys.PtrType:
case *PtrType:
if a.Res != nil {
if err := checkArg(a.Res); err != nil {
return err
@ -180,14 +180,14 @@ func (c *Call) validate(ctx *validCtx) error {
}
case *DataArg:
switch typ1 := a.Type().(type) {
case *sys.ArrayType:
if typ2, ok := typ1.Type.(*sys.IntType); !ok || typ2.Size() != 1 {
case *ArrayType:
if typ2, ok := typ1.Type.(*IntType); !ok || typ2.Size() != 1 {
return fmt.Errorf("syscall %v: data arg '%v' should be an array", c.Meta.Name, a.Type().Name())
}
}
case *GroupArg:
switch typ1 := a.Type().(type) {
case *sys.StructType:
case *StructType:
if len(a.Inner) != len(typ1.Fields) {
return fmt.Errorf("syscall %v: struct arg '%v' has wrong number of fields: want %v, got %v", c.Meta.Name, a.Type().Name(), len(typ1.Fields), len(a.Inner))
}
@ -196,7 +196,7 @@ func (c *Call) validate(ctx *validCtx) error {
return err
}
}
case *sys.ArrayType:
case *ArrayType:
for _, arg1 := range a.Inner {
if err := checkArg(arg1); err != nil {
return err
@ -206,7 +206,7 @@ func (c *Call) validate(ctx *validCtx) error {
return fmt.Errorf("syscall %v: group arg '%v' has bad underlying type %+v", c.Meta.Name, arg.Type().Name(), arg.Type())
}
case *UnionArg:
typ1, ok := a.Type().(*sys.UnionType)
typ1, ok := a.Type().(*UnionType)
if !ok {
return fmt.Errorf("syscall %v: union arg '%v' has bad type", c.Meta.Name, a.Type().Name())
}
@ -225,7 +225,7 @@ func (c *Call) validate(ctx *validCtx) error {
}
case *ResultArg:
switch a.Type().(type) {
case *sys.ResourceType:
case *ResourceType:
default:
return fmt.Errorf("syscall %v: result arg '%v' has bad meta type %+v", c.Meta.Name, arg.Type().Name(), arg.Type())
}
@ -241,8 +241,8 @@ func (c *Call) validate(ctx *validCtx) error {
}
case *ReturnArg:
switch a.Type().(type) {
case *sys.ResourceType:
case *sys.VmaType:
case *ResourceType:
case *VmaType:
default:
return fmt.Errorf("syscall %v: result arg '%v' has bad meta type %+v", c.Meta.Name, arg.Type().Name(), arg.Type())
}