From patchwork Tue May 21 07:45:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Norbert Manthey X-Patchwork-Id: 10953083 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7006E14C0 for ; Tue, 21 May 2019 07:48:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 617E72892C for ; Tue, 21 May 2019 07:48:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 558E828961; Tue, 21 May 2019 07:48:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_ADSP_ALL, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E7B172892C for ; Tue, 21 May 2019 07:48:27 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzTv-0007mS-1M; Tue, 21 May 2019 07:46:43 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzTt-0007mJ-J9 for xen-devel@lists.xenproject.org; Tue, 21 May 2019 07:46:41 +0000 X-Inumbo-ID: 91f33a10-7b9c-11e9-9bfb-1fca9b551493 Received: from smtp-fw-2101.amazon.com (unknown [72.21.196.25]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 91f33a10-7b9c-11e9-9bfb-1fca9b551493; Tue, 21 May 2019 07:46:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1558424800; x=1589960800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=xzkF0tptD1K+vwbOYdTSieHRrkGZbMSfljV+kn7SWDI=; b=nVhHJ8ToplmqXLf94sh+fTMxfGdp3Qfxvu00ROWchqBR6HSnO90FASif jqnpuvAVZfGZQqohCLO940/yaXF+fA3GiCJCYn3kByMkLwvDBM/bJZTp0 r2uMnKkKgEykMg4cWuv86vQQxjhuWFo2L5jxPj1kb5eK5l6cAz2CvMQcD o=; X-IronPort-AV: E=Sophos;i="5.60,494,1549929600"; d="scan'208";a="733992337" Received: from iad6-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-2c-397e131e.us-west-2.amazon.com) ([10.124.125.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 21 May 2019 07:46:39 +0000 Received: from EX13MTAUEB001.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan2.pdx.amazon.com [10.236.137.194]) by email-inbound-relay-2c-397e131e.us-west-2.amazon.com (8.14.7/8.14.7) with ESMTP id x4L7kYIV080694 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=FAIL); Tue, 21 May 2019 07:46:37 GMT Received: from EX13D08UEB004.ant.amazon.com (10.43.60.142) by EX13MTAUEB001.ant.amazon.com (10.43.60.96) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:46:24 +0000 Received: from EX13MTAUWB001.ant.amazon.com (10.43.161.207) by EX13D08UEB004.ant.amazon.com (10.43.60.142) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:46:23 +0000 Received: from uc1a35a69ae4659.ant.amazon.com (10.28.85.34) by mail-relay.amazon.com (10.43.161.249) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Tue, 21 May 2019 07:46:19 +0000 From: Norbert Manthey To: Date: Tue, 21 May 2019 09:45:44 +0200 Message-ID: <1558424746-24059-2-git-send-email-nmanthey@amazon.de> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> References: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH L1TF MDS GT v1 1/3] common/grant_table: harden helpers X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Tim Deegan , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Dario Faggioli , Martin Pohlack , Pawel Wieczorkiewicz , Julien Grall , David Woodhouse , Jan Beulich , Martin Mazein , Bjoern Doebel , Norbert Manthey Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Guests can issue grant table operations and provide guest controlled data to them. This data is used for memory loads in helper functions and macros. To avoid speculative out-of-bound accesses, we use the array_index_nospec macro where applicable, or the block_speculation macro. This is part of the speculative hardening effort. Signed-off-by: Norbert Manthey Reviewed-by: Jan Beulich --- Notes: v1: split the gnttab commit of the previous L1TF series into multiple commits xen/common/grant_table.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -203,8 +204,9 @@ static inline unsigned int nr_status_frames(const struct grant_table *gt) } #define MAPTRACK_PER_PAGE (PAGE_SIZE / sizeof(struct grant_mapping)) -#define maptrack_entry(t, e) \ - ((t)->maptrack[(e)/MAPTRACK_PER_PAGE][(e)%MAPTRACK_PER_PAGE]) +#define maptrack_entry(t, e) \ + ((t)->maptrack[array_index_nospec(e, (t)->maptrack_limit) / \ + MAPTRACK_PER_PAGE][(e) % MAPTRACK_PER_PAGE]) static inline unsigned int nr_maptrack_frames(struct grant_table *t) @@ -226,10 +228,23 @@ nr_maptrack_frames(struct grant_table *t) static grant_entry_header_t * shared_entry_header(struct grant_table *t, grant_ref_t ref) { - if ( t->gt_version == 1 ) + switch ( t->gt_version ) + { + case 1: + /* Returned values should be independent of speculative execution */ + block_speculation(); return (grant_entry_header_t*)&shared_entry_v1(t, ref); - else + + case 2: + /* Returned values should be independent of speculative execution */ + block_speculation(); return &shared_entry_v2(t, ref).hdr; + } + + ASSERT_UNREACHABLE(); + block_speculation(); + + return NULL; } /* Active grant entry - used for shadowing GTF_permit_access grants. */ @@ -634,14 +649,24 @@ static unsigned int nr_grant_entries(struct grant_table *gt) case 1: BUILD_BUG_ON(f2e(INITIAL_NR_GRANT_FRAMES, 1) < GNTTAB_NR_RESERVED_ENTRIES); + + /* Make sure we return a value independently of speculative execution */ + block_speculation(); return f2e(nr_grant_frames(gt), 1); + case 2: BUILD_BUG_ON(f2e(INITIAL_NR_GRANT_FRAMES, 2) < GNTTAB_NR_RESERVED_ENTRIES); + + /* Make sure we return a value independently of speculative execution */ + block_speculation(); return f2e(nr_grant_frames(gt), 2); #undef f2e } + ASSERT_UNREACHABLE(); + block_speculation(); + return 0; } From patchwork Tue May 21 07:45:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Norbert Manthey X-Patchwork-Id: 10953081 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9FAAD14C0 for ; Tue, 21 May 2019 07:48:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8BCA52892C for ; Tue, 21 May 2019 07:48:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B0DA28961; Tue, 21 May 2019 07:48:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_ADSP_ALL, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D08292892C for ; Tue, 21 May 2019 07:48:22 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzUJ-0007pg-Cj; Tue, 21 May 2019 07:47:07 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzUH-0007pT-KC for xen-devel@lists.xenproject.org; Tue, 21 May 2019 07:47:05 +0000 X-Inumbo-ID: 9dfd0002-7b9c-11e9-ace0-3b2f95878d83 Received: from smtp-fw-6002.amazon.com (unknown [52.95.49.90]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 9dfd0002-7b9c-11e9-ace0-3b2f95878d83; Tue, 21 May 2019 07:47:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1558424820; x=1589960820; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=mKyUkwpJiWDN4bs7yGZA4ydno1021YOJ4zwRCjdLdzI=; b=KW0svLLoZwn1z7g8UFwFUKMwsltfaZ8nfLVskCo0/ew3eDUtt1xKDL/d u5QKccsrGSmIbXNiY49YLPTptBI/vvaJ6CDX3i8HjmKbEzniwvXB5+dlP XZMf+qodJ1MF8T0rre0arnuynSPHfe7Lar8LRn07OdJIFQiEMYos3t3Ml g=; X-IronPort-AV: E=Sophos;i="5.60,494,1549929600"; d="scan'208";a="403024841" Received: from iad6-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2b-c300ac87.us-west-2.amazon.com) ([10.124.125.6]) by smtp-border-fw-out-6002.iad6.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 21 May 2019 07:46:58 +0000 Received: from EX13MTAUEA001.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan3.pdx.amazon.com [10.236.137.198]) by email-inbound-relay-2b-c300ac87.us-west-2.amazon.com (8.14.7/8.14.7) with ESMTP id x4L7kqTG056728 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=FAIL); Tue, 21 May 2019 07:46:58 GMT Received: from EX13D08UEE002.ant.amazon.com (10.43.62.92) by EX13MTAUEA001.ant.amazon.com (10.43.61.243) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:46:57 +0000 Received: from EX13MTAUWB001.ant.amazon.com (10.43.161.207) by EX13D08UEE002.ant.amazon.com (10.43.62.92) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:46:57 +0000 Received: from uc1a35a69ae4659.ant.amazon.com (10.28.85.34) by mail-relay.amazon.com (10.43.161.249) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Tue, 21 May 2019 07:46:53 +0000 From: Norbert Manthey To: Date: Tue, 21 May 2019 09:45:45 +0200 Message-ID: <1558424746-24059-3-git-send-email-nmanthey@amazon.de> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> References: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH L1TF MDS GT v1 2/3] common/grant_table: harden bound accesses X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Tim Deegan , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Dario Faggioli , Martin Pohlack , Pawel Wieczorkiewicz , Julien Grall , David Woodhouse , Jan Beulich , Martin Mazein , Bjoern Doebel , Norbert Manthey Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Guests can issue grant table operations and provide guest controlled data to them. This data is used as index for memory loads after bound checks have been done. To avoid speculative out-of-bound accesses, we use the array_index_nospec macro where applicable, or the macro block_speculation. Note, that the block_speculation is always used in the calls to shared_entry_header and nr_grant_entries, so that no additional protection is required once these functions have been called. Speculative execution is not blocked in case one of the following properties is true: - path cannot be triggered by the guest - path does not return to the guest - path does not result in an out-of-bound access - path cannot be executed repeatedly Only the combination of the above properties allows to actually leak continuous chunks of memory. Therefore, we only add the penalty of protective mechanisms in case a potential speculative out-of-bound access matches all the above properties. This commit addresses only out-of-bound accesses whose index is directly controlled by the guest, and the index is checked before. Potential out-of-bound accesses that are caused by speculatively evaluating the version of the current table are not addressed in this commit. This is part of the speculative hardening effort. Signed-off-by: Norbert Manthey --- Notes: v1: adapt the comments for shared_entry_header to show that they 'also' block speculative execution xen/common/grant_table.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -988,9 +988,10 @@ map_grant_ref( PIN_FAIL(unlock_out, GNTST_bad_gntref, "Bad ref %#x for d%d\n", op->ref, rgt->domain->domain_id); - act = active_entry_acquire(rgt, op->ref); + /* This call also ensures the above check cannot be passed speculatively */ shah = shared_entry_header(rgt, op->ref); status = rgt->gt_version == 1 ? &shah->flags : &status_entry(rgt, op->ref); + act = active_entry_acquire(rgt, op->ref); /* If already pinned, check the active domid and avoid refcnt overflow. */ if ( act->pin && @@ -1346,6 +1347,9 @@ unmap_common( goto unlock_out; } + /* Make sure the above bound check cannot be bypassed speculatively */ + block_speculation(); + act = active_entry_acquire(rgt, op->ref); /* @@ -1443,7 +1447,7 @@ unmap_common_complete(struct gnttab_unmap_common *op) struct page_info *pg; uint16_t *status; - if ( !op->done ) + if ( evaluate_nospec(!op->done) ) { /* unmap_common() didn't do anything - nothing to complete. */ return; @@ -2051,6 +2055,7 @@ gnttab_prepare_for_transfer( goto fail; } + /* This call also ensures the above check cannot be passed speculatively */ sha = shared_entry_header(rgt, ref); scombo.word = *(u32 *)&sha->flags; @@ -2248,7 +2253,12 @@ gnttab_transfer( spin_unlock(&e->page_alloc_lock); okay = gnttab_prepare_for_transfer(e, d, gop.ref); - if ( unlikely(!okay || assign_pages(e, page, 0, MEMF_no_refcount)) ) + /* + * Make sure the reference bound check in gnttab_prepare_for_transfer + * is respected and speculative execution is blocked accordingly + */ + if ( unlikely(!evaluate_nospec(okay)) || + unlikely(assign_pages(e, page, 0, MEMF_no_refcount)) ) { bool drop_dom_ref; @@ -2435,8 +2445,10 @@ acquire_grant_for_copy( PIN_FAIL(gt_unlock_out, GNTST_bad_gntref, "Bad grant reference %#x\n", gref); - act = active_entry_acquire(rgt, gref); + /* This call also ensures the above check cannot be passed speculatively */ shah = shared_entry_header(rgt, gref); + act = active_entry_acquire(rgt, gref); + if ( rgt->gt_version == 1 ) { sha2 = NULL; @@ -2853,6 +2865,9 @@ static int gnttab_copy_buf(const struct gnttab_copy *op, op->dest.offset, dest->ptr.offset, op->len, dest->len); + /* Make sure the above checks are not bypassed speculatively */ + block_speculation(); + memcpy(dest->virt + op->dest.offset, src->virt + op->source.offset, op->len); gnttab_mark_dirty(dest->domain, dest->mfn); @@ -2972,7 +2987,7 @@ gnttab_set_version(XEN_GUEST_HANDLE_PARAM(gnttab_set_version_t) uop) struct grant_table *gt = currd->grant_table; grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES]; int res; - unsigned int i; + unsigned int i, nr_ents; if ( copy_from_guest(&op, uop, 1) ) return -EFAULT; @@ -2996,7 +3011,8 @@ gnttab_set_version(XEN_GUEST_HANDLE_PARAM(gnttab_set_version_t) uop) * are allowed to be in use (xenstore/xenconsole keeps them mapped). * (You need to change the version number for e.g. kexec.) */ - for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++ ) + nr_ents = nr_grant_entries(gt); + for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_ents; i++ ) { if ( read_atomic(&_active_entry(gt, i).pin) != 0 ) { @@ -3238,6 +3254,9 @@ swap_grant_ref(grant_ref_t ref_a, grant_ref_t ref_b) if ( unlikely(ref_b >= nr_grant_entries(d->grant_table))) PIN_FAIL(out, GNTST_bad_gntref, "Bad ref-b %#x\n", ref_b); + /* Make sure the above checks are not bypassed speculatively */ + block_speculation(); + /* Swapping the same ref is a no-op. */ if ( ref_a == ref_b ) goto out; @@ -3707,13 +3726,14 @@ void grant_table_warn_active_grants(struct domain *d) struct grant_table *gt = d->grant_table; struct active_grant_entry *act; grant_ref_t ref; - unsigned int nr_active = 0; + unsigned int nr_active = 0, nr_ents; #define WARN_GRANT_MAX 10 grant_read_lock(gt); - for ( ref = 0; ref != nr_grant_entries(gt); ref++ ) + nr_ents = nr_grant_entries(gt); + for ( ref = 0; ref != nr_ents; ref++ ) { act = active_entry_acquire(gt, ref); if ( !act->pin ) @@ -3863,6 +3883,9 @@ static int gnttab_get_status_frame_mfn(struct domain *d, return -EINVAL; } + /* Make sure idx is bounded wrt nr_status_frames */ + block_speculation(); + *mfn = _mfn(virt_to_mfn(gt->status[idx])); return 0; } @@ -3962,6 +3985,7 @@ static void gnttab_usage_print(struct domain *rd) int first = 1; grant_ref_t ref; struct grant_table *gt = rd->grant_table; + unsigned int nr_ents; printk(" -------- active -------- -------- shared --------\n"); printk("[ref] localdom mfn pin localdom gmfn flags\n"); @@ -3974,7 +3998,8 @@ static void gnttab_usage_print(struct domain *rd) nr_grant_frames(gt), gt->max_grant_frames, nr_maptrack_frames(gt), gt->max_maptrack_frames); - for ( ref = 0; ref != nr_grant_entries(gt); ref++ ) + nr_ents = nr_grant_entries(gt); + for ( ref = 0; ref != nr_ents; ref++ ) { struct active_grant_entry *act; struct grant_entry_header *sha; From patchwork Tue May 21 07:45:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Norbert Manthey X-Patchwork-Id: 10953085 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D157314C0 for ; Tue, 21 May 2019 07:48:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C06572892C for ; Tue, 21 May 2019 07:48:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B47C328961; Tue, 21 May 2019 07:48:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_ADSP_ALL, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2ACF22892C for ; Tue, 21 May 2019 07:48:57 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzUo-0007w1-T4; Tue, 21 May 2019 07:47:38 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hSzUn-0007vq-Hs for xen-devel@lists.xenproject.org; Tue, 21 May 2019 07:47:37 +0000 X-Inumbo-ID: b2ee79e8-7b9c-11e9-8980-bc764e045a96 Received: from smtp-fw-2101.amazon.com (unknown [72.21.196.25]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id b2ee79e8-7b9c-11e9-8980-bc764e045a96; Tue, 21 May 2019 07:47:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1558424856; x=1589960856; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=Gn4S26oLtLdOoPExfexD3mJ+nmKDf8huMc68XiI9qM4=; b=HUZBVcAXlKqdDrFA0nix+svQ6bnpLAE7WWhwlWdPWAz9KGNR6i56puls aG1arHghGZeXeAsKM7BXrBvnGVskNofzbDEHvYeLiONT5DcTGBK4D+tj4 0/nduD6YXg7iesx8fn2T/Kwm/H0OKySjSa4l5eASEBdirOkYIr/bHVCtQ Y=; X-IronPort-AV: E=Sophos;i="5.60,494,1549929600"; d="scan'208";a="733992446" Received: from iad6-co-svc-p1-lb1-vlan2.amazon.com (HELO email-inbound-relay-2a-1c1b5cdd.us-west-2.amazon.com) ([10.124.125.2]) by smtp-border-fw-out-2101.iad2.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 21 May 2019 07:47:34 +0000 Received: from EX13MTAUEA001.ant.amazon.com (pdx1-ws-svc-p6-lb9-vlan3.pdx.amazon.com [10.236.137.198]) by email-inbound-relay-2a-1c1b5cdd.us-west-2.amazon.com (8.14.7/8.14.7) with ESMTP id x4L7lTff120976 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=FAIL); Tue, 21 May 2019 07:47:30 GMT Received: from EX13D08UEE001.ant.amazon.com (10.43.62.126) by EX13MTAUEA001.ant.amazon.com (10.43.61.82) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:47:19 +0000 Received: from EX13MTAUWB001.ant.amazon.com (10.43.161.207) by EX13D08UEE001.ant.amazon.com (10.43.62.126) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 21 May 2019 07:47:19 +0000 Received: from uc1a35a69ae4659.ant.amazon.com (10.28.85.34) by mail-relay.amazon.com (10.43.161.249) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Tue, 21 May 2019 07:47:15 +0000 From: Norbert Manthey To: Date: Tue, 21 May 2019 09:45:46 +0200 Message-ID: <1558424746-24059-4-git-send-email-nmanthey@amazon.de> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> References: <1558424746-24059-1-git-send-email-nmanthey@amazon.de> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH L1TF MDS GT v1 3/3] common/grant_table: harden version dependent accesses X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Tim Deegan , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Dario Faggioli , Martin Pohlack , Pawel Wieczorkiewicz , Julien Grall , David Woodhouse , Jan Beulich , Martin Mazein , Bjoern Doebel , Norbert Manthey Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Guests can issue grant table operations and provide guest controlled data to them. This data is used as index for memory loads after bound checks have been done. Depending on the grant table version, the size of elements in containers differ. As the base data structure is a page, the number of elements per page also differs. Consequently, bound checks are version dependent, so that speculative execution can happen in several stages, the bound check as well as the version check. This commit mitigates cases where out-of-bound accesses could happen due to the version comparison. In cases, where no different memory locations are accessed on the code path that follow an if statement, no protection is required. No different memory locations are accessed in the following functions after a version check: * gnttab_setup_table: only calculated numbersi are used, and then function gnttab_grow_table is called, which is version protected * gnttab_transfer: the case that depends on the version check just gets into copying a page or not * acquire_grant_for_copy: the not fixed comparison is on the abort path and does not access other structures, and on the else branch only accesses structures that are properly allocated * gnttab_set_version: all accessible data is allocated for both versions * gnttab_release_mappings: this function is called only during domain destruction and control is not returned to the guest * mem_sharing_gref_to_gfn: speculation will be stoped by the second if statement, as that places a barrier on any path to be executed. * gnttab_get_status_frame_mfn: no version dependent check, because all accesses, except the gt->status[idx], do not perform actual out-of-bound accesses, including the gnttab_grow_table function call. * gnttab_get_shared_frame: block_speculation in gnttab_get_status_frame_mfn blocks accesses * gnttab_usage_print: cannot be triggered by the guest This is part of the speculative hardening effort. Signed-off-by: Norbert Manthey --- Notes: v1: added additional fixes (compared to L1TF series) to: _set_status unmap_common_complete gnttab_grow_table xen/common/grant_table.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -837,7 +837,7 @@ static int _set_status(unsigned gt_version, grant_status_t *status) { - if ( gt_version == 1 ) + if ( evaluate_nospec(gt_version == 1) ) return _set_status_v1(domid, readonly, mapflag, shah, act); else return _set_status_v2(domid, readonly, mapflag, shah, act, status); @@ -990,9 +990,12 @@ map_grant_ref( /* This call also ensures the above check cannot be passed speculatively */ shah = shared_entry_header(rgt, op->ref); - status = rgt->gt_version == 1 ? &shah->flags : &status_entry(rgt, op->ref); act = active_entry_acquire(rgt, op->ref); + /* Make sure we do not access memory speculatively */ + status = evaluate_nospec(rgt->gt_version == 1) ? &shah->flags + : &status_entry(rgt, op->ref); + /* If already pinned, check the active domid and avoid refcnt overflow. */ if ( act->pin && ((act->domid != ld->domain_id) || @@ -1013,7 +1016,7 @@ map_grant_ref( if ( !act->pin ) { - unsigned long gfn = rgt->gt_version == 1 ? + unsigned long gfn = evaluate_nospec(rgt->gt_version == 1) ? shared_entry_v1(rgt, op->ref).frame : shared_entry_v2(rgt, op->ref).full_page.frame; @@ -1463,7 +1466,7 @@ unmap_common_complete(struct gnttab_unmap_common *op) act = active_entry_acquire(rgt, op->ref); sha = shared_entry_header(rgt, op->ref); - if ( rgt->gt_version == 1 ) + if ( evaluate_nospec(rgt->gt_version == 1) ) status = &sha->flags; else status = &status_entry(rgt, op->ref); @@ -1795,7 +1798,7 @@ gnttab_grow_table(struct domain *d, unsigned int req_nr_frames) } /* Status pages - version 2 */ - if ( gt->gt_version > 1 ) + if ( evaluate_nospec(gt->gt_version > 1) ) { if ( gnttab_populate_status_frames(d, gt, req_nr_frames) ) goto shared_alloc_failed; @@ -2290,7 +2293,7 @@ gnttab_transfer( grant_read_lock(e->grant_table); act = active_entry_acquire(e->grant_table, gop.ref); - if ( e->grant_table->gt_version == 1 ) + if ( evaluate_nospec(e->grant_table->gt_version == 1) ) { grant_entry_v1_t *sha = &shared_entry_v1(e->grant_table, gop.ref); @@ -2351,7 +2354,7 @@ release_grant_for_copy( sha = shared_entry_header(rgt, gref); mfn = act->mfn; - if ( rgt->gt_version == 1 ) + if ( evaluate_nospec(rgt->gt_version == 1) ) { status = &sha->flags; td = rd; @@ -2449,7 +2452,7 @@ acquire_grant_for_copy( shah = shared_entry_header(rgt, gref); act = active_entry_acquire(rgt, gref); - if ( rgt->gt_version == 1 ) + if ( evaluate_nospec(rgt->gt_version == 1) ) { sha2 = NULL; status = &shah->flags; @@ -3269,7 +3272,7 @@ swap_grant_ref(grant_ref_t ref_a, grant_ref_t ref_b) if ( act_b->pin ) PIN_FAIL(out, GNTST_eagain, "ref b %#x busy\n", ref_b); - if ( gt->gt_version == 1 ) + if ( evaluate_nospec(gt->gt_version == 1) ) { grant_entry_v1_t shared; @@ -3818,7 +3821,7 @@ int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref, rc = -EINVAL; else if ( ref >= nr_grant_entries(gt) ) rc = -ENOENT; - else if ( gt->gt_version == 1 ) + else if ( evaluate_nospec(gt->gt_version == 1) ) { const grant_entry_v1_t *sha1 = &shared_entry_v1(gt, ref); @@ -3840,7 +3843,7 @@ int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref, rc = -ENXIO; else if ( !rc && status ) { - if ( gt->gt_version == 1 ) + if ( evaluate_nospec(gt->gt_version == 1) ) *status = flags; else *status = status_entry(gt, ref); @@ -3927,7 +3930,7 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn, mfn_t *mfn) grant_write_lock(gt); - if ( gt->gt_version == 2 && (idx & XENMAPIDX_grant_table_status) ) + if ( evaluate_nospec(gt->gt_version == 2) && (idx & XENMAPIDX_grant_table_status) ) { idx &= ~XENMAPIDX_grant_table_status; status = true;