Blob Blame History Raw
From 9ab861c9a630d07a8ac0240f81dd0067b6c57963 Mon Sep 17 00:00:00 2001
From: Joel Savitz <jsavitz@redhat.com>
Date: Mon, 20 Sep 2021 13:49:09 -0400
Subject: [KPATCH CVE-2021-37576] KVM: PPC: kpatch fixes for CVE-2021-37576

Kernels:
3.10.0-1160.el7
3.10.0-1160.2.1.el7
3.10.0-1160.2.2.el7
3.10.0-1160.6.1.el7
3.10.0-1160.11.1.el7
3.10.0-1160.15.2.el7
3.10.0-1160.21.1.el7
3.10.0-1160.24.1.el7
3.10.0-1160.25.1.el7
3.10.0-1160.31.1.el7
3.10.0-1160.36.2.el7
3.10.0-1160.41.1.el7
3.10.0-1160.42.2.el7

Changes since last build:
arches: ppc64le
book3s_rtas.o: changed function: kvmppc_rtas_hcall
---------------------------

Kernels:
3.10.0-1160.2.1.el7
3.10.0-1160.2.2.el7
3.10.0-1160.6.1.el7
3.10.0-1160.11.1.el7
3.10.0-1160.15.2.el7
3.10.0-1160.21.1.el7
3.10.0-1160.24.1.el7
3.10.0-1160.25.1.el7
3.10.0-1160.31.1.el7
3.10.0-1160.36.2.el7
3.10.0-1160.41.1.el7
3.10.0-1160.42.2.el7

Modifications: None
Kpatch-MR: https://gitlab.com/kpatch-dev/rhel-7/-/merge_requests/8
Approved-by: Artem Savkov (@artem.savkov)
Approved-by: Joe Lawrence (@joe.lawrence)
Approved-by: Yannick Cote (@ycote1)

Z-MR: https://gitlab.com/redhat/rhel/src/kernel/rhel-7/-/merge_requests/274

No reproducer available, tested via manual install and:
KT0 test PASS (ppc64le only): https://beaker.engineering.redhat.com/jobs/5809981

for scratch build: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=39840849

commit e1b729d6d332cc22fe641edc723324222096bf29
Author: Jon Maloy <jmaloy@redhat.com>
Date:   Thu Aug 12 19:22:51 2021 -0400

    KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow

    Bugzilla: https://bugzilla.redhat.com/1988218
    Upstream Status: Merged
    Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=39246436
    CVE: CVE-2021-37576

    commit f62f3c20647ebd5fb6ecb8f0b477b9281c44c10a
    Author: Nicholas Piggin <npiggin@gmail.com>
    Date:   Tue Jul 20 20:43:09 2021 +1000

        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: 8e591cb72047 ("KVM: PPC: Book3S: Add infrastructure to implement kernel-side RTAS calls")
        Cc: stable@vger.kernel.org # v3.10+
        Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
        Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
        Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

    Signed-off-by: Jon Maloy <jmaloy@redhat.com>

Signed-off-by: Joel Savitz <jsavitz@redhat.com>
---
 arch/powerpc/kvm/book3s_rtas.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_rtas.c b/arch/powerpc/kvm/book3s_rtas.c
index ef27fbd5d9c5..d896c6854abc 100644
--- a/arch/powerpc/kvm/book3s_rtas.c
+++ b/arch/powerpc/kvm/book3s_rtas.c
@@ -230,6 +230,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
 	 * value so we can restore it on the way out.
 	 */
 	orig_rets = args.rets;
+	if (be32_to_cpu(args.nargs) >= ARRAY_SIZE(args.args)) {
+		/*
+		 * Don't overflow our args array: ensure there is room for
+		 * at least rets[0] (even if the call specifies 0 nret).
+		 *
+		 * Each handler must then check for the correct nargs and nret
+		 * values, but they may always return failure in rets[0].
+		 */
+		rc = -EINVAL;
+		goto fail;
+	}
 	args.rets = &args.args[be32_to_cpu(args.nargs)];
 
 	mutex_lock(&vcpu->kvm->lock);
@@ -257,9 +268,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
 fail:
 	/*
 	 * We only get here if the guest has called RTAS with a bogus
-	 * args pointer. That means we can't get to the args, and so we
-	 * can't fail the RTAS call. So fail right out to userspace,
-	 * which should kill the guest.
+	 * args pointer or nargs/nret values that would overflow the
+	 * array. That means we can't get to the args, and so we can't
+	 * fail the RTAS call. So fail right out to userspace, which
+	 * should kill the guest.
+	 *
+	 * SLOF should actually pass the hcall return value from the
+	 * rtas handler call in r3, so enter_rtas could be modified to
+	 * return a failure indication in r3 and we could return such
+	 * errors to the guest rather than failing to host userspace.
+	 * However old guests that don't test for failure could then
+	 * continue silently after errors, so for now we won't do this.
 	 */
 	return rc;
 }
-- 
2.26.3