• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015/2016 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4package prog
5
6import (
7	"fmt"
8)
9
10type Syscall struct {
11	ID       int
12	NR       uint64 // kernel syscall number
13	Name     string
14	CallName string
15	Args     []Type
16	Ret      Type
17}
18
19type Dir int
20
21const (
22	DirIn Dir = iota
23	DirOut
24	DirInOut
25)
26
27func (dir Dir) String() string {
28	switch dir {
29	case DirIn:
30		return "in"
31	case DirOut:
32		return "out"
33	case DirInOut:
34		return "inout"
35	default:
36		panic("unknown dir")
37	}
38}
39
40type BinaryFormat int
41
42const (
43	FormatNative BinaryFormat = iota
44	FormatBigEndian
45	FormatStrDec
46	FormatStrHex
47	FormatStrOct
48)
49
50type Type interface {
51	String() string
52	Name() string
53	FieldName() string
54	Dir() Dir
55	Optional() bool
56	Varlen() bool
57	Size() uint64
58	Format() BinaryFormat
59	BitfieldOffset() uint64
60	BitfieldLength() uint64
61	BitfieldMiddle() bool // returns true for all but last bitfield in a group
62
63	makeDefaultArg() Arg
64	isDefaultArg(arg Arg) bool
65	generate(r *randGen, s *state) (arg Arg, calls []*Call)
66	mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool)
67	minimize(ctx *minimizeArgsCtx, arg Arg, path string) bool
68}
69
70func IsPad(t Type) bool {
71	if ct, ok := t.(*ConstType); ok && ct.IsPad {
72		return true
73	}
74	return false
75}
76
77type TypeCommon struct {
78	TypeName   string
79	FldName    string // for struct fields and named args
80	TypeSize   uint64 // static size of the type, or 0 for variable size types
81	ArgDir     Dir
82	IsOptional bool
83	IsVarlen   bool
84}
85
86func (t *TypeCommon) Name() string {
87	return t.TypeName
88}
89
90func (t *TypeCommon) FieldName() string {
91	return t.FldName
92}
93
94func (t *TypeCommon) Optional() bool {
95	return t.IsOptional
96}
97
98func (t *TypeCommon) Size() uint64 {
99	if t.IsVarlen {
100		panic(fmt.Sprintf("static type size is not known: %#v", t))
101	}
102	return t.TypeSize
103}
104
105func (t *TypeCommon) Varlen() bool {
106	return t.IsVarlen
107}
108
109func (t *TypeCommon) Format() BinaryFormat {
110	return FormatNative
111}
112
113func (t *TypeCommon) BitfieldOffset() uint64 {
114	return 0
115}
116
117func (t *TypeCommon) BitfieldLength() uint64 {
118	return 0
119}
120
121func (t *TypeCommon) BitfieldMiddle() bool {
122	return false
123}
124
125func (t TypeCommon) Dir() Dir {
126	return t.ArgDir
127}
128
129type ResourceDesc struct {
130	Name   string
131	Type   Type
132	Kind   []string
133	Values []uint64
134}
135
136type ResourceType struct {
137	TypeCommon
138	ArgFormat BinaryFormat
139	Desc      *ResourceDesc
140}
141
142func (t *ResourceType) String() string {
143	return t.Name()
144}
145
146func (t *ResourceType) makeDefaultArg() Arg {
147	return MakeResultArg(t, nil, t.Default())
148}
149
150func (t *ResourceType) isDefaultArg(arg Arg) bool {
151	a := arg.(*ResultArg)
152	return a.Res == nil && a.OpDiv == 0 && a.OpAdd == 0 &&
153		len(a.uses) == 0 && a.Val == t.Default()
154}
155
156func (t *ResourceType) Default() uint64 {
157	return t.Desc.Values[0]
158}
159
160func (t *ResourceType) SpecialValues() []uint64 {
161	return t.Desc.Values
162}
163
164func (t *ResourceType) Format() BinaryFormat {
165	return t.ArgFormat
166}
167
168type IntTypeCommon struct {
169	TypeCommon
170	ArgFormat   BinaryFormat
171	BitfieldOff uint64
172	BitfieldLen uint64
173	BitfieldMdl bool
174}
175
176func (t *IntTypeCommon) String() string {
177	return t.Name()
178}
179
180func (t *IntTypeCommon) Format() BinaryFormat {
181	return t.ArgFormat
182}
183
184func (t *IntTypeCommon) BitfieldOffset() uint64 {
185	return t.BitfieldOff
186}
187
188func (t *IntTypeCommon) BitfieldLength() uint64 {
189	return t.BitfieldLen
190}
191
192func (t *IntTypeCommon) BitfieldMiddle() bool {
193	return t.BitfieldMdl
194}
195
196type ConstType struct {
197	IntTypeCommon
198	Val   uint64
199	IsPad bool
200}
201
202func (t *ConstType) makeDefaultArg() Arg {
203	return MakeConstArg(t, t.Val)
204}
205
206func (t *ConstType) isDefaultArg(arg Arg) bool {
207	return arg.(*ConstArg).Val == t.Val
208}
209
210func (t *ConstType) String() string {
211	if t.IsPad {
212		return fmt.Sprintf("pad[%v]", t.Size())
213	}
214	return fmt.Sprintf("const[%v, %v]", t.Val, t.IntTypeCommon.String())
215}
216
217type IntKind int
218
219const (
220	IntPlain   IntKind = iota
221	IntFileoff         // offset within a file
222	IntRange
223)
224
225type IntType struct {
226	IntTypeCommon
227	Kind       IntKind
228	RangeBegin uint64
229	RangeEnd   uint64
230}
231
232func (t *IntType) makeDefaultArg() Arg {
233	return MakeConstArg(t, 0)
234}
235
236func (t *IntType) isDefaultArg(arg Arg) bool {
237	return arg.(*ConstArg).Val == 0
238}
239
240type FlagsType struct {
241	IntTypeCommon
242	Vals    []uint64
243	BitMask bool
244}
245
246func (t *FlagsType) makeDefaultArg() Arg {
247	return MakeConstArg(t, 0)
248}
249
250func (t *FlagsType) isDefaultArg(arg Arg) bool {
251	return arg.(*ConstArg).Val == 0
252}
253
254type LenType struct {
255	IntTypeCommon
256	BitSize uint64 // want size in multiple of bits instead of array size
257	Buf     string
258}
259
260func (t *LenType) makeDefaultArg() Arg {
261	return MakeConstArg(t, 0)
262}
263
264func (t *LenType) isDefaultArg(arg Arg) bool {
265	return arg.(*ConstArg).Val == 0
266}
267
268type ProcType struct {
269	IntTypeCommon
270	ValuesStart   uint64
271	ValuesPerProc uint64
272}
273
274const (
275	MaxPids          = 32
276	procDefaultValue = 0xffffffffffffffff // special value denoting 0 for all procs
277)
278
279func (t *ProcType) makeDefaultArg() Arg {
280	return MakeConstArg(t, procDefaultValue)
281}
282
283func (t *ProcType) isDefaultArg(arg Arg) bool {
284	return arg.(*ConstArg).Val == procDefaultValue
285}
286
287type CsumKind int
288
289const (
290	CsumInet CsumKind = iota
291	CsumPseudo
292)
293
294type CsumType struct {
295	IntTypeCommon
296	Kind     CsumKind
297	Buf      string
298	Protocol uint64 // for CsumPseudo
299}
300
301func (t *CsumType) String() string {
302	return "csum"
303}
304
305func (t *CsumType) makeDefaultArg() Arg {
306	return MakeConstArg(t, 0)
307}
308
309func (t *CsumType) isDefaultArg(arg Arg) bool {
310	return arg.(*ConstArg).Val == 0
311}
312
313type VmaType struct {
314	TypeCommon
315	RangeBegin uint64 // in pages
316	RangeEnd   uint64
317}
318
319func (t *VmaType) String() string {
320	return "vma"
321}
322
323func (t *VmaType) makeDefaultArg() Arg {
324	return MakeNullPointerArg(t)
325}
326
327func (t *VmaType) isDefaultArg(arg Arg) bool {
328	return arg.(*PointerArg).IsNull()
329}
330
331type BufferKind int
332
333const (
334	BufferBlobRand BufferKind = iota
335	BufferBlobRange
336	BufferString
337	BufferFilename
338	BufferText
339)
340
341type TextKind int
342
343const (
344	TextX86Real TextKind = iota
345	TextX86bit16
346	TextX86bit32
347	TextX86bit64
348	TextArm64
349)
350
351type BufferType struct {
352	TypeCommon
353	Kind       BufferKind
354	RangeBegin uint64   // for BufferBlobRange kind
355	RangeEnd   uint64   // for BufferBlobRange kind
356	Text       TextKind // for BufferText
357	SubKind    string
358	Values     []string // possible values for BufferString kind
359	NoZ        bool     // non-zero terminated BufferString/BufferFilename
360}
361
362func (t *BufferType) String() string {
363	return "buffer"
364}
365
366func (t *BufferType) makeDefaultArg() Arg {
367	if t.Dir() == DirOut {
368		var sz uint64
369		if !t.Varlen() {
370			sz = t.Size()
371		}
372		return MakeOutDataArg(t, sz)
373	}
374	var data []byte
375	if !t.Varlen() {
376		data = make([]byte, t.Size())
377	}
378	return MakeDataArg(t, data)
379}
380
381func (t *BufferType) isDefaultArg(arg Arg) bool {
382	a := arg.(*DataArg)
383	if a.Size() == 0 {
384		return true
385	}
386	if a.Type().Varlen() {
387		return false
388	}
389	if a.Type().Dir() == DirOut {
390		return true
391	}
392	for _, v := range a.Data() {
393		if v != 0 {
394			return false
395		}
396	}
397	return true
398}
399
400type ArrayKind int
401
402const (
403	ArrayRandLen ArrayKind = iota
404	ArrayRangeLen
405)
406
407type ArrayType struct {
408	TypeCommon
409	Type       Type
410	Kind       ArrayKind
411	RangeBegin uint64
412	RangeEnd   uint64
413}
414
415func (t *ArrayType) String() string {
416	return fmt.Sprintf("array[%v]", t.Type.String())
417}
418
419func (t *ArrayType) makeDefaultArg() Arg {
420	var elems []Arg
421	if t.Kind == ArrayRangeLen && t.RangeBegin == t.RangeEnd {
422		for i := uint64(0); i < t.RangeBegin; i++ {
423			elems = append(elems, t.Type.makeDefaultArg())
424		}
425	}
426	return MakeGroupArg(t, elems)
427}
428
429func (t *ArrayType) isDefaultArg(arg Arg) bool {
430	a := arg.(*GroupArg)
431	if !a.fixedInnerSize() && len(a.Inner) != 0 {
432		return false
433	}
434	for _, elem := range a.Inner {
435		if !isDefault(elem) {
436			return false
437		}
438	}
439	return true
440}
441
442type PtrType struct {
443	TypeCommon
444	Type Type
445}
446
447func (t *PtrType) String() string {
448	return fmt.Sprintf("ptr[%v, %v]", t.Dir(), t.Type.String())
449}
450
451func (t *PtrType) makeDefaultArg() Arg {
452	if t.Optional() {
453		return MakeNullPointerArg(t)
454	}
455	return MakePointerArg(t, 0, t.Type.makeDefaultArg())
456}
457
458func (t *PtrType) isDefaultArg(arg Arg) bool {
459	a := arg.(*PointerArg)
460	if t.Optional() {
461		return a.IsNull()
462	}
463	return a.Address == 0 && isDefault(a.Res)
464}
465
466type StructType struct {
467	Key     StructKey
468	FldName string
469	*StructDesc
470}
471
472func (t *StructType) String() string {
473	return t.Name()
474}
475
476func (t *StructType) FieldName() string {
477	return t.FldName
478}
479
480func (t *StructType) makeDefaultArg() Arg {
481	inner := make([]Arg, len(t.Fields))
482	for i, field := range t.Fields {
483		inner[i] = field.makeDefaultArg()
484	}
485	return MakeGroupArg(t, inner)
486}
487
488func (t *StructType) isDefaultArg(arg Arg) bool {
489	a := arg.(*GroupArg)
490	for _, elem := range a.Inner {
491		if !isDefault(elem) {
492			return false
493		}
494	}
495	return true
496}
497
498type UnionType struct {
499	Key     StructKey
500	FldName string
501	*StructDesc
502}
503
504func (t *UnionType) String() string {
505	return t.Name()
506}
507
508func (t *UnionType) FieldName() string {
509	return t.FldName
510}
511
512func (t *UnionType) makeDefaultArg() Arg {
513	return MakeUnionArg(t, t.Fields[0].makeDefaultArg())
514}
515
516func (t *UnionType) isDefaultArg(arg Arg) bool {
517	a := arg.(*UnionArg)
518	return a.Option.Type().FieldName() == t.Fields[0].FieldName() && isDefault(a.Option)
519}
520
521type StructDesc struct {
522	TypeCommon
523	Fields    []Type
524	AlignAttr uint64
525}
526
527func (t *StructDesc) FieldName() string {
528	panic("must not be called")
529}
530
531type StructKey struct {
532	Name string
533	Dir  Dir
534}
535
536type KeyedStruct struct {
537	Key  StructKey
538	Desc *StructDesc
539}
540
541type ConstValue struct {
542	Name  string
543	Value uint64
544}
545
546func ForeachType(meta *Syscall, f func(Type)) {
547	seen := make(map[*StructDesc]bool)
548	var rec func(t Type)
549	rec = func(t Type) {
550		f(t)
551		switch a := t.(type) {
552		case *PtrType:
553			rec(a.Type)
554		case *ArrayType:
555			rec(a.Type)
556		case *StructType:
557			if seen[a.StructDesc] {
558				return // prune recursion via pointers to structs/unions
559			}
560			seen[a.StructDesc] = true
561			for _, f := range a.Fields {
562				rec(f)
563			}
564		case *UnionType:
565			if seen[a.StructDesc] {
566				return // prune recursion via pointers to structs/unions
567			}
568			seen[a.StructDesc] = true
569			for _, opt := range a.Fields {
570				rec(opt)
571			}
572		case *ResourceType, *BufferType, *VmaType, *LenType,
573			*FlagsType, *ConstType, *IntType, *ProcType, *CsumType:
574		default:
575			panic("unknown type")
576		}
577	}
578	for _, t := range meta.Args {
579		rec(t)
580	}
581	if meta.Ret != nil {
582		rec(meta.Ret)
583	}
584}
585