aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ifuzz
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@linux.ibm.com>2021-07-08 19:19:18 +1000
committerDmitry Vyukov <dvyukov@google.com>2021-07-19 11:29:36 +0200
commite6a175800f1d9e20aeb7ed35ea2b3fc627049e8f (patch)
tree2042be55af1e20d45e0be0181d8c50a3bdaa3b0a /pkg/ifuzz
parenta0fbb62d9577118fda219fbd475f5ea3d08ea303 (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.go27
-rw-r--r--pkg/ifuzz/powerpc/pseudo.go32
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))
+}