xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Xen.org security team <security@xen.org>
To: xen-announce@lists.xen.org, xen-devel@lists.xen.org,
	xen-users@lists.xen.org, oss-security@lists.openwall.com
Cc: "Xen.org security team" <security-team-members@xen.org>
Subject: Xen Security Advisory 241 (CVE-2017-15588) - Stale TLB entry due to page type release race
Date: Wed, 18 Oct 2017 12:08:34 +0000	[thread overview]
Message-ID: <E1e4n9G-0001KT-1X@xenbits.xenproject.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 4376 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

            Xen Security Advisory CVE-2017-15588 / XSA-241
                              version 4

             Stale TLB entry due to page type release race

UPDATES IN VERSION 4
====================

CVE assigned.

ISSUE DESCRIPTION
=================

x86 PV guests effect TLB flushes by way of a hypercall.  Xen tries to
reduce the number of TLB flushes by delaying them as much as possible.
When the last type reference of a page is dropped, the need for a TLB
flush (before the page is re-used) is recorded.  If a guest TLB flush
request involves an Inter Processor Interrupt (IPI) to a CPU in which
is the process of dropping the last type reference of some page, and
if that IPI arrives at exactly the right instruction boundary, a stale
time stamp may be recorded, possibly resulting in the later omission
of the necessary TLB flush for that page.

IMPACT
======

A malicious x86 PV guest may be able to access all of system memory,
allowing for all of privilege escalation, host crashes, and
information leaks.

VULNERABLE SYSTEMS
==================

All Xen versions from at least 3.2 onwards are vulnerable.  Earlier
versions have not been checked.

Only x86 systems are affected.  ARM systems are not affected.

Only x86 PV guests can leverage the vulnerability.  x86 HVM guests
cannot leverage the vulnerability.

RISK ASSESSMENT
===============

A successful attack would require introducing an extended delay between
two adjacent operations on one cpu -- long enough for two hypercalls to
complete on another cpu.  The security team currently has no
proof-of-concept for this vulnerability.

However, techniques for these sorts of timing-based attacks are
continually advancing, so we still recommend users potentially affected
by this issue apply the patch as soon as reasonably possible.

MITIGATION
==========

Running only HVM guests will avoid this vulnerability.

For PV guests, the vulnerability can be avoided if the guest kernel is
controlled by the host rather than guest administrator, provided that
further steps are taken to prevent the guest administrator from loading
code into the kernel (e.g. by disabling loadable modules etc) or from
using other mechanisms which allow them to run code at kernel privilege.

CREDITS
=======

This issue was discovered by Jann Horn of Google Project Zero.

RESOLUTION
==========

Applying the appropriate attached patch resolves this issue.

xsa241.patch           xen-unstable
xsa241-4.9.patch       Xen 4.9.x
xsa241-4.8.patch       Xen 4.8.x, Xen 4.7.x, Xen 4.6.x, Xen 4.5.x

$ sha256sum xsa241*
5e239ba4dbd74fd61e59a27f9abc8ea6ba32532bdf81eeb2d7e66f0fd53e40b4  xsa241.meta
b8db933d53e7e289652ffda6c46ce284a0254a9f8bc9e1be6793e388009f49ce  xsa241.patch
443a5b0818045ada44fad0370ac01af0c96181be5a4078ae3b2575799e4a4e5b  xsa241-4.8.patch
927ef14d875556481c38d4065f501211a78eec1c2396a954a4a4abfb9255960f  xsa241-4.9.patch
$

DEPLOYMENT DURING EMBARGO
=========================

Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.

But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).

Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.

(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable.  This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)

For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
  http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBCAAGBQJZ50QlAAoJEIP+FMlX6CvZp/cH/2z+BXU30Jg8PlfnXM7LDulR
+ZyoPggsqJfE8AlY7XmsPXo8qY1vsG1NHI6D0YoTvgQyFDVa2h2IBkIc/aZd7jfW
iUYTluAQcxFKSC7G02HCrMdY6w9HkpIo4AtYw9Rm6tueF9/0vaWm0jy7MCMrNxAt
Dbx8a91dkKiJ9MImLralZUMewK6kym1p2PhVPgWmF3lprvLiLSbRu19eiYSAdjBa
C8ulKhUZsDymM3Lpe+F7+9FATZ58sEyvqgAach0Wn/vhaJ0axHroW3KKVCdNMNVJ
AqFHjv6NKgHGS3HU9TEOCfCptYqE+Ne/UB4M19nVOZulfZn4Ok2MgBvogJXIA/Q=
=7sHr
-----END PGP SIGNATURE-----

