Skip to content

Commit

Permalink
KVM: arm64: Reject shared table walks in the hyp code
Browse files Browse the repository at this point in the history
Exclusive table walks are the only supported table walk in the hyp, as
there is no construct like RCU available in the hypervisor code. Reject
any attempt to do a shared table walk by returning an error and allowing
the caller to clean up the mess.

Suggested-by: Will Deacon <will@kernel.org>
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20221118182222.3932898-4-oliver.upton@linux.dev
  • Loading branch information
Oliver Upton authored and Marc Zyngier committed Nov 22, 2022
1 parent b7833bf commit 5e806c5
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
17 changes: 15 additions & 2 deletions arch/arm64/include/asm/kvm_pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,18 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke
return pteref;
}

static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) {}
static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker)
{
/*
* Due to the lack of RCU (or a similar protection scheme), only
* non-shared table walkers are allowed in the hypervisor.
*/
if (walker->flags & KVM_PGTABLE_WALK_SHARED)
return -EPERM;

return 0;
}

static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker) {}

static inline bool kvm_pgtable_walk_lock_held(void)
Expand All @@ -247,10 +258,12 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke
return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED));
}

static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker)
static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker)
{
if (walker->flags & KVM_PGTABLE_WALK_SHARED)
rcu_read_lock();

return 0;
}

static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker)
Expand Down
5 changes: 4 additions & 1 deletion arch/arm64/kvm/hyp/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,10 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size,
};
int r;

kvm_pgtable_walk_begin(walker);
r = kvm_pgtable_walk_begin(walker);
if (r)
return r;

r = _kvm_pgtable_walk(pgt, &walk_data);
kvm_pgtable_walk_end(walker);

Expand Down

0 comments on commit 5e806c5

Please sign in to comment.