From 5405d2e2ed019de7452677eacfc7de9562a8ea12 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 20 Nov 2020 17:30:23 +0100 Subject: 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. --- pkg/ifuzz/ifuzzimpl/ifuzzimpl.go | 180 +++++++++++++-------------------------- 1 file changed, 59 insertions(+), 121 deletions(-) (limited to 'pkg/ifuzz/ifuzzimpl/ifuzzimpl.go') 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} -- cgit mrf-deployment