summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorQuentin Perret <qperret@google.com>2024-11-28 16:44:06 +0100
committerOliver Upton <oliver.upton@linux.dev>2024-12-18 22:21:37 +0100
commit985bb51f17abbe83c697a5ac0aa40fad5f4e00f4 (patch)
tree0abd719d2c272f49cedf07edbbf564cc3761707a /arch
parentKVM: arm64: Fix set_id_regs selftest for ASIDBITS becoming unwritable (diff)
downloadlinux-985bb51f17abbe83c697a5ac0aa40fad5f4e00f4.tar.xz
linux-985bb51f17abbe83c697a5ac0aa40fad5f4e00f4.zip
KVM: arm64: Always check the state from hyp_ack_unshare()
There are multiple pKVM memory transitions where the state of a page is not cross-checked from the completer's PoV for performance reasons. For example, if a page is PKVM_PAGE_OWNED from the initiator's PoV, we should be guaranteed by construction that it is PKVM_NOPAGE for everybody else, hence allowing us to save a page-table lookup. When it was introduced, hyp_ack_unshare() followed that logic and bailed out without checking the PKVM_PAGE_SHARED_BORROWED state in the hypervisor's stage-1. This was correct as we could safely assume that all host-initiated shares were directed at the hypervisor at the time. But with the introduction of other types of shares (e.g. for FF-A or non-protected guests), it is now very much required to cross check this state to prevent the host from running __pkvm_host_unshare_hyp() on a page shared with TZ or a non-protected guest. Thankfully, if an attacker were to try this, the hyp_unmap() call from hyp_complete_unshare() would fail, hence causing to WARN() from __do_unshare() with the host lock held, which is fatal. But this is fragile at best, and can hardly be considered a security measure. Let's just do the right thing and always check the state from hyp_ack_unshare(). Signed-off-by: Quentin Perret <qperret@google.com> Acked-by: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20241128154406.602875-1-qperret@google.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/kvm/hyp/nvhe/mem_protect.c3
1 files changed, 0 insertions, 3 deletions
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index caba3e4bd09e..e75374d682f4 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -783,9 +783,6 @@ static int hyp_ack_unshare(u64 addr, const struct pkvm_mem_transition *tx)
if (tx->initiator.id == PKVM_ID_HOST && hyp_page_count((void *)addr))
return -EBUSY;
- if (__hyp_ack_skip_pgtable_check(tx))
- return 0;
-
return __hyp_check_page_state_range(addr, size,
PKVM_PAGE_SHARED_BORROWED);
}