linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org
Cc: James Morse <james.morse@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Oliver Upton <oliver.upton@linux.dev>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>, Joey Gouly <joey.gouly@arm.com>,
	Mark Brown <broonie@kernel.org>
Subject: [PATCH v4 03/26] KVM: arm64: nv: Add sanitising to VNCR-backed sysregs
Date: Wed, 14 Feb 2024 13:18:04 +0000	[thread overview]
Message-ID: <20240214131827.2856277-4-maz@kernel.org> (raw)
In-Reply-To: <20240214131827.2856277-1-maz@kernel.org>

VNCR-backed "registers" are actually only memory. Which means that
there is zero control over what the guest can write, and that it
is the hypervisor's job to actually sanitise the content of the
backing store. Yeah, this is fun.

In order to preserve some form of sanity, add a repainting mechanism
that makes use of a per-VM set of RES0/RES1 masks, one pair per VNCR
register. These masks get applied on access to the backing store via
__vcpu_sys_reg(), ensuring that the state that is consumed by KVM is
correct.

So far, nothing populates these masks, but stay tuned.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
---
 arch/arm64/include/asm/kvm_host.h | 22 ++++++++++++++++-
 arch/arm64/kvm/arm.c              |  1 +
 arch/arm64/kvm/nested.c           | 41 ++++++++++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 527da3d2cedb..8cda003d6267 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -238,6 +238,8 @@ static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
 	return index;
 }
 
+struct kvm_sysreg_masks;
+
 struct kvm_arch {
 	struct kvm_s2_mmu mmu;
 
@@ -312,6 +314,9 @@ struct kvm_arch {
 #define KVM_ARM_ID_REG_NUM	(IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
 	u64 id_regs[KVM_ARM_ID_REG_NUM];
 
+	/* Masks for VNCR-baked sysregs */
+	struct kvm_sysreg_masks	*sysreg_masks;
+
 	/*
 	 * For an untrusted host VM, 'pkvm.handle' is used to lookup
 	 * the associated pKVM instance in the hypervisor.
@@ -474,6 +479,13 @@ enum vcpu_sysreg {
 	NR_SYS_REGS	/* Nothing after this line! */
 };
 
+struct kvm_sysreg_masks {
+	struct {
+		u64	res0;
+		u64	res1;
+	} mask[NR_SYS_REGS - __VNCR_START__];
+};
+
 struct kvm_cpu_context {
 	struct user_pt_regs regs;	/* sp = sp_el0 */
 
@@ -868,7 +880,15 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
 
 #define ctxt_sys_reg(c,r)	(*__ctxt_sys_reg(c,r))
 
-#define __vcpu_sys_reg(v,r)	(ctxt_sys_reg(&(v)->arch.ctxt, (r)))
+u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
+#define __vcpu_sys_reg(v,r)						\
+	(*({								\
+		const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt;	\
+		u64 *__r = __ctxt_sys_reg(ctxt, (r));			\
+		if (vcpu_has_nv((v)) && (r) >= __VNCR_START__)		\
+			*__r = kvm_vcpu_sanitise_vncr_reg((v), (r));	\
+		__r;							\
+	}))
 
 u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg);
 void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a25265aca432..c063e84fc72c 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -206,6 +206,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 		pkvm_destroy_hyp_vm(kvm);
 
 	kfree(kvm->arch.mpidr_data);
+	kfree(kvm->arch.sysreg_masks);
 	kvm_destroy_vcpus(kvm);
 
 	kvm_unshare_hyp(kvm, kvm + 1);
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index d55e809e26cb..c976cd4b8379 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -163,15 +163,54 @@ static u64 limit_nv_id_reg(u32 id, u64 val)
 
 	return val;
 }
