diff options
| author | Alexey Kardashevskiy <aik@linux.ibm.com> | 2021-07-08 19:19:18 +1000 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2021-07-19 11:29:36 +0200 |
| commit | e6a175800f1d9e20aeb7ed35ea2b3fc627049e8f (patch) | |
| tree | 2042be55af1e20d45e0be0181d8c50a3bdaa3b0a /pkg/ifuzz | |
| parent | a0fbb62d9577118fda219fbd475f5ea3d08ea303 (diff) | |
pkg/ifuzz/powerpc: add some RTAS fuzzing
RunTime Abstraction Services (RTAS) is an API used by the Linux
powerpc/pseries platform to talk to the hypervisor. Under KVM, this
is implemented as a custom hypercall (which we have support for) and
an in memory array of parameters. The hypercall is H_RTAS and its only
parameter is a pointer to the mentioned array. The vast majority of
RTAS calls are handled normally by QEMU and only a handful by KVM.
This adds fuzzing of 4 RTAS calls. This uses a chunk from main 256MB RAM
for parameters. The parameters are big endian hence "<<24" for the token.
To allow more targeted fuzzing, use iset.GenerateInt().
Signed-off-by: Alexey Kardashevskiy <aik@linux.ibm.com>
Diffstat (limited to 'pkg/ifuzz')
| -rw-r--r-- | pkg/ifuzz/powerpc/powerpc.go | 27 | ||||
| -rw-r--r-- | pkg/ifuzz/powerpc/pseudo.go | 32 |
2 files changed, 57 insertions, 2 deletions
diff --git a/pkg/ifuzz/powerpc/powerpc.go b/pkg/ifuzz/powerpc/powerpc.go index 2704ae33b..48c39d4a1 100644 --- a/pkg/ifuzz/powerpc/powerpc.go +++ b/pkg/ifuzz/powerpc/powerpc.go @@ -174,6 +174,33 @@ func (imap insnSetMap) ld64(reg uint, v uint64) []byte { return ret } +func (imap insnSetMap) ld32(reg uint, v uint32) []byte { + ret := make([]byte, 0) + + ret = append(ret, imap["addis"].enc(map[string]uint{ + "RT": reg, + "RA": 0, // In "addis", '0' means 0, not GPR0 + "SI": uint((v >> 16) & 0xffff)})...) + ret = append(ret, imap["ori"].enc(map[string]uint{ + "RA": reg, + "RS": reg, + "UI": uint(v & 0xffff)})...) + + return ret +} + +func (imap insnSetMap) ldgpr32(regaddr, regval uint, addr uint64, v uint32) []byte { + ret := make([]byte, 0) + + ret = append(ret, imap.ld64(regaddr, addr)...) + ret = append(ret, imap.ld32(regval, v)...) + ret = append(ret, imap["stw"].enc(map[string]uint{ + "RA": regaddr, + "RS": regval})...) + + return ret +} + func (imap insnSetMap) sc(lev uint) []byte { return imap["sc"].enc(map[string]uint{"LEV": lev}) } diff --git a/pkg/ifuzz/powerpc/pseudo.go b/pkg/ifuzz/powerpc/pseudo.go index 91b705b02..c2a1b568f 100644 --- a/pkg/ifuzz/powerpc/pseudo.go +++ b/pkg/ifuzz/powerpc/pseudo.go @@ -46,11 +46,21 @@ func (insnset *InsnSet) initPseudo() { return gen.text }, }) + insnset.Insns = append(insnset.Insns, &Insn{ + Name: "PSEUDO_rtas", + Priv: true, + Pseudo: true, + generator: func(cfg *iset.Config, r *rand.Rand) []byte { + gen := makeGen(insnset, cfg, r) + gen.rtas() + return gen.text + }, + }) } type generator struct { imap insnSetMap - mode iset.Mode + cfg *iset.Config r *rand.Rand text []byte } @@ -58,7 +68,7 @@ type generator struct { func makeGen(insnset *InsnSet, cfg *iset.Config, r *rand.Rand) *generator { return &generator{ imap: insnset.insnMap, - mode: cfg.Mode, + cfg: cfg, r: r, } } @@ -77,3 +87,21 @@ func (gen *generator) sc(lev uint) { } gen.byte(imap.sc(lev)) } + +func (gen *generator) rtas() { + imap := gen.imap + + addr := iset.GenerateInt(gen.cfg, gen.r, 8) + token := uint32(gen.r.Intn(8) << 24) // There are only 4 tokens handled by KVM and it is BigEndian. + reg := uint(iset.GenerateInt(gen.cfg, gen.r, 4)) + + gen.byte(imap.ldgpr32(reg, reg+uint(1), addr, token)) + for i := 0; i < gen.r.Intn(4)+1; i++ { + gen.byte(imap.ldgpr32(reg, reg+uint(1), addr+uint64(i*4), + uint32(iset.GenerateInt(gen.cfg, gen.r, 4)))) + } + gen.byte(imap.ld64(3, 0xF000)) // 0xF000 is a custom H_RTAS hypercall + gen.byte(imap.ld64(4, addr)) + + gen.byte(imap.sc(1)) +} |
