mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 11:29:46 +00:00
prog: dot-import sys
In preparation for moving sys types to prog to reduce later diffs.
This commit is contained in:
parent
5db39ab953
commit
4fc4702694
@ -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
|
||||
}
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
62
prog/prio.go
62
prog/prio.go
@ -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
|
||||
|
70
prog/prog.go
70
prog/prog.go
@ -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)
|
||||
|
@ -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)
|
||||
|
138
prog/rand.go
138
prog/rand.go
@ -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")
|
||||
|
16
prog/size.go
16
prog/size.go
@ -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)
|
||||
}
|
||||
})
|
||||
|
@ -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())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user