aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2014-03-03 16:59:03 +1100
committerEli Qiao <taget@linux.vnet.ibm.com>2014-03-04 12:14:03 +0800
commit45279f154bcba5ce981566d98e28f672669cab84 (patch)
treec42abd5bd049cc0d82bb92b8977a03c39a0c9823
parentc347c8383650ff57011c0754538ec2e8011dcf7d (diff)
downloadpowerkvm-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.c12
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;