[-- Attachment #2: xsa241.meta --]
[-- Type: application/octet-stream, Size: 2185 bytes --]

{
  "XSA": 241,
  "SupportedVersions": [
    "master",
    "4.9",
    "4.8",
    "4.7",
    "4.6",
    "4.5"
  ],
  "Trees": [
    "xen"
  ],
  "Recipes": {
    "4.5": {
      "XenVersion": "4.5",
      "Recipes": {
        "xen": {
          "StableRef": "83724d9f3ae21a3b96362742e2f052b19d9f559a",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241-4.9.patch"
          ]
        }
      }
    },
    "4.6": {
      "XenVersion": "4.6",
      "Recipes": {
        "xen": {
          "StableRef": "1658a87690ac839e85db12bbf409be62bb938640",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241-4.9.patch"
          ]
        }
      }
    },
    "4.7": {
      "XenVersion": "4.7",
      "Recipes": {
        "xen": {
          "StableRef": "c7783d9c26fc191862d9883da22387340b1fab18",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241-4.9.patch"
          ]
        }
      }
    },
    "4.8": {
      "XenVersion": "4.8",
      "Recipes": {
        "xen": {
          "StableRef": "36898eb12572f0a1f85cb54d4a9e90afcb6f7045",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241-4.9.patch"
          ]
        }
      }
    },
    "4.9": {
      "XenVersion": "4.9",
      "Recipes": {
        "xen": {
          "StableRef": "2cc3d32f40c71cb242477a3f8938074d4fc36829",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241-4.9.patch"
          ]
        }
      }
    },
    "master": {
      "XenVersion": "master",
      "Recipes": {
        "xen": {
          "StableRef": "a8ea6e2688118a3e19e29b39e316faa5f96ab9d1",
          "Prereqs": [
            237,
            238,
            239,
            240
          ],
          "Patches": [
            "xsa241.patch"
          ]
        }
      }
    }
  }
}

[-- Attachment #3: xsa241.patch --]
[-- Type: application/octet-stream, Size: 6123 bytes --]

From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't store possibly stale TLB flush time stamp

While the timing window is extremely narrow, it is theoretically
possible for an update to the TLB flush clock and a subsequent flush
IPI to happen between the read and write parts of the update of the
per-page stamp. Exclude this possibility by disabling interrupts
across the update, preventing the IPI to be serviced in the middle.

This is XSA-241.

Reported-by: Jann Horn <jannh@google.com>
Suggested-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
---
v3: Fix ARM build issue.
v2: Rebase on top of staging + (237-240)

--- a/xen/arch/arm/smp.c
+++ b/xen/arch/arm/smp.c
@@ -1,3 +1,4 @@
+#include <xen/mm.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/cpregs.h>
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -488,7 +488,7 @@ void update_cr3(struct vcpu *v)
     make_cr3(v, cr3_mfn);
 }
 
-static inline void page_set_tlbflush_timestamp(struct page_info *page)
+static inline void set_tlbflush_timestamp(struct page_info *page)
 {
     /*
      * Record TLB information for flush later. We do not stamp page tables
@@ -499,7 +499,7 @@ static inline void page_set_tlbflush_timestamp(struct page_info *page)
      */
     if ( !(page->count_info & PGC_page_table) ||
          !shadow_mode_enabled(page_get_owner(page)) )
-        page->tlbflush_timestamp = tlbflush_current_time();
+        page_set_tlbflush_timestamp(page);
 }
 
 const char __section(".bss.page_aligned.const") __aligned(PAGE_SIZE)
@@ -2232,7 +2232,7 @@ static int _put_final_page_type(struct page_info *page, unsigned long type,
             dec_linear_entries(ptpg);
         }
         ASSERT(!page->linear_pt_count || page_get_owner(page)->is_dying);
-        page_set_tlbflush_timestamp(page);
+        set_tlbflush_timestamp(page);
         smp_wmb();
         page->u.inuse.type_info--;
     }
