[PATCH v2 11/13] KVM: arm64: Prevent the host from specifying a different command queue

Sebastian Ene <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.ports.arm.kernel
Message-ID <[email protected]>
Don't let a malicious host re-program the command queue register with a
different address and size to bypass the commands sanitization.
Prevent unpredictable hardware behavior and restrict updates to the
GITS_CBASER while the ITS is enabled or not in a quiescent state.

Signed-off-by: Sebastian Ene <[email protected]>
---
 arch/arm64/kvm/hyp/nvhe/its_emulate.c | 32 +++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/kvm/hyp/nvhe/its_emulate.c b/arch/arm64/kvm/hyp/nvhe/its_emulate.c
index b9b71aa18d48..97cfa31d90d1 100644
--- a/arch/arm64/kvm/hyp/nvhe/its_emulate.c
+++ b/arch/arm64/kvm/hyp/nvhe/its_emulate.c
@@ -429,9 +429,41 @@ static void ctlr_write(struct pkvm_protected_reg *region, u64 offset, u64 value)
 	writel_relaxed(value, its->base + GITS_CTLR);
 }
 
+static void cbaser_write(struct pkvm_protected_reg *region, u64 offset, u64 value)
+{
+	struct its_priv_state *its = region->priv;
+	int num_pages;
+	u64 ctlr;
+
+	ctlr = readl_relaxed(its->base + GITS_CTLR);
+	if ((ctlr & GITS_CTLR_ENABLE) || !(ctlr & GITS_CTLR_QUIESCENT))
+		return;
+
+	num_pages = its->host_state->cmdq_len / SZ_4K;
+
+	/* Don't let the host program a different command queue */
+	value &= ~(GENMASK(7, 0) | GENMASK_ULL(51, 12));
+	value |= (num_pages - 1) & GENMASK(7, 0);
+	value |= __hyp_pa(its->cmd_original) & GENMASK_ULL(51, 12);
+	its->needs_flush = (value & GITS_CBASER_SHAREABILITY_MASK) != GITS_CBASER_InnerShareable;
+
+	writeq_relaxed(value, its->base + GITS_CBASER);
+
+	/* Restart the CMDQ to read from 0 */
+	its->cmd_offset = 0;
+	writeq_relaxed(0, its->base + GITS_CWRITER);
+}
+
+static void cbaser_read(struct pkvm_protected_reg *region, u64 offset, u64 *read)
+{
+	struct its_priv_state *its = region->priv;
+	*read = readq_relaxed(its->base + GITS_CBASER);
+}
+
 static struct its_handler its_handlers[] = {
 	ITS_HANDLER(GITS_CWRITER, sizeof(u64), cwriter_write, cwriter_read),
 	ITS_HANDLER(GITS_CTLR, sizeof(u32), ctlr_write, ctlr_read),
+	ITS_HANDLER(GITS_CBASER, sizeof(u64), cbaser_write, cbaser_read),
 	{},
 };
 
-- 
2.55.0.654.g21b8a5bc05-goog
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.