diff options
Diffstat (limited to 'pkg/ifuzz/ifuzzimpl/ifuzzimpl.go')
| -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} |
