[PATCH v2 11/13] KVM: arm64: Prevent the host from specifying a different command queue
Sebastian Ene <[email protected]> Fri, 7 Aug 2026 16:43:21 +0000
| Newsgroups | dev.linux.lists.kvmarm,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-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