@@ -2240,7 +2240,7 @@ static int _put_final_page_type(struct page_info *page, unsigned long type,
     {
         ASSERT((page->u.inuse.type_info &
                 (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
-        page_set_tlbflush_timestamp(page);
+        set_tlbflush_timestamp(page);
         smp_wmb();
         page->u.inuse.type_info |= PGT_validated;
     }
@@ -2294,7 +2294,7 @@ static int _put_page_type(struct page_info *page, bool preemptible,
             if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
             {
                 /*
-                 * page_set_tlbflush_timestamp() accesses the same union
+                 * set_tlbflush_timestamp() accesses the same union
                  * linear_pt_count lives in. Unvalidated page table pages,
                  * however, should occur during domain destruction only
                  * anyway.  Updating of linear_pt_count luckily is not
@@ -2306,7 +2306,7 @@ static int _put_page_type(struct page_info *page, bool preemptible,
                 ptpg = NULL;
             }
 
-            page_set_tlbflush_timestamp(page);
+            set_tlbflush_timestamp(page);
         }
 
         if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 86186cccdf..7b16ed985d 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -1464,7 +1464,7 @@ void shadow_free(struct domain *d, mfn_t smfn)
          * TLBs when we reuse the page.  Because the destructors leave the
          * contents of the pages in place, we can delay TLB flushes until
          * just before the allocator hands the page out again. */
-        sp->tlbflush_timestamp = tlbflush_current_time();
+        page_set_tlbflush_timestamp(sp);
         perfc_decr(shadow_alloc_count);
         page_list_add_tail(sp, &d->arch.paging.shadow.freelist);
         sp = next;
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 0b9f6cc6df..0d6e53ccfa 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -1358,7 +1358,7 @@ static void free_heap_pages(
         /* If a page has no owner it will need no safety TLB flush. */
         pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
         if ( pg[i].u.free.need_tlbflush )
-            pg[i].tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(&pg[i]);
 
         /* This page is not a guest frame any more. */
         page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
diff --git a/xen/include/asm-arm/flushtlb.h b/xen/include/asm-arm/flushtlb.h
index a8e8a05363..83ff9fa8b3 100644
--- a/xen/include/asm-arm/flushtlb.h
+++ b/xen/include/asm-arm/flushtlb.h
@@ -12,6 +12,11 @@ static inline void tlbflush_filter(cpumask_t *mask, uint32_t page_timestamp) {}
 
 #define tlbflush_current_time()                 (0)
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    page->tlbflush_timestamp = tlbflush_current_time();
+}
+
 #if defined(CONFIG_ARM_32)
 # include <asm/arm32/flushtlb.h>
 #elif defined(CONFIG_ARM_64)
diff --git a/xen/include/asm-x86/flushtlb.h b/xen/include/asm-x86/flushtlb.h
index 131b31cfcc..413db692e1 100644
--- a/xen/include/asm-x86/flushtlb.h
+++ b/xen/include/asm-x86/flushtlb.h
@@ -23,6 +23,20 @@ DECLARE_PER_CPU(u32, tlbflush_time);
 
 #define tlbflush_current_time() tlbflush_clock
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    /*
+     * Prevent storing a stale time stamp, which could happen if an update
+     * to tlbflush_clock plus a subsequent flush IPI happen between the
+     * reading of tlbflush_clock and the writing of the struct page_info
+     * field.
+     */
+    ASSERT(local_irq_is_enabled());
+    local_irq_disable();
+    page->tlbflush_timestamp = tlbflush_current_time();
+    local_irq_enable();
+}
+
 /*
  * @cpu_stamp is the timestamp at last TLB flush for the CPU we are testing.
  * @lastuse_stamp is a timestamp taken when the PFN we are testing was last 
-- 
2.14.1


[-- Attachment #4: xsa241-4.8.patch --]
[-- Type: application/octet-stream, Size: 4959 bytes --]

x86: don't store possibly stale TLB flush time stamp

While the timing window is extremely narrow, it is theoretically
possible for an update to the TLB flush clock and a subsequent flush
IPI to happen between the read and write parts of the update of the
per-page stamp. Exclude this possibility by disabling interrupts
across the update, preventing the IPI to be serviced in the middle.

This is XSA-241.

Reported-by: Jann Horn <jannh@google.com>
Suggested-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>

--- a/xen/arch/arm/smp.c
+++ b/xen/arch/arm/smp.c
@@ -1,4 +1,5 @@
 #include <xen/config.h>
+#include <xen/mm.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/cpregs.h>
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2524,7 +2524,7 @@ static int _put_final_page_type(struct p
          */
         if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                (page->count_info & PGC_page_table)) )
-            page->tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(page);
         wmb();
         page->u.inuse.type_info--;
     }
@@ -2534,7 +2534,7 @@ static int _put_final_page_type(struct p
                 (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
         if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                (page->count_info & PGC_page_table)) )
-            page->tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(page);
         wmb();
         page->u.inuse.type_info |= PGT_validated;
     }
@@ -2588,7 +2588,7 @@ static int _put_page_type(struct page_in
             if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
             {
                 /*
-                 * page_set_tlbflush_timestamp() accesses the same union
+                 * set_tlbflush_timestamp() accesses the same union
                  * linear_pt_count lives in. Unvalidated page table pages,
                  * however, should occur during domain destruction only
                  * anyway.  Updating of linear_pt_count luckily is not
@@ -2609,7 +2609,7 @@ static int _put_page_type(struct page_in
              */
             if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                    (page->count_info & PGC_page_table)) )
-                page->tlbflush_timestamp = tlbflush_current_time();
+                page_set_tlbflush_timestamp(page);
         }
 
         if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -1464,7 +1464,7 @@ void shadow_free(struct domain *d, mfn_t
          * TLBs when we reuse the page.  Because the destructors leave the
          * contents of the pages in place, we can delay TLB flushes until
          * just before the allocator hands the page out again. */
-        sp->tlbflush_timestamp = tlbflush_current_time();
+        page_set_tlbflush_timestamp(sp);
         perfc_decr(shadow_alloc_count);
         page_list_add_tail(sp, &d->arch.paging.shadow.freelist);
         sp = next;
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -960,7 +960,7 @@ static void free_heap_pages(
         /* If a page has no owner it will need no safety TLB flush. */
         pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
         if ( pg[i].u.free.need_tlbflush )
-            pg[i].tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(&pg[i]);
 
         /* This page is not a guest frame any more. */
         page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
--- a/xen/include/asm-arm/flushtlb.h
+++ b/xen/include/asm-arm/flushtlb.h
@@ -12,6 +12,11 @@ static inline void tlbflush_filter(cpuma
 
 #define tlbflush_current_time()                 (0)
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    page->tlbflush_timestamp = tlbflush_current_time();
+}
+
 #if defined(CONFIG_ARM_32)
 # include <asm/arm32/flushtlb.h>
 #elif defined(CONFIG_ARM_64)
--- a/xen/include/asm-x86/flushtlb.h
+++ b/xen/include/asm-x86/flushtlb.h
@@ -23,6 +23,20 @@ DECLARE_PER_CPU(u32, tlbflush_time);
 
 #define tlbflush_current_time() tlbflush_clock
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    /*
+     * Prevent storing a stale time stamp, which could happen if an update
+     * to tlbflush_clock plus a subsequent flush IPI happen between the
+     * reading of tlbflush_clock and the writing of the struct page_info
+     * field.
+     */
+    ASSERT(local_irq_is_enabled());
+    local_irq_disable();
+    page->tlbflush_timestamp = tlbflush_current_time();
+    local_irq_enable();
+}
+
 /*
  * @cpu_stamp is the timestamp at last TLB flush for the CPU we are testing.
  * @lastuse_stamp is a timestamp taken when the PFN we are testing was last 

[-- Attachment #5: xsa241-4.9.patch --]
[-- Type: application/octet-stream, Size: 4981 bytes --]

From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't store possibly stale TLB flush time stamp

While the timing window is extremely narrow, it is theoretically
possible for an update to the TLB flush clock and a subsequent flush
IPI to happen between the read and write parts of the update of the
per-page stamp. Exclude this possibility by disabling interrupts
across the update, preventing the IPI to be serviced in the middle.

This is XSA-241.

Reported-by: Jann Horn <jannh@google.com>
Suggested-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>

--- a/xen/arch/arm/smp.c
+++ b/xen/arch/arm/smp.c
@@ -1,3 +1,4 @@
+#include <xen/mm.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/cpregs.h>
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2524,7 +2524,7 @@ static int _put_final_page_type(struct p
          */
         if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                (page->count_info & PGC_page_table)) )
