ANDROID: KVM: arm64: iommu: Add owner to domains

Add an owner to each domain either host or a VM which is set at alloc
time, and all other IOMMU operations would be allowed only from the
domain owner.
The new vm member is protected by kvm_iommu_domain_lock while
set/cleared in alloc/free, and the check is done only after the domain
refcount is elevated to avoid racing with alloc.

Bug: 357781595
Bug: 348382247
Bug: 236685427
Change-Id: Ie23379d958922368ec3be2127ba90393709a77bb
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2024-07-02 13:30:35 +00:00
committed by Carlos Llamas
parent 8a9430e18b
commit 540b4b9ce3
2 changed files with 29 additions and 2 deletions
+28 -2
View File
@@ -219,14 +219,29 @@ handle_to_domain(pkvm_handle_t domain_id)
static int domain_get(struct kvm_hyp_iommu_domain *domain)
{
int old = atomic_fetch_inc_acquire(&domain->refs);
struct pkvm_hyp_vcpu *hyp_vcpu = __get_vcpu();
int ret = 0;
BUG_ON(!old || (old + 1 < 0));
return 0;
/* check done after refcount is elevated to avoid race with alloc_domain */
if (!hyp_vcpu && domain->vm)
ret = -EPERM;
if (hyp_vcpu && (domain->vm != pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu)))
ret = -EPERM;
if (ret)
atomic_dec_return_release(&domain->refs);
return ret;
}
static void domain_put(struct kvm_hyp_iommu_domain *domain)
{
struct pkvm_hyp_vcpu *hyp_vcpu = __get_vcpu();
BUG_ON(!atomic_dec_return_release(&domain->refs));
WARN_ON(!hyp_vcpu && domain->vm);
WARN_ON(hyp_vcpu && (domain->vm != pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu)));
}
static int kvm_iommu_init_atomic_pool(struct kvm_hyp_memcache *atomic_mc)
@@ -285,6 +300,8 @@ int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type)
{
int ret = -EINVAL;
struct kvm_hyp_iommu_domain *domain;
struct pkvm_hyp_vcpu *hyp_vcpu = __get_vcpu();
struct pkvm_hyp_vm *vm;
domain = handle_to_domain(domain_id);
if (!domain)
@@ -299,6 +316,10 @@ int kvm_iommu_alloc_domain(pkvm_handle_t domain_id, int type)
if (ret)
goto out_unlock;
if (hyp_vcpu) {
vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
domain->vm = vm;
}
atomic_set_release(&domain->refs, 1);
out_unlock:
hyp_spin_unlock(&kvm_iommu_domain_lock);
@@ -309,13 +330,18 @@ int kvm_iommu_free_domain(pkvm_handle_t domain_id)
{
int ret = 0;
struct kvm_hyp_iommu_domain *domain;
struct pkvm_hyp_vcpu *hyp_vcpu = __get_vcpu();
struct pkvm_hyp_vm *vm = NULL;
domain = handle_to_domain(domain_id);
if (!domain)
return -EINVAL;
hyp_spin_lock(&kvm_iommu_domain_lock);
if (WARN_ON(atomic_cmpxchg_acquire(&domain->refs, 1, 0) != 1)) {
if (hyp_vcpu)
vm = pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu);
if (WARN_ON(atomic_cmpxchg_acquire(&domain->refs, 1, 0) != 1) || domain->vm != vm) {
ret = -EINVAL;
goto out_unlock;
}
+1
View File
@@ -21,6 +21,7 @@ struct kvm_hyp_iommu_domain {
atomic_t refs;
pkvm_handle_t domain_id;
void *priv;
void *vm;
ANDROID_KABI_RESERVE(1);
ANDROID_KABI_RESERVE(2);
};