diff options
| author | Hrutvik Kanabar <hrutvik@google.com> | 2022-09-20 14:43:25 +0000 |
|---|---|---|
| committer | Marco Elver <me@marcoelver.com> | 2022-09-22 16:42:04 +0200 |
| commit | 3fddc7194573e00eabde07dbb8ff17b025eb5c75 (patch) | |
| tree | 666f974b48e810491fc10070d8176acbf881c3ac /prog/mutation.go | |
| parent | 5088f152247b1ec7659f72a05309254ca1b2b1d7 (diff) | |
pkg/mgrconfig, prog, syz-fuzzer: manager-configurable syscall mutation
Allow manager configuration to specify that certain syscalls should not
be mutated. This is expected to be useful when mutating certain syscalls
is unlikely to produce interesting executions. For example, mutating a
`syz_mount_image` call will likely produce a corrupt image.
Some implementation details:
- Add a `no_mutate_syscalls` manager config entry, with the same format
as `enable_syscalls`. Ensure this is parsed and stored in the config
as a set of syscall IDs.
- Send this set to fuzzers when they connect to their managers via RPC.
Ensure each fuzzer stores a copy of the set.
- When mutating arguments of a syscall, check first whether it has been
specified as non-mutatable.
- For all mutations not managed by a `syz-manager`, retain previous
behaviour by ensuring that no syscalls are considered non-mutable.
Diffstat (limited to 'prog/mutation.go')
| -rw-r--r-- | prog/mutation.go | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/prog/mutation.go b/prog/mutation.go index b03987671..ca53b1c7b 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -16,22 +16,24 @@ const maxBlobLen = uint64(100 << 10) // Mutate program p. // -// p: The program to mutate. -// rs: Random source. -// ncalls: The allowed maximum calls in mutated program. -// ct: ChoiceTable for syscalls. -// corpus: The entire corpus, including original program p. -func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Prog) { +// p: The program to mutate. +// rs: Random source. +// ncalls: The allowed maximum calls in mutated program. +// ct: ChoiceTable for syscalls. +// noMutate: Set of IDs of syscalls which should not be mutated. +// corpus: The entire corpus, including original program p. +func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, noMutate map[int]bool, corpus []*Prog) { r := newRand(p.Target, rs) if ncalls < len(p.Calls) { ncalls = len(p.Calls) } ctx := &mutator{ - p: p, - r: r, - ncalls: ncalls, - ct: ct, - corpus: corpus, + p: p, + r: r, + ncalls: ncalls, + ct: ct, + noMutate: noMutate, + corpus: corpus, } for stop, ok := false, false; !stop; stop = ok && len(p.Calls) != 0 && r.oneOf(3) { switch { @@ -59,11 +61,12 @@ func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Pro // Internal state required for performing mutations -- currently this matches // the arguments passed to Mutate(). type mutator struct { - p *Prog // The program to mutate. - r *randGen // The randGen instance. - ncalls int // The allowed maximum calls in mutated program. - ct *ChoiceTable // ChoiceTable for syscalls. - corpus []*Prog // The entire corpus, including original program p. + p *Prog // The program to mutate. + r *randGen // The randGen instance. + ncalls int // The allowed maximum calls in mutated program. + ct *ChoiceTable // ChoiceTable for syscalls. + noMutate map[int]bool // Set of IDs of syscalls which should not be mutated. + corpus []*Prog // The entire corpus, including original program p. } // This function selects a random other program p0 out of the corpus, and @@ -93,6 +96,9 @@ func (ctx *mutator) squashAny() bool { return false } ptr := complexPtrs[r.Intn(len(complexPtrs))] + if ctx.noMutate[ptr.call.Meta.ID] { + return false + } if !p.Target.isAnyPtr(ptr.arg.Type()) { p.Target.squashPtr(ptr.arg) } @@ -172,6 +178,9 @@ func (ctx *mutator) mutateArg() bool { return false } c := p.Calls[idx] + if ctx.noMutate[c.Meta.ID] { + return false + } updateSizes := true for stop, ok := false, false; !stop; stop = ok && r.oneOf(3) { ok = true |
