Skip to content

Commit 3f83150

Browse files
farosasmpe
authored andcommitted
KVM: PPC: mmio: Reject instructions that access more than mmio.data size
The MMIO interface between the kernel and userspace uses a structure that supports a maximum of 8-bytes of data. Instructions that access more than that need to be emulated in parts. We currently don't have generic support for splitting the emulation in parts and each set of instructions needs to be explicitly included. There's already an error message being printed when a load or store exceeds the mmio.data buffer but we don't fail the emulation until later at kvmppc_complete_mmio_load and even then we allow userspace to make a partial copy of the data, which ends up overwriting some fields of the mmio structure. This patch makes the emulation fail earlier at kvmppc_handle_load|store, which will send a Program interrupt to the guest. This is better than allowing the guest to proceed with partial data. Note that this was caught in a somewhat artificial scenario using quadword instructions (lq/stq), there's no account of an actual guest in the wild running instructions that are not properly emulated. (While here, remove the "bad MMIO" messages. The caller already has an error message.) Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220125215655.1026224-4-farosas@linux.ibm.com
1 parent b99234b commit 3f83150

1 file changed

Lines changed: 5 additions & 11 deletions

File tree

arch/powerpc/kvm/powerpc.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,10 +1114,8 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu)
11141114
struct kvm_run *run = vcpu->run;
11151115
u64 gpr;
11161116

1117-
if (run->mmio.len > sizeof(gpr)) {
1118-
printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
1117+
if (run->mmio.len > sizeof(gpr))
11191118
return;
1120-
}
11211119

11221120
if (!vcpu->arch.mmio_host_swabbed) {
11231121
switch (run->mmio.len) {
@@ -1236,10 +1234,8 @@ static int __kvmppc_handle_load(struct kvm_vcpu *vcpu,
12361234
host_swabbed = !is_default_endian;
12371235
}
12381236

1239-
if (bytes > sizeof(run->mmio.data)) {
1240-
printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
1241-
run->mmio.len);
1242-
}
1237+
if (bytes > sizeof(run->mmio.data))
1238+
return EMULATE_FAIL;
12431239

12441240
run->mmio.phys_addr = vcpu->arch.paddr_accessed;
12451241
run->mmio.len = bytes;
@@ -1325,10 +1321,8 @@ int kvmppc_handle_store(struct kvm_vcpu *vcpu,
13251321
host_swabbed = !is_default_endian;
13261322
}
13271323

1328-
if (bytes > sizeof(run->mmio.data)) {
1329-
printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
1330-
run->mmio.len);
1331-
}
1324+
if (bytes > sizeof(run->mmio.data))
1325+
return EMULATE_FAIL;
13321326

13331327
run->mmio.phys_addr = vcpu->arch.paddr_accessed;
13341328
run->mmio.len = bytes;

0 commit comments

Comments
 (0)