From patchwork Wed Aug 22 06:40:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juerg Haefliger X-Patchwork-Id: 960800 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41wHxB1dNbz9s7X; Wed, 22 Aug 2018 16:40:46 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1fsMoo-00070r-QI; Wed, 22 Aug 2018 06:40:38 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1fsMog-0006uv-9w for kernel-team@lists.ubuntu.com; Wed, 22 Aug 2018 06:40:30 +0000 Received: from mail-ed1-f71.google.com ([209.85.208.71]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1fsMog-0004F0-00 for kernel-team@lists.ubuntu.com; Wed, 22 Aug 2018 06:40:30 +0000 Received: by mail-ed1-f71.google.com with SMTP id k48-v6so490496ede.14 for ; Tue, 21 Aug 2018 23:40:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Z+CEvP+MXUBVQnjpfgjRNrbopTCTqreOnjS6Xm8g0cs=; b=f3pHp7TY2X54a3RAgoE2xWFATk4Q2KF7AB5gH3pWLXVPPmZarfG4hP1dCB94IlmPvo hxB+3VUqmJLf8cpIcxP2GMOf6p9UJ3RsofsbQWe0gDVKb/r5S+B1zmEgLNTDDAqc1GE0 Het9MHWO1BGIm2wPT1aWJjd4fGLhrkff5r3elAOfVJkaqHcIbukJ11//9AX7LTzml4xs RLX5oZ8HbIva0MwkScUg/bcDWHbC2V1ljRdCrS5sWrJvu922019eJPgb6nQcZbLqzA/i OT1LCs3WiIAV9TbKGpR1GAH7SmtqOCWJqIutdhd85hFRtUen0ARK36NltJtLMyRgLUjG HGyA== X-Gm-Message-State: AOUpUlFN8L5hTMJnOISZv368EftqJXMJpRWL0mEp/DpCpgda6m2GzSnm Ielf/P5VcqofgfS1xNX/ikQ3RDlNDRqPPWeAvVHgUK0P+0cHHsPqR19Oensl6YQEVGSEDbLaU26 u6wOv02jnKTO1sZ9LdEG/X/qQoAtq9m8mpBfAdnnVfQ== X-Received: by 2002:a50:b003:: with SMTP id i3-v6mr9452599edd.120.1534920029401; Tue, 21 Aug 2018 23:40:29 -0700 (PDT) X-Google-Smtp-Source: AA+uWPy+BXoQJiEtymJiXhNte69boDK4O5yZDELlRmVUgXqAdZzs/C3KOaWWh9iG4oicPMVQPE/EGQ== X-Received: by 2002:a50:b003:: with SMTP id i3-v6mr9452588edd.120.1534920029261; Tue, 21 Aug 2018 23:40:29 -0700 (PDT) Received: from localhost.localdomain ([81.221.205.149]) by smtp.gmail.com with ESMTPSA id j23-v6sm529350edh.29.2018.08.21.23.40.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Aug 2018 23:40:28 -0700 (PDT) From: Juerg Haefliger X-Google-Original-From: Juerg Haefliger To: kernel-team@lists.ubuntu.com Subject: [SRU][Trusty][PATCH 5/7] x86,mm: fix pte_special versus pte_numa Date: Wed, 22 Aug 2018 08:40:19 +0200 Message-Id: <20180822064021.17216-6-juergh@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180822064021.17216-1-juergh@canonical.com> References: <20180822064021.17216-1-juergh@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: juergh@canonical.com MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Hugh Dickins Sasha Levin has shown oopses on ffffea0003480048 and ffffea0003480008 at mm/memory.c:1132, running Trinity on different 3.16-rc-next kernels: where zap_pte_range() checks page->mapping to see if PageAnon(page). Those addresses fit struct pages for pfns d2001 and d2000, and in each dump a register or a stack slot showed d2001730 or d2000730: pte flags 0x730 are PCD ACCESSED PROTNONE SPECIAL IOMAP; and Sasha's e820 map has a hole between cfffffff and 100000000, which would need special access. Commit c46a7c817e66 ("x86: define _PAGE_NUMA by reusing software bits on the PMD and PTE levels") has broken vm_normal_page(): a PROTNONE SPECIAL pte no longer passes the pte_special() test, so zap_pte_range() goes on to try to access a non-existent struct page. Fix this by refining pte_special() (SPECIAL with PRESENT or PROTNONE) to complement pte_numa() (SPECIAL with neither PRESENT nor PROTNONE). A hint that this was a problem was that c46a7c817e66 added pte_numa() test to vm_normal_page(), and moved its is_zero_pfn() test from slow to fast path: This was papering over a pte_special() snag when the zero page was encountered during zap. This patch reverts vm_normal_page() to how it was before, relying on pte_special(). It still appears that this patch may be incomplete: aren't there other places which need to be handling PROTNONE along with PRESENT? For example, pte_mknuma() clears _PAGE_PRESENT and sets _PAGE_NUMA, but on a PROT_NONE area, that would make it pte_special(). This is side-stepped by the fact that NUMA hinting faults skipped PROT_NONE VMAs and there are no grounds where a NUMA hinting fault on a PROT_NONE VMA would be interesting. Fixes: c46a7c817e66 ("x86: define _PAGE_NUMA by reusing software bits on the PMD and PTE levels") Reported-by: Sasha Levin Tested-by: Sasha Levin Signed-off-by: Hugh Dickins Signed-off-by: Mel Gorman Cc: "Kirill A. Shutemov" Cc: Peter Zijlstra Cc: Rik van Riel Cc: Johannes Weiner Cc: Cyrill Gorcunov Cc: Matthew Wilcox Cc: [3.16] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds CVE-2018-3620 CVE-2018-3646 (cherry picked from commit b38af4721f59d0b564468f623b3e52a638195015) Signed-off-by: Juerg Haefliger --- arch/x86/include/asm/pgtable.h | 9 +++++++-- mm/memory.c | 7 +++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index aa0b02bd1855..0eeaaf82a299 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -140,8 +140,13 @@ static inline int pte_exec(pte_t pte) static inline int pte_special(pte_t pte) { - return (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_SPECIAL)) == - (_PAGE_PRESENT|_PAGE_SPECIAL); + /* + * See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h. + * On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 == + * __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL. + */ + return (pte_flags(pte) & _PAGE_SPECIAL) && + (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE)); } /* Entries that were set to PROT_NONE are inverted */ diff --git a/mm/memory.c b/mm/memory.c index c8140b854dd6..337dfc000343 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -745,7 +745,7 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn = pte_pfn(pte); if (HAVE_PTE_SPECIAL) { - if (likely(!pte_special(pte) || pte_numa(pte))) + if (likely(!pte_special(pte))) goto check_pfn; if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) return NULL; @@ -771,15 +771,14 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, } } + if (is_zero_pfn(pfn)) + return NULL; check_pfn: if (unlikely(pfn > highest_memmap_pfn)) { print_bad_pte(vma, addr, pte, NULL); return NULL; } - if (is_zero_pfn(pfn)) - return NULL; - /* * NOTE! We still have PageReserved() pages in the page tables. * eg. VDSO mappings can cause them to exist.