-            page->tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(page);
         wmb();
         page->u.inuse.type_info--;
     }
@@ -2534,7 +2534,7 @@ static int _put_final_page_type(struct p
                 (PGT_count_mask|PGT_validated|PGT_partial)) == 1);
         if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                (page->count_info & PGC_page_table)) )
-            page->tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(page);
         wmb();
         page->u.inuse.type_info |= PGT_validated;
     }
@@ -2588,7 +2588,7 @@ static int _put_page_type(struct page_in
             if ( ptpg && PGT_type_equal(x, ptpg->u.inuse.type_info) )
             {
                 /*
-                 * page_set_tlbflush_timestamp() accesses the same union
+                 * set_tlbflush_timestamp() accesses the same union
                  * linear_pt_count lives in. Unvalidated page table pages,
                  * however, should occur during domain destruction only
                  * anyway.  Updating of linear_pt_count luckily is not
@@ -2609,7 +2609,7 @@ static int _put_page_type(struct page_in
              */
             if ( !(shadow_mode_enabled(page_get_owner(page)) &&
                    (page->count_info & PGC_page_table)) )
-                page->tlbflush_timestamp = tlbflush_current_time();
+                page_set_tlbflush_timestamp(page);
         }
 
         if ( likely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) == x) )
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -1464,7 +1464,7 @@ void shadow_free(struct domain *d, mfn_t
          * TLBs when we reuse the page.  Because the destructors leave the
          * contents of the pages in place, we can delay TLB flushes until
          * just before the allocator hands the page out again. */
-        sp->tlbflush_timestamp = tlbflush_current_time();
+        page_set_tlbflush_timestamp(sp);
         perfc_decr(shadow_alloc_count);
         page_list_add_tail(sp, &d->arch.paging.shadow.freelist);
         sp = next;
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -960,7 +960,7 @@ static void free_heap_pages(
         /* If a page has no owner it will need no safety TLB flush. */
         pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
         if ( pg[i].u.free.need_tlbflush )
-            pg[i].tlbflush_timestamp = tlbflush_current_time();
+            page_set_tlbflush_timestamp(&pg[i]);
 
         /* This page is not a guest frame any more. */
         page_set_owner(&pg[i], NULL); /* set_gpfn_from_mfn snoops pg owner */
--- a/xen/include/asm-arm/flushtlb.h
+++ b/xen/include/asm-arm/flushtlb.h
@@ -12,6 +12,11 @@ static inline void tlbflush_filter(cpuma
 
 #define tlbflush_current_time()                 (0)
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    page->tlbflush_timestamp = tlbflush_current_time();
+}
+
 #if defined(CONFIG_ARM_32)
 # include <asm/arm32/flushtlb.h>
 #elif defined(CONFIG_ARM_64)
--- a/xen/include/asm-x86/flushtlb.h
+++ b/xen/include/asm-x86/flushtlb.h
@@ -23,6 +23,20 @@ DECLARE_PER_CPU(u32, tlbflush_time);
 
 #define tlbflush_current_time() tlbflush_clock
 
+static inline void page_set_tlbflush_timestamp(struct page_info *page)
+{
+    /*
+     * Prevent storing a stale time stamp, which could happen if an update
+     * to tlbflush_clock plus a subsequent flush IPI happen between the
+     * reading of tlbflush_clock and the writing of the struct page_info
+     * field.
+     */
+    ASSERT(local_irq_is_enabled());
+    local_irq_disable();
+    page->tlbflush_timestamp = tlbflush_current_time();
+    local_irq_enable();
+}
+
 /*
  * @cpu_stamp is the timestamp at last TLB flush for the CPU we are testing.
  * @lastuse_stamp is a timestamp taken when the PFN we are testing was last 

[-- Attachment #6: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

                 reply	other threads:[~2017-10-18 12:08 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=E1e4n9G-0001KT-1X@xenbits.xenproject.org \
    --to=security@xen.org \
    --cc=oss-security@lists.openwall.com \
    --cc=security-team-members@xen.org \
    --cc=xen-announce@lists.xen.org \
    --cc=xen-devel@lists.xen.org \
    --cc=xen-users@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).