From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753257AbdI0N3N (ORCPT ); Wed, 27 Sep 2017 09:29:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:35970 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753226AbdI0N3M (ORCPT ); Wed, 27 Sep 2017 09:29:12 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C02C97E456 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, marc.zyngier@arm.com, cdall@linaro.org, peter.maydell@linaro.org, andre.przywara@arm.com, wanghaibin.wang@huawei.com Cc: wu.wubin@huawei.com Subject: [PATCH v2 04/10] KVM: arm/arm64: vgic-its: Check GITS_BASER Valid bit before saving tables Date: Wed, 27 Sep 2017 15:28:34 +0200 Message-Id: <1506518920-18571-5-git-send-email-eric.auger@redhat.com> In-Reply-To: <1506518920-18571-1-git-send-email-eric.auger@redhat.com> References: <1506518920-18571-1-git-send-email-eric.auger@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 27 Sep 2017 13:29:11 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org At the moment we don't properly check the GITS_BASER.Valid bit before saving the collection and device tables. On Collection table save() we use the gpa field whereas the Valid bit should be used. On device table save() 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 unifomize the code between save and restore. Signed-off-by: Eric Auger --- virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index c1f7972..60ecf91 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, static int vgic_its_save_device_tables(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_device_table; struct its_device *dev; int dte_esz = abi->dte_esz; - u64 baser; - baser = its->baser_device_table; + if (!(baser & GITS_BASER_VALID)) + return 0; list_sort(NULL, &its->device_list, vgic_its_device_cmp); @@ -2217,17 +2218,17 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz) static int vgic_its_save_collection_table(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_coll_table; + gpa_t gpa = BASER_ADDRESS(baser); struct its_collection *collection; u64 val; - gpa_t gpa; size_t max_size, filled = 0; int ret, cte_esz = abi->cte_esz; - gpa = BASER_ADDRESS(its->baser_coll_table); - if (!gpa) + if (!(baser & GITS_BASER_VALID)) return 0; - max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; + max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; list_for_each_entry(collection, &its->collection_list, coll_list) { ret = vgic_its_save_cte(its, collection, gpa, cte_esz); @@ -2258,17 +2259,18 @@ static int vgic_its_save_collection_table(struct vgic_its *its) static int vgic_its_restore_collection_table(struct vgic_its *its) { const struct vgic_its_abi *abi = vgic_its_get_abi(its); + u64 baser = its->baser_coll_table; int cte_esz = abi->cte_esz; size_t max_size, read = 0; gpa_t gpa; int ret; - if (!(its->baser_coll_table & GITS_BASER_VALID)) + if (!(baser & GITS_BASER_VALID)) return 0; - gpa = BASER_ADDRESS(its->baser_coll_table); + gpa = BASER_ADDRESS(baser); - max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K; + max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K; while (read < max_size) { ret = vgic_its_restore_cte(its, gpa, cte_esz); -- 2.5.5