aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/decl.go522
-rw-r--r--sys/decl_test.go62
-rw-r--r--sys/init.go257
-rw-r--r--sys/sys_386.go6
-rw-r--r--sys/sys_amd64.go6
-rw-r--r--sys/sys_arm.go6
-rw-r--r--sys/sys_arm64.go6
-rw-r--r--sys/sys_ppc64le.go6
-rw-r--r--sys/syz-sysgen/syscallnr.go4
-rw-r--r--sys/syz-sysgen/sysgen.go5
10 files changed, 282 insertions, 598 deletions
diff --git a/sys/decl.go b/sys/decl.go
deleted file mode 100644
index 82d27e915..000000000
--- a/sys/decl.go
+++ /dev/null
@@ -1,522 +0,0 @@
-// Copyright 2015/2016 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package sys
-
-import (
- "fmt"
-)
-
-type Syscall struct {
- ID int
- NR uint64 // kernel syscall number
- Name string
- CallName string
- Args []Type
- Ret Type
-}
-
-type Dir int
-
-const (
- DirIn Dir = iota
- DirOut
- DirInOut
-)
-
-type Type interface {
- Name() string
- FieldName() string
- Dir() Dir
- Optional() bool
- Default() uint64
- Varlen() bool
- Size() uint64
- BitfieldOffset() uint64
- BitfieldLength() uint64
- BitfieldMiddle() bool // returns true for all but last bitfield in a group
-}
-
-func IsPad(t Type) bool {
- if ct, ok := t.(*ConstType); ok && ct.IsPad {
- return true
- }
- return false
-}
-
-type TypeCommon struct {
- TypeName string
- FldName string // for struct fields and named args
- TypeSize uint64 // static size of the type, or 0 for variable size types
- ArgDir Dir
- IsOptional bool
-}
-
-func (t *TypeCommon) Name() string {
- return t.TypeName
-}
-
-func (t *TypeCommon) FieldName() string {
- return t.FldName
-}
-
-func (t *TypeCommon) Optional() bool {
- return t.IsOptional
-}
-
-func (t *TypeCommon) Default() uint64 {
- return 0
-}
-
-func (t *TypeCommon) Size() uint64 {
- if t.Varlen() {
- panic(fmt.Sprintf("static type size is not known: %#v", t))
- }
- return t.TypeSize
-}
-
-func (t *TypeCommon) Varlen() bool {
- return t.TypeSize == 0
-}
-
-func (t *TypeCommon) BitfieldOffset() uint64 {
- return 0
-}
-
-func (t *TypeCommon) BitfieldLength() uint64 {
- return 0
-}
-
-func (t *TypeCommon) BitfieldMiddle() bool {
- return false
-}
-
-func (t TypeCommon) Dir() Dir {
- return t.ArgDir
-}
-
-const (
- InvalidFD = ^uint64(0)
-)
-
-type ResourceDesc struct {
- Name string
- Type Type
- Kind []string
- Values []uint64
-}
-
-type ResourceType struct {
- TypeCommon
- Desc *ResourceDesc
-}
-
-func (t *ResourceType) Default() uint64 {
- return t.Desc.Values[0]
-}
-
-func (t *ResourceType) SpecialValues() []uint64 {
- return t.Desc.Values
-}
-
-type IntTypeCommon struct {
- TypeCommon
- BitfieldOff uint64
- BitfieldLen uint64
- BigEndian bool
- BitfieldMdl bool
-}
-
-func (t *IntTypeCommon) BitfieldOffset() uint64 {
- return t.BitfieldOff
-}
-
-func (t *IntTypeCommon) BitfieldLength() uint64 {
- return t.BitfieldLen
-}
-
-func (t *IntTypeCommon) BitfieldMiddle() bool {
- return t.BitfieldMdl
-}
-
-type ConstType struct {
- IntTypeCommon
- Val uint64
- IsPad bool
-}
-
-type IntKind int
-
-const (
- IntPlain IntKind = iota
- IntFileoff // offset within a file
- IntRange
-)
-
-type IntType struct {
- IntTypeCommon
- Kind IntKind
- RangeBegin uint64
- RangeEnd uint64
-}
-
-type FlagsType struct {
- IntTypeCommon
- Vals []uint64
-}
-
-type LenType struct {
- IntTypeCommon
- ByteSize uint64 // want size in multiple of bytes instead of array size
- Buf string
-}
-
-type ProcType struct {
- IntTypeCommon
- ValuesStart uint64
- ValuesPerProc uint64
-}
-
-type CsumKind int
-
-const (
- CsumInet CsumKind = iota
- CsumPseudo
-)
-
-type CsumType struct {
- IntTypeCommon
- Kind CsumKind
- Buf string
- Protocol uint64 // for CsumPseudo
-}
-
-type VmaType struct {
- TypeCommon
- RangeBegin uint64 // in pages
- RangeEnd uint64
-}
-
-type BufferKind int
-
-const (
- BufferBlobRand BufferKind = iota
- BufferBlobRange
- BufferString
- BufferFilename
- BufferText
-)
-
-type TextKind int
-
-const (
- Text_x86_real TextKind = iota
- Text_x86_16
- Text_x86_32
- Text_x86_64
- Text_arm64
-)
-
-type BufferType struct {
- TypeCommon
- Kind BufferKind
- RangeBegin uint64 // for BufferBlobRange kind
- RangeEnd uint64 // for BufferBlobRange kind
- Text TextKind // for BufferText
- SubKind string
- Values []string // possible values for BufferString kind
-}
-
-type ArrayKind int
-
-const (
- ArrayRandLen ArrayKind = iota
- ArrayRangeLen
-)
-
-type ArrayType struct {
- TypeCommon
- Type Type
- Kind ArrayKind
- RangeBegin uint64
- RangeEnd uint64
-}
-
-type PtrType struct {
- TypeCommon
- Type Type
-}
-
-type StructType struct {
- Key StructKey
- FldName string
- *StructDesc
-}
-
-func (t *StructType) FieldName() string {
- return t.FldName
-}
-
-type UnionType struct {
- Key StructKey
- FldName string
- *StructDesc
-}
-
-func (t *UnionType) FieldName() string {
- return t.FldName
-}
-
-var (
- SyscallMap = make(map[string]*Syscall)
- Resources map[string]*ResourceDesc
- ctors = make(map[string][]*Syscall)
-)
-
-type StructDesc struct {
- TypeCommon
- Fields []Type
- AlignAttr uint64
-}
-
-func (t *StructDesc) FieldName() string {
- panic("must not be called")
-}
-
-type StructKey struct {
- Name string
- Dir Dir
-}
-
-type KeyedStruct struct {
- Key StructKey
- Desc *StructDesc
-}
-
-func initStructFields() {
- keyedStructs := make(map[StructKey]*StructDesc)
- for _, desc := range structDescs {
- keyedStructs[desc.Key] = desc.Desc
- }
-
- for _, c := range Syscalls {
- ForeachType(c, func(t Type) {
- switch s := t.(type) {
- case *StructType:
- s.StructDesc = keyedStructs[s.Key]
- if s.StructDesc == nil {
- panic("no struct desc")
- }
- case *UnionType:
- s.StructDesc = keyedStructs[s.Key]
- if s.StructDesc == nil {
- panic("no union desc")
- }
- }
- })
- }
-}
-
-// ResourceConstructors returns a list of calls that can create a resource of the given kind.
-func ResourceConstructors(name string) []*Syscall {
- return ctors[name]
-}
-
-func initResources() {
- Resources = make(map[string]*ResourceDesc)
- for _, res := range resourceArray {
- Resources[res.Name] = res
- }
- for _, c := range Syscalls {
- ForeachType(c, func(t Type) {
- if r, ok := t.(*ResourceType); ok {
- r.Desc = Resources[r.TypeName]
- }
- })
- }
- for _, res := range resourceArray {
- ctors[res.Name] = resourceCtors(res.Kind, false)
- }
-}
-
-func resourceCtors(kind []string, precise bool) []*Syscall {
- // Find calls that produce the necessary resources.
- var metas []*Syscall
- for _, meta := range Syscalls {
- // Recurse into arguments to see if there is an out/inout arg of necessary type.
- ok := false
- ForeachType(meta, func(typ Type) {
- if ok {
- return
- }
- switch typ1 := typ.(type) {
- case *ResourceType:
- if typ1.Dir() != DirIn && isCompatibleResource(kind, typ1.Desc.Kind, precise) {
- ok = true
- }
- }
- })
- if ok {
- metas = append(metas, meta)
- }
- }
- return metas
-}
-
-// IsCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst.
-func IsCompatibleResource(dst, src string) bool {
- dstRes := Resources[dst]
- if dstRes == nil {
- panic(fmt.Sprintf("unknown resource '%v'", dst))
- }
- srcRes := Resources[src]
- if srcRes == nil {
- panic(fmt.Sprintf("unknown resource '%v'", src))
- }
- return isCompatibleResource(dstRes.Kind, srcRes.Kind, false)
-}
-
-// isCompatibleResource returns true if resource of kind src can be passed as an argument of kind dst.
-// If precise is true, then it does not allow passing a less specialized resource (e.g. fd)
-// as a more specialized resource (e.g. socket). Otherwise it does.
-func isCompatibleResource(dst, src []string, precise bool) bool {
- if len(dst) > len(src) {
- // dst is more specialized, e.g dst=socket, src=fd.
- if precise {
- return false
- }
- dst = dst[:len(src)]
- }
- if len(src) > len(dst) {
- // src is more specialized, e.g dst=fd, src=socket.
- src = src[:len(dst)]
- }
- for i, k := range dst {
- if k != src[i] {
- return false
- }
- }
- return true
-}
-
-func (c *Syscall) InputResources() []*ResourceType {
- var resources []*ResourceType
- ForeachType(c, func(typ Type) {
- switch typ1 := typ.(type) {
- case *ResourceType:
- if typ1.Dir() != DirOut && !typ1.IsOptional {
- resources = append(resources, typ1)
- }
- }
- })
- return resources
-}
-
-func TransitivelyEnabledCalls(enabled map[*Syscall]bool) map[*Syscall]bool {
- supported := make(map[*Syscall]bool)
- for c := range enabled {
- supported[c] = true
- }
- inputResources := make(map[*Syscall][]*ResourceType)
- ctors := make(map[string][]*Syscall)
- for c := range supported {
- inputs := c.InputResources()
- inputResources[c] = inputs
- for _, res := range inputs {
- if _, ok := ctors[res.Desc.Name]; ok {
- continue
- }
- ctors[res.Desc.Name] = resourceCtors(res.Desc.Kind, true)
- }
- }
- for {
- n := len(supported)
- haveGettime := supported[SyscallMap["clock_gettime"]]
- for c := range supported {
- canCreate := true
- for _, res := range inputResources[c] {
- noctors := true
- for _, ctor := range ctors[res.Desc.Name] {
- if supported[ctor] {
- noctors = false
- break
- }
- }
- if noctors {
- canCreate = false
- break
- }
- }
- // We need to support structs as resources,
- // but for now we just special-case timespec/timeval.
- if canCreate && !haveGettime {
- ForeachType(c, func(typ Type) {
- if a, ok := typ.(*StructType); ok && a.Dir() != DirOut && (a.Name() == "timespec" || a.Name() == "timeval") {
- canCreate = false
- }
- })
- }
- if !canCreate {
- delete(supported, c)
- }
- }
- if n == len(supported) {
- break
- }
- }
- return supported
-}
-
-func ForeachType(meta *Syscall, f func(Type)) {
- seen := make(map[*StructDesc]bool)
- var rec func(t Type)
- rec = func(t Type) {
- f(t)
- switch a := t.(type) {
- case *PtrType:
- rec(a.Type)
- case *ArrayType:
- rec(a.Type)
- case *StructType:
- if seen[a.StructDesc] {
- return // prune recursion via pointers to structs/unions
- }
- seen[a.StructDesc] = true
- for _, f := range a.Fields {
- rec(f)
- }
- case *UnionType:
- if seen[a.StructDesc] {
- return // prune recursion via pointers to structs/unions
- }
- seen[a.StructDesc] = true
- for _, opt := range a.Fields {
- rec(opt)
- }
- case *ResourceType, *BufferType, *VmaType, *LenType,
- *FlagsType, *ConstType, *IntType, *ProcType, *CsumType:
- default:
- panic("unknown type")
- }
- }
- for _, t := range meta.Args {
- rec(t)
- }
- if meta.Ret != nil {
- rec(meta.Ret)
- }
-}
-
-func init() {
- initStructFields()
- initResources()
- structDescs = nil
-
- for _, c := range Syscalls {
- if SyscallMap[c.Name] != nil {
- println(c.Name)
- panic("duplicate syscall")
- }
- SyscallMap[c.Name] = c
- }
-}
diff --git a/sys/decl_test.go b/sys/decl_test.go
deleted file mode 100644
index a156f4f61..000000000
--- a/sys/decl_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2015 syzkaller project authors. All rights reserved.
-// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
-
-package sys
-
-import (
- "testing"
-)
-
-func TestResourceCtors(t *testing.T) {
- for _, c := range Syscalls {
- for _, res := range c.InputResources() {
- if len(resourceCtors(res.Desc.Kind, true)) == 0 {
- t.Errorf("call %v requires input resource %v, but there are no calls that can create this resource", c.Name, res.Desc.Name)
- }
- }
- }
-}
-
-func TestTransitivelyEnabledCalls(t *testing.T) {
- t.Parallel()
- calls := make(map[*Syscall]bool)
- for _, c := range Syscalls {
- calls[c] = true
- }
- if trans := TransitivelyEnabledCalls(calls); len(calls) != len(trans) {
- for c := range calls {
- if !trans[c] {
- t.Logf("disabled %v", c.Name)
- }
- }
- t.Fatalf("can't create some resource")
- }
- delete(calls, SyscallMap["epoll_create"])
- if trans := TransitivelyEnabledCalls(calls); len(calls) != len(trans) {
- t.Fatalf("still must be able to create epoll fd with epoll_create1")
- }
- delete(calls, SyscallMap["epoll_create1"])
- trans := TransitivelyEnabledCalls(calls)
- if len(calls)-5 != len(trans) ||
- trans[SyscallMap["epoll_ctl$EPOLL_CTL_ADD"]] ||
- trans[SyscallMap["epoll_ctl$EPOLL_CTL_MOD"]] ||
- trans[SyscallMap["epoll_ctl$EPOLL_CTL_DEL"]] ||
- trans[SyscallMap["epoll_wait"]] ||
- trans[SyscallMap["epoll_pwait"]] {
- t.Fatalf("epoll fd is not disabled")
- }
-}
-
-func TestClockGettime(t *testing.T) {
- t.Parallel()
- calls := make(map[*Syscall]bool)
- for _, c := range Syscalls {
- calls[c] = true
- }
- // Removal of clock_gettime should disable all calls that accept timespec/timeval.
- delete(calls, SyscallMap["clock_gettime"])
- trans := TransitivelyEnabledCalls(calls)
- if len(trans)+10 > len(calls) {
- t.Fatalf("clock_gettime did not disable enough calls: before %v, after %v", len(calls), len(trans))
- }
-}
diff --git a/sys/init.go b/sys/init.go
new file mode 100644
index 000000000..edefe3a52
--- /dev/null
+++ b/sys/init.go
@@ -0,0 +1,257 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package sys
+
+import (
+ "runtime"
+
+ "github.com/google/syzkaller/prog"
+)
+
+func init() {
+ lazyInit()
+ target := &prog.Target{
+ OS: runtime.GOOS,
+ Arch: runtime.GOARCH,
+ PtrSize: ptrSize,
+ PageSize: pageSize,
+ DataOffset: dataOffset,
+ Syscalls: syscalls,
+ Resources: resources,
+ MakeMmap: makeMmap,
+ AnalyzeMmap: analyzeMmap,
+ SanitizeCall: sanitizeCall,
+ SpecialStructs: map[string]func(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (prog.Arg, []*prog.Call){
+ "timespec": generateTimespec,
+ "timeval": generateTimespec,
+ },
+ }
+ prog.RegisterTarget(target)
+}
+
+const (
+ // TODO(dvyukov): dehardcode
+ ptrSize = 8
+ pageSize = 4 << 10
+ dataOffset = 512 << 20
+ invalidFD = ^uint64(0)
+)
+
+var (
+ mmapSyscall *prog.Syscall
+ clockGettimeSyscall *prog.Syscall
+)
+
+// createMmapCall creates a "normal" mmap call that maps [start, start+npages) page range.
+func makeMmap(start, npages uint64) *prog.Call {
+ return &prog.Call{
+ Meta: mmapSyscall,
+ Args: []prog.Arg{
+ prog.MakePointerArg(mmapSyscall.Args[0], start, 0, npages, nil),
+ prog.MakeConstArg(mmapSyscall.Args[1], npages*pageSize),
+ prog.MakeConstArg(mmapSyscall.Args[2], PROT_READ|PROT_WRITE),
+ prog.MakeConstArg(mmapSyscall.Args[3], MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED),
+ prog.MakeResultArg(mmapSyscall.Args[4], nil, invalidFD),
+ prog.MakeConstArg(mmapSyscall.Args[5], 0),
+ },
+ Ret: prog.MakeReturnArg(mmapSyscall.Ret),
+ }
+}
+
+func analyzeMmap(c *prog.Call) (start, npages uint64, mapped bool) {
+ switch c.Meta.Name {
+ case "mmap":
+ // Filter out only very wrong arguments.
+ npages = c.Args[1].(*prog.ConstArg).Val / pageSize
+ if npages == 0 {
+ return
+ }
+ flags := c.Args[3].(*prog.ConstArg).Val
+ fd := c.Args[4].(*prog.ResultArg).Val
+ if flags&MAP_ANONYMOUS == 0 && fd == invalidFD {
+ return
+ }
+ start = c.Args[0].(*prog.PointerArg).PageIndex
+ mapped = true
+ return
+ case "munmap":
+ start = c.Args[0].(*prog.PointerArg).PageIndex
+ npages = c.Args[1].(*prog.ConstArg).Val / pageSize
+ mapped = false
+ return
+ case "mremap":
+ start = c.Args[4].(*prog.PointerArg).PageIndex
+ npages = c.Args[2].(*prog.ConstArg).Val / pageSize
+ mapped = true
+ return
+ default:
+ return
+ }
+}
+
+func sanitizeCall(c *prog.Call) {
+ switch c.Meta.CallName {
+ case "mmap":
+ // Add MAP_FIXED flag, otherwise it produces non-deterministic results.
+ c.Args[3].(*prog.ConstArg).Val |= MAP_FIXED
+ case "mremap":
+ // Add MREMAP_FIXED flag, otherwise it produces non-deterministic results.
+ flags := c.Args[3].(*prog.ConstArg)
+ if flags.Val&MREMAP_MAYMOVE != 0 {
+ flags.Val |= MREMAP_FIXED
+ }
+ case "mknod", "mknodat":
+ pos := 1
+ if c.Meta.CallName == "mknodat" {
+ pos = 2
+ }
+ mode := c.Args[pos].(*prog.ConstArg)
+ dev := c.Args[pos+1].(*prog.ConstArg)
+ // Char and block devices read/write io ports, kernel memory and do other nasty things.
+ // TODO: not required if executor drops privileges.
+ switch mode.Val & (S_IFREG | S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK) {
+ case S_IFREG, S_IFIFO, S_IFSOCK:
+ case S_IFBLK:
+ if dev.Val>>8 == 7 {
+ break // loop
+ }
+ mode.Val &^= S_IFBLK
+ mode.Val |= S_IFREG
+ case S_IFCHR:
+ mode.Val &^= S_IFCHR
+ mode.Val |= S_IFREG
+ }
+ case "syslog":
+ cmd := c.Args[0].(*prog.ConstArg)
+ // These disable console output, but we need it.
+ if cmd.Val == SYSLOG_ACTION_CONSOLE_OFF || cmd.Val == SYSLOG_ACTION_CONSOLE_ON {
+ cmd.Val = SYSLOG_ACTION_SIZE_UNREAD
+ }
+ case "ioctl":
+ cmd := c.Args[1].(*prog.ConstArg)
+ // Freeze kills machine. Though, it is an interesting functions,
+ // so we need to test it somehow.
+ // TODO: not required if executor drops privileges.
+ if uint32(cmd.Val) == FIFREEZE {
+ cmd.Val = FITHAW
+ }
+ case "ptrace":
+ req := c.Args[0].(*prog.ConstArg)
+ // PTRACE_TRACEME leads to unkillable processes, see:
+ // https://groups.google.com/forum/#!topic/syzkaller/uGzwvhlCXAw
+ if req.Val == PTRACE_TRACEME {
+ req.Val = ^uint64(0)
+ }
+ case "exit", "exit_group":
+ code := c.Args[0].(*prog.ConstArg)
+ // These codes are reserved by executor.
+ if code.Val%128 == 67 || code.Val%128 == 68 {
+ code.Val = 1
+ }
+ }
+}
+
+func generateTimespec(g *prog.Gen, typ *prog.StructType, old *prog.GroupArg) (arg prog.Arg, calls []*prog.Call) {
+ // We need to generate timespec/timeval that are either
+ // (1) definitely in the past, or
+ // (2) definitely in unreachable fututre, or
+ // (3) few ms ahead of now.
+ // Note timespec/timeval can be absolute or relative to now.
+ usec := typ.Name() == "timeval"
+ switch {
+ case g.NOutOf(1, 4):
+ // Now for relative, past for absolute.
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 0),
+ prog.MakeResultArg(typ.Fields[1], nil, 0),
+ })
+ case g.NOutOf(1, 3):
+ // Few ms ahead for relative, past for absolute
+ nsec := uint64(10 * 1e6)
+ if usec {
+ nsec /= 1e3
+ }
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 0),
+ prog.MakeResultArg(typ.Fields[1], nil, nsec),
+ })
+ case g.NOutOf(1, 2):
+ // Unreachable fututre for both relative and absolute
+ arg = prog.MakeGroupArg(typ, []prog.Arg{
+ prog.MakeResultArg(typ.Fields[0], nil, 2e9),
+ prog.MakeResultArg(typ.Fields[1], nil, 0),
+ })
+ default:
+ // Few ms ahead for absolute.
+ meta := clockGettimeSyscall
+ ptrArgType := meta.Args[1].(*prog.PtrType)
+ argType := ptrArgType.Type.(*prog.StructType)
+ tp := prog.MakeGroupArg(argType, []prog.Arg{
+ prog.MakeResultArg(argType.Fields[0], nil, 0),
+ prog.MakeResultArg(argType.Fields[1], nil, 0),
+ })
+ var tpaddr prog.Arg
+ tpaddr, calls = g.Alloc(ptrArgType, tp)
+ gettime := &prog.Call{
+ Meta: meta,
+ Args: []prog.Arg{
+ prog.MakeConstArg(meta.Args[0], CLOCK_REALTIME),
+ tpaddr,
+ },
+ Ret: prog.MakeReturnArg(meta.Ret),
+ }
+ calls = append(calls, gettime)
+ sec := prog.MakeResultArg(typ.Fields[0], tp.(*prog.GroupArg).Inner[0], 0)
+ nsec := prog.MakeResultArg(typ.Fields[1], tp.(*prog.GroupArg).Inner[1], 0)
+ if usec {
+ nsec.(*prog.ResultArg).OpDiv = 1e3
+ nsec.(*prog.ResultArg).OpAdd = 10 * 1e3
+ } else {
+ nsec.(*prog.ResultArg).OpAdd = 10 * 1e6
+ }
+ arg = prog.MakeGroupArg(typ, []prog.Arg{sec, nsec})
+ }
+ return
+}
+
+func lazyInit() {
+ resourceMap := make(map[string]*prog.ResourceDesc)
+ for _, res := range resources {
+ resourceMap[res.Name] = res
+ }
+
+ keyedStructs := make(map[prog.StructKey]*prog.StructDesc)
+ for _, desc := range structDescs {
+ keyedStructs[desc.Key] = desc.Desc
+ }
+ structDescs = nil
+
+ for _, c := range syscalls {
+ prog.ForeachType(c, func(t0 prog.Type) {
+ switch t := t0.(type) {
+ case *prog.ResourceType:
+ t.Desc = resourceMap[t.TypeName]
+ if t.Desc == nil {
+ panic("no resource desc")
+ }
+ case *prog.StructType:
+ t.StructDesc = keyedStructs[t.Key]
+ if t.StructDesc == nil {
+ panic("no struct desc")
+ }
+ case *prog.UnionType:
+ t.StructDesc = keyedStructs[t.Key]
+ if t.StructDesc == nil {
+ panic("no union desc")
+ }
+ }
+ })
+ switch c.Name {
+ case "mmap":
+ mmapSyscall = c
+ case "clock_gettime":
+ clockGettimeSyscall = c
+ }
+ }
+}
diff --git a/sys/sys_386.go b/sys/sys_386.go
index f0eebd212..a699a8893 100644
--- a/sys/sys_386.go
+++ b/sys/sys_386.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 18446744073709551615, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_amd64.go b/sys/sys_amd64.go
index 0b85dda44..5325d7f13 100644
--- a/sys/sys_amd64.go
+++ b/sys/sys_amd64.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 43, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_arm.go b/sys/sys_arm.go
index adcd5dbef..128fd836d 100644
--- a/sys/sys_arm.go
+++ b/sys/sys_arm.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5892,7 +5894,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 9437469, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 4, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_arm64.go b/sys/sys_arm64.go
index 435eb92b6..bfc975594 100644
--- a/sys/sys_arm64.go
+++ b/sys/sys_arm64.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 202, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/sys_ppc64le.go b/sys/sys_ppc64le.go
index 52a8bca35..332c3e6b2 100644
--- a/sys/sys_ppc64le.go
+++ b/sys/sys_ppc64le.go
@@ -1,7 +1,9 @@
// AUTOGENERATED FILE
package sys
-var resourceArray = []*ResourceDesc{
+import . "github.com/google/syzkaller/prog"
+
+var resources = []*ResourceDesc{
{Name: "assoc_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"assoc_id"}, Values: []uint64{0}},
{Name: "bpf_map_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_map_id"}, Values: []uint64{0, 4294967295}},
{Name: "bpf_prog_id", Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", TypeSize: 4}}}, Kind: []string{"bpf_prog_id"}, Values: []uint64{0, 4294967295}},
@@ -5941,7 +5943,7 @@ var structDescs = []*KeyedStruct{
}}},
}
-var Syscalls = []*Syscall{
+var syscalls = []*Syscall{
{NR: 330, Name: "accept", CallName: "accept", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "sock", FldName: "fd", TypeSize: 4}},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "peer", TypeSize: 8, IsOptional: true}, Type: &UnionType{Key: StructKey{Name: "sockaddr_storage", Dir: 1}}},
diff --git a/sys/syz-sysgen/syscallnr.go b/sys/syz-sysgen/syscallnr.go
index 02c676cf0..da427a553 100644
--- a/sys/syz-sysgen/syscallnr.go
+++ b/sys/syz-sysgen/syscallnr.go
@@ -9,7 +9,7 @@ import (
"strings"
"text/template"
- "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/prog"
)
type Arch struct {
@@ -26,7 +26,7 @@ var archs = []*Arch{
{"ppc64le", 8, []string{"__ppc64__", "__PPC64__", "__powerpc64__"}},
}
-func generateExecutorSyscalls(arch *Arch, syscalls []*sys.Syscall) []byte {
+func generateExecutorSyscalls(arch *Arch, syscalls []*prog.Syscall) []byte {
data := ArchData{
CARCH: arch.CARCH,
}
diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go
index 7381f1edb..f09835aef 100644
--- a/sys/syz-sysgen/sysgen.go
+++ b/sys/syz-sysgen/sysgen.go
@@ -116,8 +116,9 @@ func main() {
func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io.Writer) {
fmt.Fprintf(out, "// AUTOGENERATED FILE\n")
fmt.Fprintf(out, "package sys\n\n")
+ fmt.Fprintf(out, "import . \"github.com/google/syzkaller/prog\"\n\n")
- fmt.Fprintf(out, "var resourceArray = ")
+ fmt.Fprintf(out, "var resources = ")
serializer.Write(out, prog.Resources)
fmt.Fprintf(out, "\n\n")
@@ -133,7 +134,7 @@ func generate(arch string, prog *compiler.Prog, consts map[string]uint64, out io
serializer.Write(out, prog.StructDescs)
fmt.Fprintf(out, "\n\n")
- fmt.Fprintf(out, "var Syscalls = ")
+ fmt.Fprintf(out, "var syscalls = ")
serializer.Write(out, prog.Syscalls)
fmt.Fprintf(out, "\n\n")