+
+u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysreg sr)
+{
+	u64 v = ctxt_sys_reg(&vcpu->arch.ctxt, sr);
+	struct kvm_sysreg_masks *masks;
+
+	masks = vcpu->kvm->arch.sysreg_masks;
+
+	if (masks) {
+		sr -= __VNCR_START__;
+
+		v &= ~masks->mask[sr].res0;
+		v |= masks->mask[sr].res1;
+	}
+
+	return v;
+}
+
+static void __maybe_unused set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
+{
+	int i = sr - __VNCR_START__;
+
+	kvm->arch.sysreg_masks->mask[i].res0 = res0;
+	kvm->arch.sysreg_masks->mask[i].res1 = res1;
+}
+
 int kvm_init_nv_sysregs(struct kvm *kvm)
 {
+	int ret = 0;
+
 	mutex_lock(&kvm->arch.config_lock);
 
+	if (kvm->arch.sysreg_masks)
+		goto out;
+
+	kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
+					 GFP_KERNEL);
+	if (!kvm->arch.sysreg_masks) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
 	for (int i = 0; i < KVM_ARM_ID_REG_NUM; i++)
 		kvm->arch.id_regs[i] = limit_nv_id_reg(IDX_IDREG(i),
 						       kvm->arch.id_regs[i]);
 
+out:
 	mutex_unlock(&kvm->arch.config_lock);
 
-	return 0;
+	return ret;
 }
-- 
2.39.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2024-02-14 13:19 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-14 13:18 [PATCH v4 00/26] KVM/arm64: VM configuration enforcement Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 01/26] arm64: sysreg: Add missing ID_AA64ISAR[13]_EL1 fields and variants Marc Zyngier
2024-02-15 18:06   ` Catalin Marinas
2024-02-14 13:18 ` [PATCH v4 02/26] KVM: arm64: Add feature checking helpers Marc Zyngier
2024-02-14 13:18 ` Marc Zyngier [this message]
2024-02-14 13:18 ` [PATCH v4 04/26] KVM: arm64: nv: Add sanitising to EL2 configuration registers Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 05/26] KVM: arm64: nv: Add sanitising to VNCR-backed FGT sysregs Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 06/26] KVM: arm64: nv: Add sanitising to VNCR-backed HCRX_EL2 Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 07/26] KVM: arm64: nv: Drop sanitised_sys_reg() helper Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 08/26] KVM: arm64: Unify HDFG[WR]TR_GROUP FGT identifiers Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 09/26] KVM: arm64: nv: Correctly handle negative polarity FGTs Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 10/26] KVM: arm64: nv: Turn encoding ranges into discrete XArray stores Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 11/26] KVM: arm64: Drop the requirement for XARRAY_MULTI Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 12/26] KVM: arm64: nv: Move system instructions to their own sys_reg_desc array Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 13/26] KVM: arm64: Always populate the trap configuration xarray Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 14/26] KVM: arm64: Register AArch64 system register entries with the sysreg xarray Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 15/26] KVM: arm64: Use the xarray as the primary sysreg/sysinsn walker Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 16/26] KVM: arm64: Rename __check_nv_sr_forward() to triage_sysreg_trap() Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 17/26] KVM: arm64: Add Fine-Grained UNDEF tracking information Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 18/26] KVM: arm64: Propagate and handle Fine-Grained UNDEF bits Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 19/26] KVM: arm64: Move existing feature disabling over to FGU infrastructure Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 20/26] KVM: arm64: Streamline save/restore of HFG[RW]TR_EL2 Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 21/26] KVM: arm64: Make TLBI OS/Range UNDEF if not advertised to the guest Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 22/26] KVM: arm64: Make PIR{,E0}_EL1 UNDEF if S1PIE is " Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 23/26] KVM: arm64: Make AMU sysreg UNDEF if FEAT_AMU " Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 24/26] KVM: arm64: Make FEAT_MOPS UNDEF if " Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 25/26] KVM: arm64: Snapshot all non-zero RES0/RES1 sysreg fields for later checking Marc Zyngier
2024-02-14 13:18 ` [PATCH v4 26/26] KVM: arm64: Add debugfs file for guest's ID registers Marc Zyngier
2024-02-15 21:03 ` [PATCH v4 00/26] KVM/arm64: VM configuration enforcement Oliver Upton
2024-02-19 17:34 ` Oliver Upton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240214131827.2856277-4-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=james.morse@arm.com \
    --cc=joey.gouly@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=oliver.upton@linux.dev \
    --cc=suzuki.poulose@arm.com \
    --cc=will@kernel.org \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).