diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-11-20 17:30:23 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-11-21 08:46:20 +0100 |
| commit | 5405d2e2ed019de7452677eacfc7de9562a8ea12 (patch) | |
| tree | 7b2f9f488a4b57ce9a40e4d16bc263c2f00d8e48 /pkg/ifuzz/ifuzzimpl | |
| parent | 9bc78a846441516a33a7fd3b245380f463ba88ed (diff) | |
pkg/ifuzz: invert ifuzz and ifuzzimpl
ifuzzimpl imports the public interface package ifuzz
and prog package needs to import ifuzzimpl (implementation guts that
nobody outside of ifuzz should care about). This is not right.
Invert everything so that prog package only needs to import ifuzz
and ifuzz imports ifuzzimpl.
Diffstat (limited to 'pkg/ifuzz/ifuzzimpl')
| -rw-r--r-- | pkg/ifuzz/ifuzzimpl/ifuzzimpl.go | 180 |
1 files changed, 59 insertions, 121 deletions
diff --git a/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go b/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go index f1ea64f37..71485172c 100644 --- a/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go +++ b/pkg/ifuzz/ifuzzimpl/ifuzzimpl.go @@ -4,142 +4,80 @@ package ifuzzimpl import ( - "github.com/google/syzkaller/pkg/ifuzz" "math/rand" ) -var ( - Types = make(map[string]ifuzz.InsnSet) +const ( + ArchX86 = "x86" + ArchPowerPC = "powerpc" ) -func Register(arch string, insns ifuzz.InsnSet) { - Types[arch] = insns -} +var Arches = make(map[string]InsnSet) -// ModeInsns returns list of all instructions for the given mode. -func ModeInsns(cfg *ifuzz.Config) []ifuzz.Insn { - insnset := Types[cfg.Arch] - if cfg.Mode < 0 || cfg.Mode >= ifuzz.ModeLast { - panic("bad mode") - } - var insns []ifuzz.Insn - insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypeUser)...) - if cfg.Priv { - insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypePriv)...) - if cfg.Exec { - insns = append(insns, insnset.GetInsns(cfg.Mode, ifuzz.TypeExec)...) - } - } - return insns +type ( + Mode int + Type int +) + +type Insn interface { + GetName() string + GetMode() int + GetPseudo() bool + GetPriv() bool + IsCompatible(cfg *Config) bool + Encode(cfg *Config, r *rand.Rand) []byte } -func Generate(cfg *ifuzz.Config, r *rand.Rand) []byte { - var text []byte - for i := 0; i < cfg.Len; i++ { - insn := randInsn(cfg, r) - text = append(text, insn.Encode(cfg, r)...) - } - return text +type InsnSet interface { + GetInsns(mode Mode, typ Type) []Insn + Decode(mode Mode, text []byte) (int, error) + DecodeExt(mode Mode, text []byte) (int, error) // XED, to keep ifuzz_test happy } -func Mutate(cfg *ifuzz.Config, r *rand.Rand, text []byte) []byte { - insns := split(cfg, text) - retry := false - for stop := false; !stop || retry || len(insns) == 0; stop = r.Intn(2) == 0 { - retry = false - switch x := r.Intn(100); { - case x < 10 && len(insns) != 0: - // Delete instruction. - i := r.Intn(len(insns)) - copy(insns[i:], insns[i+1:]) - insns = insns[:len(insns)-1] - case x < 40 && len(insns) != 0: - // Replace instruction with another. - insn := randInsn(cfg, r) - text1 := insn.Encode(cfg, r) - i := r.Intn(len(insns)) - insns[i] = text1 - case x < 70 && len(insns) != 0: - // Mutate instruction. - i := r.Intn(len(insns)) - text1 := insns[i] - for stop := false; !stop || len(text1) == 0; stop = r.Intn(2) == 0 { - switch x := r.Intn(100); { - case x < 5 && len(text1) != 0: - // Delete byte. - pos := r.Intn(len(text1)) - copy(text1[pos:], text1[pos+1:]) - text1 = text1[:len(text1)-1] - case x < 40 && len(text1) != 0: - // Replace a byte. - pos := r.Intn(len(text1)) - text1[pos] = byte(r.Intn(256)) - case x < 70 && len(text1) != 0: - // Flip a bit. - pos := r.Intn(len(text1)) - text1[pos] ^= 1 << byte(r.Intn(8)) - default: - // Insert a byte. - pos := r.Intn(len(text1) + 1) - text1 = append(text1, 0) - copy(text1[pos+1:], text1[pos:]) - text1[pos] = byte(r.Intn(256)) - } - } - insns[i] = text1 - case len(insns) < cfg.Len: - // Insert a new instruction. - insn := randInsn(cfg, r) - text1 := insn.Encode(cfg, r) - i := r.Intn(len(insns) + 1) - insns = append(insns, nil) - copy(insns[i+1:], insns[i:]) - insns[i] = text1 - default: - retry = true - } - } - text = nil - for _, insn := range insns { - text = append(text, insn...) - } - return text +type Config struct { + Arch string + Len int // number of instructions to generate + Mode Mode // one of ModeXXX + Priv bool // generate CPL=0 instructions (x86), HV/!PR mode (PPC) + Exec bool // generate instructions sequences interesting for execution + MemRegions []MemRegion // generated instructions will reference these regions } -func randInsn(cfg *ifuzz.Config, r *rand.Rand) ifuzz.Insn { - insnset := Types[cfg.Arch] - var insns []ifuzz.Insn - if cfg.Priv && cfg.Exec { - insns = insnset.GetInsns(cfg.Mode, r.Intn(3)) - } else if cfg.Priv { - insns = insnset.GetInsns(cfg.Mode, r.Intn(2)) - } else { - insns = insnset.GetInsns(cfg.Mode, ifuzz.TypeUser) - } - return insns[r.Intn(len(insns))] +type MemRegion struct { + Start uint64 + Size uint64 } -func split(cfg *ifuzz.Config, text []byte) [][]byte { - insnset := Types[cfg.Arch] - text = append([]byte{}, text...) - var insns [][]byte - var bad []byte - for len(text) != 0 { - n, err := insnset.Decode(cfg.Mode, text) - if err != nil || n == 0 { - bad = append(bad, text[0]) - text = text[1:] - continue - } - if bad != nil { - insns = append(insns, bad) - bad = nil - } - insns = append(insns, text[:n]) - text = text[n:] +const ( + ModeLong64 Mode = iota + ModeProt32 + ModeProt16 + ModeReal16 + ModeLast +) + +const ( + TypeExec Type = iota + TypePriv + TypeUser + TypeAll + TypeLast +) + +// ModeInsns returns list of all instructions for the given mode. +func ModeInsns(cfg *Config) []Insn { + insnset := Arches[cfg.Arch] + if cfg.Mode < 0 || cfg.Mode >= ModeLast { + panic("bad mode") } - if bad != nil { - insns = append(insns, bad) + insns := insnset.GetInsns(cfg.Mode, TypeUser) + if cfg.Priv { + insns = append(insns, insnset.GetInsns(cfg.Mode, TypePriv)...) + if cfg.Exec { + insns = append(insns, insnset.GetInsns(cfg.Mode, TypeExec)...) + } } return insns } + +var SpecialNumbers = [...]uint64{0, 1 << 15, 1 << 16, 1 << 31, 1 << 32, 1 << 47, 1 << 47, 1 << 63} |
