github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/prog/rand.go (about)

     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  
     4  package prog
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"math"
    10  	"math/rand"
    11  	"path/filepath"
    12  	"sort"
    13  	"strings"
    14  
    15  	"github.com/google/syzkaller/pkg/ifuzz"
    16  )
    17  
    18  const (
    19  	// "Recommended" number of calls in programs that we try to aim at during fuzzing.
    20  	RecommendedCalls = 30
    21  	// "Recommended" max number of calls in programs.
    22  	// If we receive longer programs from hub/corpus we discard them.
    23  	MaxCalls = 40
    24  )
    25  
    26  type randGen struct {
    27  	*rand.Rand
    28  	target             *Target
    29  	inGenerateResource bool
    30  	inPatchConditional bool
    31  	recDepth           map[string]int
    32  }
    33  
    34  func newRand(target *Target, rs rand.Source) *randGen {
    35  	return &randGen{
    36  		Rand:     rand.New(rs),
    37  		target:   target,
    38  		recDepth: make(map[string]int),
    39  	}
    40  }
    41  
    42  func (r *randGen) rand(n int) uint64 {
    43  	return uint64(r.Intn(n))
    44  }
    45  
    46  func (r *randGen) randRange(begin, end uint64) uint64 {
    47  	return begin + uint64(r.Intn(int(end-begin+1)))
    48  }
    49  
    50  func (r *randGen) bin() bool {
    51  	return r.Intn(2) == 0
    52  }
    53  
    54  func (r *randGen) oneOf(n int) bool {
    55  	return r.Intn(n) == 0
    56  }
    57  
    58  func (r *randGen) rand64() uint64 {
    59  	v := uint64(r.Int63())
    60  	if r.bin() {
    61  		v |= 1 << 63
    62  	}
    63  	return v
    64  }
    65  
    66  var (
    67  	// Some potentially interesting integers.
    68  	specialInts = []uint64{
    69  		0, 1, 31, 32, 63, 64, 127, 128,
    70  		129, 255, 256, 257, 511, 512,
    71  		1023, 1024, 1025, 2047, 2048, 4095, 4096,
    72  		(1 << 15) - 1, (1 << 15), (1 << 15) + 1,
    73  		(1 << 16) - 1, (1 << 16), (1 << 16) + 1,
    74  		(1 << 31) - 1, (1 << 31), (1 << 31) + 1,
    75  		(1 << 32) - 1, (1 << 32), (1 << 32) + 1,
    76  		(1 << 63) - 1, (1 << 63), (1 << 63) + 1,
    77  		(1 << 64) - 1,
    78  	}
    79  	// The indexes (exclusive) for the maximum specialInts values that fit in 1, 2, ... 8 bytes.
    80  	specialIntIndex [9]int
    81  )
    82  
    83  func init() {
    84  	sort.Slice(specialInts, func(i, j int) bool {
    85  		return specialInts[i] < specialInts[j]
    86  	})
    87  	for i := range specialIntIndex {
    88  		bitSize := uint64(8 * i)
    89  		specialIntIndex[i] = sort.Search(len(specialInts), func(i int) bool {
    90  			return specialInts[i]>>bitSize != 0
    91  		})
    92  	}
    93  }
    94  
    95  func (r *randGen) randInt64() uint64 {
    96  	return r.randInt(64)
    97  }
    98  
    99  func (r *randGen) randInt(bits uint64) uint64 {
   100  	v := r.rand64()
   101  	switch {
   102  	case r.nOutOf(100, 182):
   103  		v %= 10
   104  	case bits >= 8 && r.nOutOf(50, 82):
   105  		v = specialInts[r.Intn(specialIntIndex[bits/8])]
   106  	case r.nOutOf(10, 32):
   107  		v %= 256
   108  	case r.nOutOf(10, 22):
   109  		v %= 4 << 10
   110  	case r.nOutOf(10, 12):
   111  		v %= 64 << 10
   112  	default:
   113  		v %= 1 << 31
   114  	}
   115  	switch {
   116  	case r.nOutOf(100, 107):
   117  	case r.nOutOf(5, 7):
   118  		v = uint64(-int64(v))
   119  	default:
   120  		v <<= uint(r.Intn(int(bits)))
   121  	}
   122  	return truncateToBitSize(v, bits)
   123  }
   124  
   125  func truncateToBitSize(v, bitSize uint64) uint64 {
   126  	if bitSize == 0 || bitSize > 64 {
   127  		panic(fmt.Sprintf("invalid bitSize value: %d", bitSize))
   128  	}
   129  	return v & uint64(1<<bitSize-1)
   130  }
   131  
   132  func (r *randGen) randRangeInt(begin, end, bitSize, align uint64) uint64 {
   133  	if r.oneOf(100) {
   134  		return r.randInt(bitSize)
   135  	}
   136  	if align != 0 {
   137  		if begin == 0 && int64(end) == -1 {
   138  			// Special [0:-1] range for all possible values.
   139  			end = uint64(1<<bitSize - 1)
   140  		}
   141  		endAlign := (end - begin) / align
   142  		return begin + r.randRangeInt(0, endAlign, bitSize, 0)*align
   143  	}
   144  	return begin + (r.Uint64() % (end - begin + 1))
   145  }
   146  
   147  // biasedRand returns a random int in range [0..n),
   148  // probability of n-1 is k times higher than probability of 0.
   149  func (r *randGen) biasedRand(n, k int) int {
   150  	nf, kf := float64(n), float64(k)
   151  	rf := nf * (kf/2 + 1) * r.Float64()
   152  	bf := (-1 + math.Sqrt(1+2*kf*rf/nf)) * nf / kf
   153  	return int(bf)
   154  }
   155  
   156  func (r *randGen) randArrayLen() uint64 {
   157  	const maxLen = 10
   158  	// biasedRand produces: 10, 9, ..., 1, 0,
   159  	// we want: 1, 2, ..., 9, 10, 0
   160  	return uint64(maxLen-r.biasedRand(maxLen+1, 10)+1) % (maxLen + 1)
   161  }
   162  
   163  func (r *randGen) randBufLen() (n uint64) {
   164  	switch {
   165  	case r.nOutOf(50, 56):
   166  		n = r.rand(256)
   167  	case r.nOutOf(5, 6):
   168  		n = 4 << 10
   169  	}
   170  	return
   171  }
   172  
   173  func (r *randGen) randPageCount() (n uint64) {
   174  	switch {
   175  	case r.nOutOf(100, 106):
   176  		n = r.rand(4) + 1
   177  	case r.nOutOf(5, 6):
   178  		n = r.rand(20) + 1
   179  	default:
   180  		n = (r.rand(3) + 1) * r.target.NumPages / 4
   181  	}
   182  	return
   183  }
   184  
   185  // Change a flag value or generate a new one.
   186  // If you are changing this function, run TestFlags and examine effect of results.
   187  func (r *randGen) flags(vv []uint64, bitmask bool, oldVal uint64) uint64 {
   188  	// Get these simpler cases out of the way first.
   189  	// Once in a while we want to return completely random values,
   190  	// or 0 which is frequently special.
   191  	if r.oneOf(100) {
   192  		return r.rand64()
   193  	}
   194  	if r.oneOf(50) {
   195  		return 0
   196  	}
   197  	if !bitmask && oldVal != 0 && r.oneOf(100) {
   198  		// Slightly increment/decrement the old value.
   199  		// This is especially important during mutation when len(vv) == 1,
   200  		// otherwise in that case we produce almost no randomness
   201  		// (the value is always mutated to 0).
   202  		inc := uint64(1)
   203  		if r.bin() {
   204  			inc = ^uint64(0)
   205  		}
   206  		v := oldVal + inc
   207  		for r.bin() {
   208  			v += inc
   209  		}
   210  		return v
   211  	}
   212  	if len(vv) == 1 {
   213  		// This usually means that value or 0,
   214  		// at least that's our best (and only) bet.
   215  		if r.bin() {
   216  			return 0
   217  		}
   218  		return vv[0]
   219  	}
   220  	if !bitmask && !r.oneOf(10) {
   221  		// Enumeration, so just choose one of the values.
   222  		return vv[r.rand(len(vv))]
   223  	}
   224  	if r.oneOf(len(vv) + 4) {
   225  		return 0
   226  	}
   227  	// Flip rand bits. Do this for non-bitmask sometimes
   228  	// because we may have detected bitmask incorrectly for complex cases
   229  	// (e.g. part of the vlaue is bitmask and another is not).
   230  	v := oldVal
   231  	if v != 0 && r.oneOf(10) {
   232  		v = 0 // Ignore the old value sometimes.
   233  	}
   234  	// We don't want to return 0 here, because we already given 0
   235  	// fixed probability above (otherwise we get 0 too frequently).
   236  	// Note: this loop can hang if all values are equal to 0. We don't generate such flags in the compiler now,
   237  	// but it used to hang occasionally, so we keep the try < 10 logic b/c we don't have a local check for values.
   238  	for try := 0; try < 10 && (v == 0 || r.nOutOf(2, 3)); try++ {
   239  		flag := vv[r.rand(len(vv))]
   240  		if r.oneOf(20) {
   241  			// Try choosing adjacent bit values in case we forgot
   242  			// to add all relevant flags to the descriptions.
   243  			if r.bin() {
   244  				flag >>= 1
   245  			} else {
   246  				flag <<= 1
   247  			}
   248  		}
   249  		v ^= flag
   250  	}
   251  	return v
   252  }
   253  
   254  func (r *randGen) filename(s *state, typ *BufferType) string {
   255  	fn := r.filenameImpl(s)
   256  	if fn != "" && fn[len(fn)-1] == 0 {
   257  		panic(fmt.Sprintf("zero-terminated filename: %q", fn))
   258  	}
   259  	if escapingFilename(fn) {
   260  		panic(fmt.Sprintf("sandbox escaping file name %q, s.files are %v", fn, s.files))
   261  	}
   262  	if !typ.Varlen() {
   263  		size := typ.Size()
   264  		if uint64(len(fn)) < size {
   265  			fn += string(make([]byte, size-uint64(len(fn))))
   266  		}
   267  		fn = fn[:size]
   268  	} else if !typ.NoZ {
   269  		fn += "\x00"
   270  	}
   271  	return fn
   272  }
   273  
   274  func escapingFilename(file string) bool {
   275  	file = filepath.Clean(file)
   276  	return len(file) >= 1 && file[0] == '/' ||
   277  		len(file) >= 2 && file[0] == '.' && file[1] == '.'
   278  }
   279  
   280  var specialFiles = []string{"", "."}
   281  
   282  const specialFileLenPad = "a"
   283  
   284  func (r *randGen) filenameImpl(s *state) string {
   285  	if r.oneOf(100) {
   286  		return specialFiles[r.Intn(len(specialFiles))]
   287  	}
   288  	if len(s.files) == 0 || r.oneOf(10) {
   289  		// Generate a new name.
   290  		dir := "."
   291  		if r.oneOf(2) && len(s.files) != 0 {
   292  			dir = r.randFromMap(s.files)
   293  			if dir != "" && dir[len(dir)-1] == 0 {
   294  				dir = dir[:len(dir)-1]
   295  			}
   296  			if r.oneOf(10) && filepath.Clean(dir)[0] != '.' {
   297  				dir += "/.."
   298  			}
   299  		}
   300  		for i := 0; ; i++ {
   301  			f := fmt.Sprintf("%v/file%v", dir, i)
   302  			if r.oneOf(100) {
   303  				// Make file name very long using target.SpecialFileLenghts consts.
   304  				// Add/subtract some small const to account for our file name prefix
   305  				// and potential kernel off-by-one's.
   306  				fileLen := r.randFilenameLength()
   307  				if add := fileLen - len(f); add > 0 {
   308  					f += strings.Repeat(specialFileLenPad, add)
   309  				}
   310  			}
   311  			if !s.files[f] {
   312  				return f
   313  			}
   314  		}
   315  	}
   316  	return r.randFromMap(s.files)
   317  }
   318  
   319  func (r *randGen) randFilenameLength() int {
   320  	off := r.biasedRand(10, 5)
   321  	if r.bin() {
   322  		off = -off
   323  	}
   324  	lens := r.target.SpecialFileLenghts
   325  	res := lens[r.Intn(len(lens))] + off
   326  	if res < 0 {
   327  		res = 0
   328  	}
   329  	return res
   330  }
   331  
   332  func (r *randGen) randFromMap(m map[string]bool) string {
   333  	files := make([]string, 0, len(m))
   334  	for f := range m {
   335  		files = append(files, f)
   336  	}
   337  	sort.Strings(files)
   338  	return files[r.Intn(len(files))]
   339  }
   340  
   341  func (r *randGen) randString(s *state, t *BufferType) []byte {
   342  	if len(t.Values) != 0 {
   343  		return []byte(t.Values[r.Intn(len(t.Values))])
   344  	}
   345  	if len(s.strings) != 0 && r.bin() {
   346  		// Return an existing string.
   347  		// TODO(dvyukov): make s.strings indexed by string SubKind.
   348  		return []byte(r.randFromMap(s.strings))
   349  	}
   350  	punct := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '\\',
   351  		'/', ':', '.', ',', '-', '\'', '[', ']', '{', '}'}
   352  	buf := new(bytes.Buffer)
   353  	for r.nOutOf(3, 4) {
   354  		if r.nOutOf(10, 11) {
   355  			buf.Write([]byte{punct[r.Intn(len(punct))]})
   356  		} else {
   357  			buf.Write([]byte{byte(r.Intn(256))})
   358  		}
   359  	}
   360  	if r.oneOf(100) == t.NoZ {
   361  		buf.Write([]byte{0})
   362  	}
   363  	return buf.Bytes()
   364  }
   365  
   366  func (r *randGen) allocAddr(s *state, typ Type, dir Dir, size uint64, data Arg) *PointerArg {
   367  	return MakePointerArg(typ, dir, s.ma.alloc(r, size, data.Type().Alignment()), data)
   368  }
   369  
   370  func (r *randGen) allocVMA(s *state, typ Type, dir Dir, numPages uint64) *PointerArg {
   371  	page := s.va.alloc(r, numPages)
   372  	return MakeVmaPointerArg(typ, dir, page*r.target.PageSize, numPages*r.target.PageSize)
   373  }
   374  
   375  func (r *randGen) createResource(s *state, res *ResourceType, dir Dir) (Arg, []*Call) {
   376  	if !r.inGenerateResource {
   377  		panic("inGenerateResource is not set")
   378  	}
   379  	kind := res.Desc.Name
   380  	// Find calls that produce the necessary resources.
   381  	ctors := r.enabledCtors(s, kind)
   382  	// We may have no resources, but still be in createResource due to ANYRES.
   383  	if len(r.target.resourceMap) != 0 && r.oneOf(1000) {
   384  		// Spoof resource subkind.
   385  		var all []string
   386  		for kind1 := range r.target.resourceMap {
   387  			if r.target.isCompatibleResource(res.Desc.Kind[0], kind1) {
   388  				all = append(all, kind1)
   389  			}
   390  		}
   391  		if len(all) == 0 {
   392  			panic(fmt.Sprintf("got no spoof resources for %v in %v/%v",
   393  				kind, r.target.OS, r.target.Arch))
   394  		}
   395  		sort.Strings(all)
   396  		kind1 := all[r.Intn(len(all))]
   397  		ctors1 := r.enabledCtors(s, kind1)
   398  		if len(ctors1) != 0 {
   399  			// Don't use the resource for which we don't have any ctors.
   400  			// It's fine per-se because below we just return nil in such case.
   401  			// But in TestCreateResource tests we want to ensure that we don't fail
   402  			// to create non-optional resources, and if we spoof a non-optional
   403  			// resource with ctors with a optional resource w/o ctors, then that check will fail.
   404  			kind, ctors = kind1, ctors1
   405  		}
   406  	}
   407  	if len(ctors) == 0 {
   408  		// We may not have any constructors for optional input resources because we don't disable
   409  		// syscalls based on optional inputs resources w/o ctors in TransitivelyEnabledCalls.
   410  		return nil, nil
   411  	}
   412  	// Now we have a set of candidate calls that can create the necessary resource.
   413  	// Generate one of them.
   414  	var meta *Syscall
   415  	// Prefer precise constructors.
   416  	var precise []*Syscall
   417  	for _, info := range ctors {
   418  		if info.Precise {
   419  			precise = append(precise, info.Call)
   420  		}
   421  	}
   422  	if len(precise) > 0 {
   423  		// If the argument is optional, it's not guaranteed that there'd be a
   424  		// precise constructor.
   425  		meta = precise[r.Intn(len(precise))]
   426  	}
   427  	if meta == nil || r.oneOf(3) {
   428  		// Sometimes just take a random one.
   429  		meta = ctors[r.Intn(len(ctors))].Call
   430  	}
   431  
   432  	calls := r.generateParticularCall(s, meta)
   433  	s1 := newState(r.target, s.ct, nil)
   434  	s1.analyze(calls[len(calls)-1])
   435  	// Now see if we have what we want.
   436  	var allres []*ResultArg
   437  	for kind1, res1 := range s1.resources {
   438  		if r.target.isCompatibleResource(kind, kind1) {
   439  			allres = append(allres, res1...)
   440  		}
   441  	}
   442  	sort.SliceStable(allres, func(i, j int) bool {
   443  		return allres[i].Type().Name() < allres[j].Type().Name()
   444  	})
   445  	if len(allres) == 0 {
   446  		panic(fmt.Sprintf("failed to create a resource %v (%v) with %v",
   447  			res.Desc.Kind[0], kind, meta.Name))
   448  	}
   449  	arg := MakeResultArg(res, dir, allres[r.Intn(len(allres))], 0)
   450  	return arg, calls
   451  }
   452  
   453  func (r *randGen) enabledCtors(s *state, kind string) []ResourceCtor {
   454  	var ret []ResourceCtor
   455  	for _, info := range r.target.resourceCtors[kind] {
   456  		if s.ct.Generatable(info.Call.ID) {
   457  			ret = append(ret, info)
   458  		}
   459  	}
   460  	return ret
   461  }
   462  
   463  func (r *randGen) generateText(kind TextKind) []byte {
   464  	switch kind {
   465  	case TextTarget:
   466  		if cfg := createTargetIfuzzConfig(r.target); cfg != nil {
   467  			return ifuzz.Generate(cfg, r.Rand)
   468  		}
   469  		text := make([]byte, 50)
   470  		for i := range text {
   471  			text[i] = byte(r.Intn(256))
   472  		}
   473  		return text
   474  	default:
   475  		cfg := createIfuzzConfig(kind)
   476  		return ifuzz.Generate(cfg, r.Rand)
   477  	}
   478  }
   479  
   480  func (r *randGen) mutateText(kind TextKind, text []byte) []byte {
   481  	switch kind {
   482  	case TextTarget:
   483  		if cfg := createTargetIfuzzConfig(r.target); cfg != nil {
   484  			return ifuzz.Mutate(cfg, r.Rand, text)
   485  		}
   486  		return mutateData(r, text, 40, 60)
   487  	default:
   488  		cfg := createIfuzzConfig(kind)
   489  		return ifuzz.Mutate(cfg, r.Rand, text)
   490  	}
   491  }
   492  
   493  func createTargetIfuzzConfig(target *Target) *ifuzz.Config {
   494  	cfg := &ifuzz.Config{
   495  		Len:  10,
   496  		Priv: false,
   497  		Exec: true,
   498  		MemRegions: []ifuzz.MemRegion{
   499  			{Start: target.DataOffset, Size: target.NumPages * target.PageSize},
   500  		},
   501  	}
   502  	for _, p := range target.SpecialPointers {
   503  		cfg.MemRegions = append(cfg.MemRegions, ifuzz.MemRegion{
   504  			Start: p & ^target.PageSize, Size: p & ^target.PageSize + target.PageSize,
   505  		})
   506  	}
   507  	switch target.Arch {
   508  	case "amd64":
   509  		cfg.Mode = ifuzz.ModeLong64
   510  		cfg.Arch = ifuzz.ArchX86
   511  	case "386":
   512  		cfg.Mode = ifuzz.ModeProt32
   513  		cfg.Arch = ifuzz.ArchX86
   514  	case "ppc64":
   515  		cfg.Mode = ifuzz.ModeLong64
   516  		cfg.Arch = ifuzz.ArchPowerPC
   517  	case "arm64":
   518  		cfg.Mode = ifuzz.ModeLong64
   519  		cfg.Arch = ifuzz.ArchArm64
   520  	default:
   521  		return nil
   522  	}
   523  	return cfg
   524  }
   525  
   526  func createIfuzzConfig(kind TextKind) *ifuzz.Config {
   527  	cfg := &ifuzz.Config{
   528  		Len:  10,
   529  		Priv: true,
   530  		Exec: true,
   531  		MemRegions: []ifuzz.MemRegion{
   532  			{Start: 0 << 12, Size: 1 << 12},
   533  			{Start: 1 << 12, Size: 1 << 12},
   534  			{Start: 2 << 12, Size: 1 << 12},
   535  			{Start: 3 << 12, Size: 1 << 12},
   536  			{Start: 4 << 12, Size: 1 << 12},
   537  			{Start: 5 << 12, Size: 1 << 12},
   538  			{Start: 6 << 12, Size: 1 << 12},
   539  			{Start: 7 << 12, Size: 1 << 12},
   540  			{Start: 8 << 12, Size: 1 << 12},
   541  			{Start: 9 << 12, Size: 1 << 12},
   542  			{Start: 0xfec00000, Size: 0x100}, // ioapic
   543  		},
   544  	}
   545  	switch kind {
   546  	case TextX86Real:
   547  		cfg.Mode = ifuzz.ModeReal16
   548  		cfg.Arch = ifuzz.ArchX86
   549  	case TextX86bit16:
   550  		cfg.Mode = ifuzz.ModeProt16
   551  		cfg.Arch = ifuzz.ArchX86
   552  	case TextX86bit32:
   553  		cfg.Mode = ifuzz.ModeProt32
   554  		cfg.Arch = ifuzz.ArchX86
   555  	case TextX86bit64:
   556  		cfg.Mode = ifuzz.ModeLong64
   557  		cfg.Arch = ifuzz.ArchX86
   558  	case TextPpc64:
   559  		cfg.Mode = ifuzz.ModeLong64
   560  		cfg.Arch = ifuzz.ArchPowerPC
   561  	case TextArm64:
   562  		cfg.Mode = ifuzz.ModeLong64
   563  		cfg.Arch = ifuzz.ArchArm64
   564  	default:
   565  		panic(fmt.Sprintf("unknown text kind: %v", kind))
   566  	}
   567  	return cfg
   568  }
   569  
   570  // nOutOf returns true n out of outOf times.
   571  func (r *randGen) nOutOf(n, outOf int) bool {
   572  	if n <= 0 || n >= outOf {
   573  		panic("bad probability")
   574  	}
   575  	v := r.Intn(outOf)
   576  	return v < n
   577  }
   578  
   579  func (r *randGen) generateCall(s *state, p *Prog, insertionPoint int) []*Call {
   580  	biasCall := -1
   581  	if insertionPoint > 0 {
   582  		// Choosing the base call is based on the insertion point of the new calls sequence.
   583  		insertionCall := p.Calls[r.Intn(insertionPoint)].Meta
   584  		if !insertionCall.Attrs.NoGenerate {
   585  			// We must be careful not to bias towards a non-generatable call.
   586  			biasCall = insertionCall.ID
   587  		}
   588  	}
   589  	idx := s.ct.choose(r.Rand, biasCall)
   590  	meta := r.target.Syscalls[idx]
   591  	return r.generateParticularCall(s, meta)
   592  }
   593  
   594  func (r *randGen) generateParticularCall(s *state, meta *Syscall) (calls []*Call) {
   595  	if meta.Attrs.Disabled {
   596  		panic(fmt.Sprintf("generating disabled call %v", meta.Name))
   597  	}
   598  	if meta.Attrs.NoGenerate {
   599  		panic(fmt.Sprintf("generating no_generate call: %v", meta.Name))
   600  	}
   601  	c := MakeCall(meta, nil)
   602  	c.Args, calls = r.generateArgs(s, meta.Args, DirIn)
   603  	moreCalls, _ := r.patchConditionalFields(c, s)
   604  	r.target.assignSizesCall(c)
   605  	return append(append(calls, moreCalls...), c)
   606  }
   607  
   608  // GenerateAllSyzProg generates a program that contains all pseudo syz_ calls for testing.
   609  func (target *Target) GenerateAllSyzProg(rs rand.Source) *Prog {
   610  	p := &Prog{
   611  		Target: target,
   612  	}
   613  	r := newRand(target, rs)
   614  	s := newState(target, target.DefaultChoiceTable(), nil)
   615  	for _, meta := range target.PseudoSyscalls() {
   616  		calls := r.generateParticularCall(s, meta)
   617  		for _, c := range calls {
   618  			s.analyze(c)
   619  			p.Calls = append(p.Calls, c)
   620  		}
   621  	}
   622  	if err := p.validate(); err != nil {
   623  		panic(err)
   624  	}
   625  	return p
   626  }
   627  
   628  // PseudoSyscalls selects one *Syscall for each pseudosyscall.
   629  func (target *Target) PseudoSyscalls() []*Syscall {
   630  	handled := make(map[string]bool)
   631  	var ret []*Syscall
   632  	for _, meta := range target.Syscalls {
   633  		if !strings.HasPrefix(meta.CallName, "syz_") ||
   634  			handled[meta.CallName] ||
   635  			meta.Attrs.Disabled ||
   636  			meta.Attrs.NoGenerate {
   637  			continue
   638  		}
   639  		ret = append(ret, meta)
   640  		handled[meta.CallName] = true
   641  	}
   642  	return ret
   643  }
   644  
   645  // GenSampleProg generates a single sample program for the call.
   646  func (target *Target) GenSampleProg(meta *Syscall, rs rand.Source) *Prog {
   647  	r := newRand(target, rs)
   648  	s := newState(target, target.DefaultChoiceTable(), nil)
   649  	p := &Prog{
   650  		Target: target,
   651  	}
   652  	for _, c := range r.generateParticularCall(s, meta) {
   653  		s.analyze(c)
   654  		p.Calls = append(p.Calls, c)
   655  	}
   656  	if err := p.validate(); err != nil {
   657  		panic(err)
   658  	}
   659  	return p
   660  }
   661  
   662  // DataMmapProg creates program that maps data segment.
   663  // Also used for testing as the simplest program.
   664  func (target *Target) DataMmapProg() *Prog {
   665  	return &Prog{
   666  		Target:   target,
   667  		Calls:    target.MakeDataMmap(),
   668  		isUnsafe: true,
   669  	}
   670  }
   671  
   672  func (r *randGen) generateArgs(s *state, fields []Field, dir Dir) ([]Arg, []*Call) {
   673  	var calls []*Call
   674  	args := make([]Arg, len(fields))
   675  
   676  	// Generate all args. Size args have the default value 0 for now.
   677  	for i, field := range fields {
   678  		arg, calls1 := r.generateArg(s, field.Type, field.Dir(dir))
   679  		if arg == nil {
   680  			panic(fmt.Sprintf("generated arg is nil for field '%v', fields: %+v", field.Type.Name(), fields))
   681  		}
   682  		args[i] = arg
   683  		calls = append(calls, calls1...)
   684  	}
   685  
   686  	return args, calls
   687  }
   688  
   689  func (r *randGen) generateArg(s *state, typ Type, dir Dir) (arg Arg, calls []*Call) {
   690  	return r.generateArgImpl(s, typ, dir, false)
   691  }
   692  
   693  func (r *randGen) generateArgImpl(s *state, typ Type, dir Dir, ignoreSpecial bool) (arg Arg, calls []*Call) {
   694  	if dir == DirOut {
   695  		// No need to generate something interesting for output scalar arguments.
   696  		// But we still need to generate the argument itself so that it can be referenced
   697  		// in subsequent calls. For the same reason we do generate pointer/array/struct
   698  		// output arguments (their elements can be referenced in subsequent calls).
   699  		switch typ.(type) {
   700  		case *IntType, *FlagsType, *ConstType, *ProcType, *VmaType, *ResourceType:
   701  			return typ.DefaultArg(dir), nil
   702  		}
   703  	}
   704  
   705  	if typ.Optional() && r.oneOf(5) {
   706  		if res, ok := typ.(*ResourceType); ok {
   707  			v := res.Desc.Values[r.Intn(len(res.Desc.Values))]
   708  			return MakeResultArg(typ, dir, nil, v), nil
   709  		}
   710  		return typ.DefaultArg(dir), nil
   711  	}
   712  
   713  	// Allow infinite recursion for optional pointers.
   714  	if pt, ok := typ.(*PtrType); ok && typ.Optional() {
   715  		switch pt.Elem.(type) {
   716  		case *StructType, *ArrayType, *UnionType:
   717  			name := pt.Elem.Name()
   718  			r.recDepth[name]++
   719  			defer func() {
   720  				r.recDepth[name]--
   721  				if r.recDepth[name] == 0 {
   722  					delete(r.recDepth, name)
   723  				}
   724  			}()
   725  			if r.recDepth[name] >= 3 {
   726  				return MakeSpecialPointerArg(typ, dir, 0), nil
   727  			}
   728  		}
   729  	}
   730  
   731  	if !ignoreSpecial && dir != DirOut {
   732  		switch typ.(type) {
   733  		case *StructType, *UnionType:
   734  			if gen := r.target.SpecialTypes[typ.Name()]; gen != nil {
   735  				return gen(&Gen{r, s}, typ, dir, nil)
   736  			}
   737  		}
   738  	}
   739  
   740  	return typ.generate(r, s, dir)
   741  }
   742  
   743  func (a *ResourceType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   744  	canRecurse := false
   745  	if !r.inGenerateResource {
   746  		// Don't allow recursion for resourceCentric/createResource.
   747  		// That can lead to generation of huge programs and may be very slow
   748  		// (esp. if we are generating some failing attempts in createResource already).
   749  		r.inGenerateResource = true
   750  		defer func() { r.inGenerateResource = false }()
   751  		canRecurse = true
   752  	}
   753  	if canRecurse && r.nOutOf(8, 10) ||
   754  		!canRecurse && r.nOutOf(19, 20) {
   755  		arg = r.existingResource(s, a, dir)
   756  		if arg != nil {
   757  			return
   758  		}
   759  	}
   760  	if canRecurse {
   761  		if r.oneOf(4) {
   762  			arg, calls = r.resourceCentric(s, a, dir)
   763  			if arg != nil {
   764  				return
   765  			}
   766  		}
   767  		if r.nOutOf(4, 5) {
   768  			// If we could not reuse a resource, let's prefer resource creation over
   769  			// random int substitution.
   770  			arg, calls = r.createResource(s, a, dir)
   771  			if arg != nil {
   772  				return
   773  			}
   774  		}
   775  	}
   776  	special := a.SpecialValues()
   777  	arg = MakeResultArg(a, dir, nil, special[r.Intn(len(special))])
   778  	return
   779  }
   780  
   781  func (a *BufferType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   782  	switch a.Kind {
   783  	case BufferBlobRand, BufferBlobRange:
   784  		sz := r.randBufLen()
   785  		if a.Kind == BufferBlobRange {
   786  			sz = r.randRange(a.RangeBegin, a.RangeEnd)
   787  		}
   788  		if dir == DirOut {
   789  			return MakeOutDataArg(a, dir, sz), nil
   790  		}
   791  		data := make([]byte, sz)
   792  		for i := range data {
   793  			data[i] = byte(r.Intn(256))
   794  		}
   795  		return MakeDataArg(a, dir, data), nil
   796  	case BufferString:
   797  		data := r.randString(s, a)
   798  		if dir == DirOut {
   799  			return MakeOutDataArg(a, dir, uint64(len(data))), nil
   800  		}
   801  		return MakeDataArg(a, dir, data), nil
   802  	case BufferFilename:
   803  		if dir == DirOut {
   804  			var sz uint64
   805  			switch {
   806  			case !a.Varlen():
   807  				sz = a.Size()
   808  			case r.nOutOf(1, 3):
   809  				sz = r.rand(100)
   810  			default:
   811  				sz = uint64(r.randFilenameLength())
   812  			}
   813  			return MakeOutDataArg(a, dir, sz), nil
   814  		}
   815  		return MakeDataArg(a, dir, []byte(r.filename(s, a))), nil
   816  	case BufferGlob:
   817  		return MakeDataArg(a, dir, r.randString(s, a)), nil
   818  	case BufferText:
   819  		if dir == DirOut {
   820  			return MakeOutDataArg(a, dir, uint64(r.Intn(100))), nil
   821  		}
   822  		return MakeDataArg(a, dir, r.generateText(a.Text)), nil
   823  	case BufferCompressed:
   824  		panic(fmt.Sprintf("can't generate compressed type %v", a))
   825  	default:
   826  		panic("unknown buffer kind")
   827  	}
   828  }
   829  
   830  func (a *VmaType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   831  	npages := r.randPageCount()
   832  	if a.RangeBegin != 0 || a.RangeEnd != 0 {
   833  		npages = a.RangeBegin + uint64(r.Intn(int(a.RangeEnd-a.RangeBegin+1)))
   834  	}
   835  	return r.allocVMA(s, a, dir, npages), nil
   836  }
   837  
   838  func (a *FlagsType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   839  	return MakeConstArg(a, dir, r.flags(a.Vals, a.BitMask, 0)), nil
   840  }
   841  
   842  func (a *ConstType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   843  	return MakeConstArg(a, dir, a.Val), nil
   844  }
   845  
   846  func (a *IntType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   847  	bits := a.TypeBitSize()
   848  	v := r.randInt(bits)
   849  	switch a.Kind {
   850  	case IntRange:
   851  		v = r.randRangeInt(a.RangeBegin, a.RangeEnd, bits, a.Align)
   852  	}
   853  	return MakeConstArg(a, dir, v), nil
   854  }
   855  
   856  func (a *ProcType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   857  	return MakeConstArg(a, dir, r.rand(int(a.ValuesPerProc))), nil
   858  }
   859  
   860  func (a *ArrayType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   861  	var count uint64
   862  	switch a.Kind {
   863  	case ArrayRandLen:
   864  		count = r.randArrayLen()
   865  	case ArrayRangeLen:
   866  		count = r.randRange(a.RangeBegin, a.RangeEnd)
   867  	}
   868  	// The resource we are trying to generate may be in the array elements, so create at least 1.
   869  	if r.inGenerateResource && count == 0 {
   870  		count = 1
   871  	}
   872  	var inner []Arg
   873  	for i := uint64(0); i < count; i++ {
   874  		arg1, calls1 := r.generateArg(s, a.Elem, dir)
   875  		inner = append(inner, arg1)
   876  		calls = append(calls, calls1...)
   877  	}
   878  	return MakeGroupArg(a, dir, inner), calls
   879  }
   880  
   881  func (a *StructType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   882  	args, calls := r.generateArgs(s, a.Fields, dir)
   883  	group := MakeGroupArg(a, dir, args)
   884  	return group, calls
   885  }
   886  
   887  func (a *UnionType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   888  	if a.isConditional() {
   889  		// Conditions may reference other fields that may not have already
   890  		// been generated. We'll fill them in later.
   891  		return a.DefaultArg(dir), nil
   892  	}
   893  	index := r.Intn(len(a.Fields))
   894  	optType, optDir := a.Fields[index].Type, a.Fields[index].Dir(dir)
   895  	opt, calls := r.generateArg(s, optType, optDir)
   896  	return MakeUnionArg(a, dir, opt, index), calls
   897  }
   898  
   899  func (a *PtrType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   900  	// The resource we are trying to generate may be in the pointer,
   901  	// so don't try to create an empty special pointer during resource generation.
   902  	if !r.inGenerateResource && r.oneOf(1000) {
   903  		index := r.rand(len(r.target.SpecialPointers))
   904  		return MakeSpecialPointerArg(a, dir, index), nil
   905  	}
   906  	inner, calls := r.generateArg(s, a.Elem, a.ElemDir)
   907  	arg = r.allocAddr(s, a, dir, inner.Size(), inner)
   908  	return arg, calls
   909  }
   910  
   911  func (a *LenType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   912  	// Updated later in assignSizesCall.
   913  	return MakeConstArg(a, dir, 0), nil
   914  }
   915  
   916  func (a *CsumType) generate(r *randGen, s *state, dir Dir) (arg Arg, calls []*Call) {
   917  	// Filled at runtime by executor.
   918  	return MakeConstArg(a, dir, 0), nil
   919  }
   920  
   921  func (r *randGen) existingResource(s *state, res *ResourceType, dir Dir) Arg {
   922  	alltypes := make([][]*ResultArg, 0, len(s.resources))
   923  	for _, res1 := range s.resources {
   924  		alltypes = append(alltypes, res1)
   925  	}
   926  	sort.Slice(alltypes, func(i, j int) bool {
   927  		return alltypes[i][0].Type().Name() < alltypes[j][0].Type().Name()
   928  	})
   929  	var allres []*ResultArg
   930  	for _, res1 := range alltypes {
   931  		name1 := res1[0].Type().Name()
   932  		if r.target.isCompatibleResource(res.Desc.Name, name1) ||
   933  			r.oneOf(50) && r.target.isCompatibleResource(res.Desc.Kind[0], name1) {
   934  			allres = append(allres, res1...)
   935  		}
   936  	}
   937  	if len(allres) == 0 {
   938  		return nil
   939  	}
   940  	return MakeResultArg(res, dir, allres[r.Intn(len(allres))], 0)
   941  }
   942  
   943  // Finds a compatible resource with the type `t` and the calls that initialize that resource.
   944  func (r *randGen) resourceCentric(s *state, t *ResourceType, dir Dir) (arg Arg, calls []*Call) {
   945  	var p *Prog
   946  	var resource *ResultArg
   947  	for _, idx := range r.Perm(len(s.corpus)) {
   948  		corpusProg := s.corpus[idx]
   949  		resources := getCompatibleResources(corpusProg, t.TypeName, r)
   950  		if len(resources) == 0 {
   951  			continue
   952  		}
   953  		argMap := make(map[*ResultArg]*ResultArg)
   954  		p = corpusProg.cloneWithMap(argMap)
   955  		resource = argMap[resources[r.Intn(len(resources))]]
   956  		break
   957  	}
   958  
   959  	// No compatible resource was found.
   960  	if resource == nil {
   961  		return nil, nil
   962  	}
   963  
   964  	// Set that stores the resources that appear in the same calls with the selected resource.
   965  	relatedRes := map[*ResultArg]bool{resource: true}
   966  
   967  	// Remove unrelated calls from the program.
   968  	for idx := len(p.Calls) - 1; idx >= 0; idx-- {
   969  		includeCall := false
   970  		var newResources []*ResultArg
   971  		ForeachArg(p.Calls[idx], func(arg Arg, _ *ArgCtx) {
   972  			if a, ok := arg.(*ResultArg); ok {
   973  				if a.Res != nil && !relatedRes[a.Res] {
   974  					newResources = append(newResources, a.Res)
   975  				}
   976  				if relatedRes[a] || relatedRes[a.Res] {
   977  					includeCall = true
   978  				}
   979  			}
   980  		})
   981  		if !includeCall {
   982  			p.RemoveCall(idx)
   983  		} else {
   984  			for _, res := range newResources {
   985  				relatedRes[res] = true
   986  			}
   987  		}
   988  	}
   989  
   990  	// Selects a biased random length of the returned calls (more calls could offer more
   991  	// interesting programs). The values returned (n = len(calls): n, n-1, ..., 2.
   992  	biasedLen := 2 + r.biasedRand(len(calls)-1, 10)
   993  
   994  	// Removes the references that are not used anymore.
   995  	for i := biasedLen; i < len(calls); i++ {
   996  		p.RemoveCall(i)
   997  	}
   998  
   999  	return MakeResultArg(t, dir, resource, 0), p.Calls
  1000  }
  1001  
  1002  func getCompatibleResources(p *Prog, resourceType string, r *randGen) (resources []*ResultArg) {
  1003  	for _, c := range p.Calls {
  1004  		ForeachArg(c, func(arg Arg, _ *ArgCtx) {
  1005  			// Collect only initialized resources (the ones that are already used in other calls).
  1006  			a, ok := arg.(*ResultArg)
  1007  			if !ok || len(a.uses) == 0 || a.Dir() != DirOut {
  1008  				return
  1009  			}
  1010  			if !r.target.isCompatibleResource(resourceType, a.Type().Name()) {
  1011  				return
  1012  			}
  1013  			resources = append(resources, a)
  1014  		})
  1015  	}
  1016  	return resources
  1017  }