Skip to content

Commit f62f3c2

Browse files
npigginmpe
authored andcommitted
KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow
The kvmppc_rtas_hcall() sets the host rtas_args.rets pointer based on the rtas_args.nargs that was provided by the guest. That guest nargs value is not range checked, so the guest can cause the host rets pointer to be pointed outside the args array. The individual rtas function handlers check the nargs and nrets values to ensure they are correct, but if they are not, the handlers store a -3 (0xfffffffd) failure indication in rets[0] which corrupts host memory. Fix this by testing up front whether the guest supplied nargs and nret would exceed the array size, and fail the hcall directly without storing a failure indication to rets[0]. Also expand on a comment about why we kill the guest and try not to return errors directly if we have a valid rets[0] pointer. Fixes: 8e591cb ("KVM: PPC: Book3S: Add infrastructure to implement kernel-side RTAS calls") Cc: [email protected] # v3.10+ Reported-by: Alexey Kardashevskiy <[email protected]> Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent bc4188a commit f62f3c2

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

arch/powerpc/kvm/book3s_rtas.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
242242
* value so we can restore it on the way out.
243243
*/
244244
orig_rets = args.rets;
245+
if (be32_to_cpu(args.nargs) >= ARRAY_SIZE(args.args)) {
246+
/*
247+
* Don't overflow our args array: ensure there is room for
248+
* at least rets[0] (even if the call specifies 0 nret).
249+
*
250+
* Each handler must then check for the correct nargs and nret
251+
* values, but they may always return failure in rets[0].
252+
*/
253+
rc = -EINVAL;
254+
goto fail;
255+
}
245256
args.rets = &args.args[be32_to_cpu(args.nargs)];
246257

247258
mutex_lock(&vcpu->kvm->arch.rtas_token_lock);
@@ -269,9 +280,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
269280
fail:
270281
/*
271282
* We only get here if the guest has called RTAS with a bogus
272-
* args pointer. That means we can't get to the args, and so we
273-
* can't fail the RTAS call. So fail right out to userspace,
274-
* which should kill the guest.
283+
* args pointer or nargs/nret values that would overflow the
284+
* array. That means we can't get to the args, and so we can't
285+
* fail the RTAS call. So fail right out to userspace, which
286+
* should kill the guest.
287+
*
288+
* SLOF should actually pass the hcall return value from the
289+
* rtas handler call in r3, so enter_rtas could be modified to
290+
* return a failure indication in r3 and we could return such
291+
* errors to the guest rather than failing to host userspace.
292+
* However old guests that don't test for failure could then
293+
* continue silently after errors, so for now we won't do this.
275294
*/
276295
return rc;
277296
}

0 commit comments

Comments
 (0)