mirror of
https://github.com/reactos/syzkaller.git
synced 2024-12-04 09:43:38 +00:00
ddf7b3e065
There is effectively infinite number of possible crypto algorithm names due to templates. Plus there is tricky relation between algorithms and algorithm type names. This change adds custom mutator for sockaddr_alg struct to improve variance in generated algorithms.
173 lines
4.7 KiB
Go
173 lines
4.7 KiB
Go
// Copyright 2017 syzkaller project authors. All rights reserved.
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
package prog
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"sort"
|
|
)
|
|
|
|
// Target describes target OS/arch pair.
|
|
type Target struct {
|
|
OS string
|
|
Arch string
|
|
Revision string // unique hash representing revision of the descriptions
|
|
PtrSize uint64
|
|
PageSize uint64
|
|
DataOffset uint64
|
|
|
|
Syscalls []*Syscall
|
|
Resources []*ResourceDesc
|
|
Structs []*KeyedStruct
|
|
Consts []ConstValue
|
|
|
|
// Syscall used by MakeMmap.
|
|
// It has some special meaning because there are usually too many of them.
|
|
MmapSyscall *Syscall
|
|
|
|
// MakeMmap creates call that maps [start, start+npages) page range.
|
|
MakeMmap func(start, npages uint64) *Call
|
|
|
|
// AnalyzeMmap analyzes the call c regarding mapping/unmapping memory.
|
|
// If it maps/unmaps any memory returns [start, start+npages) range,
|
|
// otherwise returns npages = 0.
|
|
AnalyzeMmap func(c *Call) (start, npages uint64, mapped bool)
|
|
|
|
// SanitizeCall neutralizes harmful calls.
|
|
SanitizeCall func(c *Call)
|
|
|
|
// SpecialStructs allows target to do custom generation/mutation for some struct types.
|
|
// Map key is struct name for which custom generation/mutation is required.
|
|
// Map value is custom generation/mutation function that will be called
|
|
// for the corresponding structs. g is helper object that allows generate random numbers,
|
|
// allocate memory, etc. typ is the struct type. old is the old value of the struct
|
|
// for mutation, or nil for generation. The function returns a new value of the struct,
|
|
// and optionally any calls that need to be inserted before the arg reference.
|
|
SpecialStructs map[string]func(g *Gen, typ *StructType, old *GroupArg) (Arg, []*Call)
|
|
|
|
// Special strings that can matter for the target.
|
|
// Used as fallback when string type does not have own dictionary.
|
|
StringDictionary []string
|
|
|
|
// Filled by prog package:
|
|
SyscallMap map[string]*Syscall
|
|
ConstMap map[string]uint64
|
|
resourceMap map[string]*ResourceDesc
|
|
// Maps resource name to a list of calls that can create the resource.
|
|
resourceCtors map[string][]*Syscall
|
|
}
|
|
|
|
var targets = make(map[string]*Target)
|
|
|
|
func RegisterTarget(target *Target, initArch func(target *Target)) {
|
|
key := target.OS + "/" + target.Arch
|
|
if targets[key] != nil {
|
|
panic(fmt.Sprintf("duplicate target %v", key))
|
|
}
|
|
target.SanitizeCall = func(c *Call) {}
|
|
initTarget(target)
|
|
initArch(target)
|
|
target.ConstMap = nil // currently used only by initArch
|
|
targets[key] = target
|
|
}
|
|
|
|
func GetTarget(OS, arch string) (*Target, error) {
|
|
key := OS + "/" + arch
|
|
target := targets[key]
|
|
if target == nil {
|
|
var supported []string
|
|
for _, t := range targets {
|
|
supported = append(supported, fmt.Sprintf("%v/%v", t.OS, t.Arch))
|
|
}
|
|
sort.Strings(supported)
|
|
return nil, fmt.Errorf("unknown target: %v (supported: %v)", key, supported)
|
|
}
|
|
return target, nil
|
|
}
|
|
|
|
func AllTargets() []*Target {
|
|
var res []*Target
|
|
for _, t := range targets {
|
|
res = append(res, t)
|
|
}
|
|
sort.Slice(res, func(i, j int) bool {
|
|
if res[i].OS != res[j].OS {
|
|
return res[i].OS < res[j].OS
|
|
}
|
|
return res[i].Arch < res[j].Arch
|
|
})
|
|
return res
|
|
}
|
|
|
|
func initTarget(target *Target) {
|
|
target.ConstMap = make(map[string]uint64)
|
|
for _, c := range target.Consts {
|
|
target.ConstMap[c.Name] = c.Value
|
|
}
|
|
|
|
target.resourceMap = make(map[string]*ResourceDesc)
|
|
for _, res := range target.Resources {
|
|
target.resourceMap[res.Name] = res
|
|
}
|
|
|
|
keyedStructs := make(map[StructKey]*StructDesc)
|
|
for _, desc := range target.Structs {
|
|
keyedStructs[desc.Key] = desc.Desc
|
|
}
|
|
target.Structs = nil
|
|
|
|
target.SyscallMap = make(map[string]*Syscall)
|
|
for _, c := range target.Syscalls {
|
|
target.SyscallMap[c.Name] = c
|
|
ForeachType(c, func(t0 Type) {
|
|
switch t := t0.(type) {
|
|
case *ResourceType:
|
|
t.Desc = target.resourceMap[t.TypeName]
|
|
if t.Desc == nil {
|
|
panic("no resource desc")
|
|
}
|
|
case *StructType:
|
|
t.StructDesc = keyedStructs[t.Key]
|
|
if t.StructDesc == nil {
|
|
panic("no struct desc")
|
|
}
|
|
case *UnionType:
|
|
t.StructDesc = keyedStructs[t.Key]
|
|
if t.StructDesc == nil {
|
|
panic("no union desc")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
target.resourceCtors = make(map[string][]*Syscall)
|
|
for _, res := range target.Resources {
|
|
target.resourceCtors[res.Name] = target.calcResourceCtors(res.Kind, false)
|
|
}
|
|
}
|
|
|
|
type Gen struct {
|
|
r *randGen
|
|
s *state
|
|
}
|
|
|
|
func (g *Gen) Rand() *rand.Rand {
|
|
return g.r.Rand
|
|
}
|
|
|
|
func (g *Gen) NOutOf(n, outOf int) bool {
|
|
return g.r.nOutOf(n, outOf)
|
|
}
|
|
|
|
func (g *Gen) Alloc(ptrType Type, data Arg) (Arg, []*Call) {
|
|
return g.r.addr(g.s, ptrType, data.Size(), data)
|
|
}
|
|
|
|
func (g *Gen) GenerateArg(typ Type, pcalls *[]*Call) Arg {
|
|
arg, calls := g.r.generateArg(g.s, typ)
|
|
*pcalls = append(*pcalls, calls...)
|
|
return arg
|
|
}
|