aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2017-10-26 11:23:06 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2017-10-28 22:25:06 -0400
commitc2385eaa6c5a87cdc4e04ed589ae103ca3297c84 (patch)
tree712404cee49dc091b21b2923b531697197a940c8
parentc9b51bb60d944067f36f67750e19c18c3cc2697c (diff)
KVM: arm/arm64: vgic-its: Check GITS_BASER Valid bit before saving tables
At the moment we don't properly check the GITS_BASER<n>.Valid bit before saving the collection and device tables. On vgic_its_save_collection_table() we use the GITS_BASER gpa field whereas the Valid bit should be used. On vgic_its_save_device_tables() there is no check. This can cause various bugs, among which a subsequent fault when accessing the table in guest memory. Let's systematically check the Valid bit before doing anything. We also uniformize the code between save and restore. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Andre Przywara <andre.przywara@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index e69ef7d27fde..547f12dc4d54 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -2067,11 +2067,12 @@ static int vgic_its_device_cmp(void *priv, struct list_head *a,
2067static int vgic_its_save_device_tables(struct vgic_its *its) 2067static int vgic_its_save_device_tables(struct vgic_its *its)
2068{ 2068{
2069 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2069 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2070 u64 baser = its->baser_device_table;
2070 struct its_device *dev; 2071 struct its_device *dev;
2071 int dte_esz = abi->dte_esz; 2072 int dte_esz = abi->dte_esz;
2072 u64 baser;
2073 2073
2074 baser = its->baser_device_table; 2074 if (!(baser & GITS_BASER_VALID))
2075 return 0;
2075 2076
2076 list_sort(NULL, &its->device_list, vgic_its_device_cmp); 2077 list_sort(NULL, &its->device_list, vgic_its_device_cmp);
2077 2078
@@ -2215,17 +2216,17 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
2215static int vgic_its_save_collection_table(struct vgic_its *its) 2216static int vgic_its_save_collection_table(struct vgic_its *its)
2216{ 2217{
2217 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2218 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2219 u64 baser = its->baser_coll_table;
2220 gpa_t gpa = BASER_ADDRESS(baser);
2218 struct its_collection *collection; 2221 struct its_collection *collection;
2219 u64 val; 2222 u64 val;
2220 gpa_t gpa;
2221 size_t max_size, filled = 0; 2223 size_t max_size, filled = 0;
2222 int ret, cte_esz = abi->cte_esz; 2224 int ret, cte_esz = abi->cte_esz;
2223 2225
2224 gpa = BASER_ADDRESS(its->baser_coll_table); 2226 if (!(baser & GITS_BASER_VALID))
2225 if (!gpa)
2226 return 0; 2227 return 0;
2227 2228
2228 max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; 2229 max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
2229 2230
2230 list_for_each_entry(collection, &its->collection_list, coll_list) { 2231 list_for_each_entry(collection, &its->collection_list, coll_list) {
2231 ret = vgic_its_save_cte(its, collection, gpa, cte_esz); 2232 ret = vgic_its_save_cte(its, collection, gpa, cte_esz);
@@ -2256,17 +2257,18 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
2256static int vgic_its_restore_collection_table(struct vgic_its *its) 2257static int vgic_its_restore_collection_table(struct vgic_its *its)
2257{ 2258{
2258 const struct vgic_its_abi *abi = vgic_its_get_abi(its); 2259 const struct vgic_its_abi *abi = vgic_its_get_abi(its);
2260 u64 baser = its->baser_coll_table;
2259 int cte_esz = abi->cte_esz; 2261 int cte_esz = abi->cte_esz;
2260 size_t max_size, read = 0; 2262 size_t max_size, read = 0;
2261 gpa_t gpa; 2263 gpa_t gpa;
2262 int ret; 2264 int ret;
2263 2265
2264 if (!(its->baser_coll_table & GITS_BASER_VALID)) 2266 if (!(baser & GITS_BASER_VALID))
2265 return 0; 2267 return 0;
2266 2268
2267 gpa = BASER_ADDRESS(its->baser_coll_table); 2269 gpa = BASER_ADDRESS(baser);
2268 2270
2269 max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; 2271 max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
2270 2272
2271 while (read < max_size) { 2273 while (read < max_size) {
2272 ret = vgic_its_restore_cte(its, gpa, cte_esz); 2274 ret = vgic_its_restore_cte(its, gpa, cte_esz);