diff options
Diffstat (limited to 'sys/decl.go')
| -rw-r--r-- | sys/decl.go | 522 |
1 files changed, 0 insertions, 522 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 - } -} |
