diff options
| -rw-r--r-- | pkg/compiler/types.go | 23 | ||||
| -rw-r--r-- | pkg/host/syscalls.go | 20 | ||||
| -rw-r--r-- | prog/any.go | 99 | ||||
| -rw-r--r-- | prog/decl_test.go | 3 | ||||
| -rw-r--r-- | prog/rand.go | 2 | ||||
| -rw-r--r-- | prog/size.go | 2 | ||||
| -rw-r--r-- | prog/target.go | 19 | ||||
| -rw-r--r-- | sys/syz-sysgen/sysgen.go | 6 |
8 files changed, 71 insertions, 103 deletions
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 2fddb4917..fd021cefc 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -964,6 +964,29 @@ type optional[T] [ val T void void ] [varlen] + +# prog/any.go knows layout of these types. +ANYUNION [ + ANYBLOB array[int8] + ANYRES16 ANYRES16 + ANYRES32 ANYRES32 + ANYRES64 ANYRES64 + ANYRESDEC fmt[dec, ANYRES64] + ANYRESHEX fmt[hex, ANYRES64] + ANYRESOCT fmt[oct, ANYRES64] +] [varlen] + +ANYPTRS [ + ANYPTR ptr[in, array[ANYUNION]] + ANYPTR64 ptr64[in, array[ANYUNION]] +] + +resource ANYRES16[int16]: -1, 0 +resource ANYRES32[int32]: -1, 0 +resource ANYRES64[int64]: -1, 0 + +syz_builtin0(a ptr[in, ANYPTRS]) (disabled) +syz_builtin1(a ptr[out, ANYUNION]) (disabled) ` func init() { diff --git a/pkg/host/syscalls.go b/pkg/host/syscalls.go index d63c7ceef..e322fc3b1 100644 --- a/pkg/host/syscalls.go +++ b/pkg/host/syscalls.go @@ -16,16 +16,24 @@ func DetectSupportedSyscalls(target *prog.Target, sandbox string) ( log.Logf(1, "detecting supported syscalls") supported := make(map[*prog.Syscall]bool) unsupported := make(map[*prog.Syscall]string) + const disabledAttribute = "has disabled attribute in descriptions" // These do not have own host and parasitize on some other OS. if targets.Get(target.OS, target.Arch).HostFuzzer { for _, c := range target.Syscalls { - supported[c] = true + if c.Attrs.Disabled { + unsupported[c] = disabledAttribute + } else { + supported[c] = true + } } } else { for _, c := range target.Syscalls { ok, reason := false, "" - switch c.CallName { - case "syz_execute_func": + switch { + case c.Attrs.Disabled: + ok = false + reason = disabledAttribute + case c.CallName == "syz_execute_func": // syz_execute_func caused multiple problems: // 1. First it lead to corpus exploision. The program used existing values in registers // to pollute output area. We tried to zero registers (though, not reliably). @@ -55,12 +63,6 @@ func DetectSupportedSyscalls(target *prog.Target, sandbox string) ( } } } - for c := range supported { - if c.Attrs.Disabled { - delete(supported, c) - unsupported[c] = "has disabled attribute in descriptions" - } - } return supported, unsupported, nil } diff --git a/prog/any.go b/prog/any.go index ce3736a4b..7bf38b6be 100644 --- a/prog/any.go +++ b/prog/any.go @@ -21,88 +21,29 @@ type anyTypes struct { resoct *ResourceType } -// This generates type descriptions for: -// -// resource ANYRES16[int16]: 0xffffffffffffffff, 0 -// resource ANYRES32[int32]: 0xffffffffffffffff, 0 -// resource ANYRES64[int64]: 0xffffffffffffffff, 0 -// ANY [ -// bin array[int8] -// res16 ANYRES16 -// res32 ANYRES32 -// res64 ANYRES64 -// resdec fmt[dec, ANYRES64] -// reshex fmt[hex, ANYRES64] -// resoct fmt[oct, ANYRES64] -// ] [varlen] -func initAnyTypes(target *Target) { - target.any.union = &UnionType{ - TypeCommon: TypeCommon{ - TypeName: "ANYUNION", - IsVarlen: true, - }, - } - target.any.array = &ArrayType{ - TypeCommon: TypeCommon{ - TypeName: "ANYARRAY", - IsVarlen: true, - }, - Elem: target.any.union, - } - target.any.ptrPtr = &PtrType{ - TypeCommon: TypeCommon{ - TypeName: "ANYPTR", - TypeSize: target.PtrSize, - IsOptional: true, - }, - Elem: target.any.array, - ElemDir: DirIn, - } - target.any.ptr64 = &PtrType{ - TypeCommon: TypeCommon{ - TypeName: "ANYPTR64", - TypeSize: 8, - IsOptional: true, - }, - Elem: target.any.array, - ElemDir: DirIn, - } - target.any.blob = &BufferType{ - TypeCommon: TypeCommon{ - TypeName: "ANYBLOB", - IsVarlen: true, - }, - } - createResource := func(name, base string, bf BinaryFormat, size uint64) *ResourceType { - return &ResourceType{ - TypeCommon: TypeCommon{ - TypeName: name, - TypeSize: size, - IsOptional: true, - }, - ArgFormat: bf, - Desc: &ResourceDesc{ - Name: name, - Kind: []string{name}, - Values: []uint64{^uint64(0), 0}, - }, +func (target *Target) initAnyTypes() { + var anyPtrs *UnionType + for _, typ := range target.types { + if typ.Name() == "ANYPTRS" { + anyPtrs = typ.(*UnionType) + break } } - target.any.res16 = createResource("ANYRES16", "int16", FormatNative, 2) - target.any.res32 = createResource("ANYRES32", "int32", FormatNative, 4) - target.any.res64 = createResource("ANYRES64", "int64", FormatNative, 8) - target.any.resdec = createResource("ANYRESDEC", "int64", FormatStrDec, 20) - target.any.reshex = createResource("ANYRESHEX", "int64", FormatStrHex, 18) - target.any.resoct = createResource("ANYRESOCT", "int64", FormatStrOct, 23) - target.any.union.Fields = []Field{ - {Name: "ANYBLOB", Type: target.any.blob}, - {Name: "ANYRES16", Type: target.any.res16}, - {Name: "ANYRES32", Type: target.any.res32}, - {Name: "ANYRES64", Type: target.any.res64}, - {Name: "ANYRESDEC", Type: target.any.resdec}, - {Name: "ANYRESHEX", Type: target.any.reshex}, - {Name: "ANYRESOCT", Type: target.any.resoct}, + if anyPtrs == nil { + panic("no builtin ANYPTRS type") } + // These types are generated by builtin descriptions in pkg/compiler/types.go. + target.any.ptrPtr = anyPtrs.Fields[0].Type.(*PtrType) + target.any.ptr64 = anyPtrs.Fields[1].Type.(*PtrType) + target.any.array = target.any.ptrPtr.Elem.(*ArrayType) + target.any.union = target.any.array.Elem.(*UnionType) + target.any.blob = target.any.union.Fields[0].Type.(*BufferType) + target.any.res16 = target.any.union.Fields[1].Type.(*ResourceType) + target.any.res32 = target.any.union.Fields[2].Type.(*ResourceType) + target.any.res64 = target.any.union.Fields[3].Type.(*ResourceType) + target.any.resdec = target.any.union.Fields[4].Type.(*ResourceType) + target.any.reshex = target.any.union.Fields[5].Type.(*ResourceType) + target.any.resoct = target.any.union.Fields[6].Type.(*ResourceType) } func (target *Target) getAnyPtrType(size uint64) *PtrType { diff --git a/prog/decl_test.go b/prog/decl_test.go index f999ae589..5f1795ec6 100644 --- a/prog/decl_test.go +++ b/prog/decl_test.go @@ -13,9 +13,8 @@ func TestResourceCtors(t *testing.T) { t.Skip("too slow") } testEachTarget(t, func(t *testing.T, target *Target) { - expectFail := false for _, res := range target.Resources { - if len(target.calcResourceCtors(res, true)) == 0 != expectFail { + if len(target.calcResourceCtors(res, true)) == 0 && !strings.HasPrefix(res.Name, "ANY") { t.Errorf("resource %v can't be created", res.Name) } } diff --git a/prog/rand.go b/prog/rand.go index 150f4b266..18c86d77a 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -568,7 +568,7 @@ func (target *Target) GenerateAllSyzProg(rs rand.Source) *Prog { s := newState(target, target.DefaultChoiceTable(), nil) handled := make(map[string]bool) for _, meta := range target.Syscalls { - if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] { + if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] || meta.Attrs.Disabled { continue } handled[meta.CallName] = true diff --git a/prog/size.go b/prog/size.go index 61d382723..6eccec50f 100644 --- a/prog/size.go +++ b/prog/size.go @@ -55,7 +55,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A offset += buf.Size() continue } - if typ := buf.Type().Name(); typ == target.any.ptrPtr.Name() || typ == target.any.ptr64.Name() { + if typ := buf.Type(); typ == target.any.ptrPtr || typ == target.any.ptr64 { // If path points into squashed argument, we don't have the target argument. // In such case we simply leave size argument as is. It can't happen during generation, // only during mutation and mutation can set size to random values, so it should be fine. diff --git a/prog/target.go b/prog/target.go index af03dc47f..630fb7cbf 100644 --- a/prog/target.go +++ b/prog/target.go @@ -23,7 +23,6 @@ type Target struct { Syscalls []*Syscall Resources []*ResourceDesc Consts []ConstValue - Types []Type // MakeDataMmap creates calls that mmaps target data memory range. MakeDataMmap func() []*Call @@ -57,10 +56,12 @@ type Target struct { SpecialPointers []uint64 // Filled by prog package: + SyscallMap map[string]*Syscall + ConstMap map[string]uint64 + init sync.Once initArch func(target *Target) - SyscallMap map[string]*Syscall - ConstMap map[string]uint64 + types []Type resourceMap map[string]*ResourceDesc // Maps resource name to a list of calls that can create the resource. resourceCtors map[string][]*Syscall @@ -75,12 +76,13 @@ const maxSpecialPointers = 16 var targets = make(map[string]*Target) -func RegisterTarget(target *Target, initArch func(target *Target)) { +func RegisterTarget(target *Target, types []Type, initArch func(target *Target)) { key := target.OS + "/" + target.Arch if targets[key] != nil { panic(fmt.Sprintf("duplicate target %v", key)) } target.initArch = initArch + target.types = types targets[key] = target } @@ -122,7 +124,6 @@ func (target *Target) lazyInit() { target.AnnotateCall = func(c ExecCall) string { return "" } target.initTarget() target.initArch(target) - target.ConstMap = nil // currently used only by initArch // Give these 2 known addresses fixed positions and prepend target-specific ones at the end. target.SpecialPointers = append([]uint64{ 0x0000000000000000, // NULL pointer (keep this first because code uses special index=0 as NULL) @@ -132,6 +133,9 @@ func (target *Target) lazyInit() { if len(target.SpecialPointers) > maxSpecialPointers { panic("too many special pointers") } + // These are used only during lazyInit. + target.ConstMap = nil + target.types = nil } func (target *Target) initTarget() { @@ -140,8 +144,8 @@ func (target *Target) initTarget() { target.ConstMap[c.Name] = c.Value } - target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.Types) - target.Types = nil + target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.types) + target.initAnyTypes() target.SyscallMap = make(map[string]*Syscall) for i, c := range target.Syscalls { @@ -156,7 +160,6 @@ func (target *Target) initTarget() { for _, res := range target.Resources { target.resourceCtors[res.Name] = target.calcResourceCtors(res, false) } - initAnyTypes(target) } func (target *Target) GetConst(name string) uint64 { diff --git a/sys/syz-sysgen/sysgen.go b/sys/syz-sysgen/sysgen.go index bf39ba9ee..654664af6 100644 --- a/sys/syz-sysgen/sysgen.go +++ b/sys/syz-sysgen/sysgen.go @@ -189,8 +189,8 @@ func generate(target *targets.Target, prg *compiler.Prog, consts map[string]uint fmt.Fprintf(out, "\tRegisterTarget(&Target{"+ "OS: %q, Arch: %q, Revision: revision_%v, PtrSize: %v, "+ "PageSize: %v, NumPages: %v, DataOffset: %v, Syscalls: syscalls_%v, "+ - "Resources: resources_%v, Types: types_%v, Consts: consts_%v}, "+ - "InitTarget)\n}\n\n", + "Resources: resources_%v, Consts: consts_%v}, "+ + "types_%v, InitTarget)\n}\n\n", target.OS, target.Arch, target.Arch, target.PtrSize, target.PageSize, target.NumPages, target.DataOffset, target.Arch, target.Arch, target.Arch, target.Arch) @@ -267,7 +267,7 @@ func generateExecutorSyscalls(target *targets.Target, syscalls []*prog.Syscall, Name: c.Name, CallName: c.CallName, NR: int32(c.NR), - NeedCall: !target.SyscallNumbers || strings.HasPrefix(c.CallName, "syz_"), + NeedCall: (!target.SyscallNumbers || strings.HasPrefix(c.CallName, "syz_")) && !c.Attrs.Disabled, Attrs: attrVals[:last+1], }) } |
