diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2014-03-03 16:59:03 +1100 |
---|---|---|
committer | Eli Qiao <taget@linux.vnet.ibm.com> | 2014-03-04 12:14:03 +0800 |
commit | 45279f154bcba5ce981566d98e28f672669cab84 (patch) | |
tree | c42abd5bd049cc0d82bb92b8977a03c39a0c9823 | |
parent | c347c8383650ff57011c0754538ec2e8011dcf7d (diff) | |
download | powerkvm-45279f154bcba5ce981566d98e28f672669cab84.tar.gz |
powerpc: fix realmode-failure flag reset
A malicious guest can register an IOMMU in KVM while a TCE request is
being passed from the real to virtual mode. If vcpu->arch.tce_rm_fail
was previously used and not cleared because of missing LIOBN entry in KVM,
this may cause unwanted put_page() in the virtual mode handler.
This moves @tce_rm_fail earlier to avoid using the incorrect tce_rm_fail
flag value.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
-rw-r--r-- | arch/powerpc/kvm/book3s_64_vio_hv.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index dd41fcdb7bfe15..58f666dfda876e 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c @@ -358,6 +358,9 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, struct kvmppc_spapr_tce_table *tt; struct iommu_group *grp = NULL; + vcpu->arch.tce_rm_fail = TCERM_NONE; + vcpu->arch.tce_tmp_num = 0; + tt = kvmppc_find_tce_table(vcpu->kvm, liobn); if (!tt) { grp = find_group_by_liobn_rm(vcpu->kvm, liobn); @@ -365,9 +368,6 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, return H_TOO_HARD; } - vcpu->arch.tce_rm_fail = TCERM_NONE; - vcpu->arch.tce_tmp_num = 0; - if (grp) return kvmppc_rm_h_put_tce_iommu(vcpu, grp, liobn, ioba, tce); @@ -392,6 +392,9 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, struct page *pg = NULL; struct iommu_group *grp = NULL; + vcpu->arch.tce_rm_fail = TCERM_NONE; + vcpu->arch.tce_tmp_num = 0; + tt = kvmppc_find_tce_table(vcpu->kvm, liobn); if (!tt) { grp = find_group_by_liobn_rm(vcpu->kvm, liobn); @@ -412,9 +415,6 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, if (tt && ((ioba + (npages << IOMMU_PAGE_SHIFT)) > tt->window_size)) return H_PARAMETER; - vcpu->arch.tce_rm_fail = TCERM_NONE; - vcpu->arch.tce_tmp_num = 0; - tces = kvmppc_rm_gpa_to_hpa_and_get(vcpu, tce_list, &pg); if (tces == ERROR_ADDR) { vcpu->arch.tce_rm_fail = pg ? TCERM_GETLISTPAGE : TCERM_NONE; |