From patchwork Tue Feb 5 00:51:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khalid Elmously X-Patchwork-Id: 1036386 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 43tmH76H6Fz9sNG; Tue, 5 Feb 2019 11:51:31 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1gqoxS-0002kv-Hm; Tue, 05 Feb 2019 00:51:26 +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 1gqoxQ-0002kb-SQ for kernel-team@lists.ubuntu.com; Tue, 05 Feb 2019 00:51:24 +0000 Received: from mail-it1-f198.google.com ([209.85.166.198]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1gqoxQ-0000G8-8H for kernel-team@lists.ubuntu.com; Tue, 05 Feb 2019 00:51:24 +0000 Received: by mail-it1-f198.google.com with SMTP id k133so2904925ite.4 for ; Mon, 04 Feb 2019 16:51:24 -0800 (PST) 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=62yUnjE7SCBtqhUutuQp+wN9upYQKO9k1x57bdQGIQI=; b=in/qfyRNqIwScrHts8Xnze7B7i2MhTgJJIKPO+vH1ngn660YTdIaAtusjZDdj5wMzk CT6zBGOD49Gn0bzlnrDO7tBwoEpvnTRxsGZABJKwtihqUkAIcRhoISSDivXRL7pwHP1F yuk6TLEkXO/g7TkVBdaewqpXlLRVkUpBe+bQGcqa/Eg1T6RK+q/iLU10G9nS9/W2lDpg aRzKaHWunrv1VtbQq6cbjsZ1NLDAHgwb38m+sQkcW/IhbUcAiTpyDQhdDdecwYMcFLbW l2fMvDVQ26PFH40DsWH9jPc2/x0A5SINQ1udnDrD/eb+XZB3ucNQljzholdWaldwE7lp ZEDA== X-Gm-Message-State: AHQUAuax+Er3JDO7OcpHE3hUhwfaXemfVNR1ZJfkxKULyX071trixTb9 7Y0ywl0AcWr1hwuhBCrvhcPycn8BGd6/zQM/mBXjej0F7iobrin8P35HmsYJ/R1dWZuIDSGr+fV +9ymGpQZR89P2rpx8UTFt08udwkW9tv1DUV5Dl/yaxg== X-Received: by 2002:a05:660c:4c5:: with SMTP id v5mr1301103itk.104.1549327883160; Mon, 04 Feb 2019 16:51:23 -0800 (PST) X-Google-Smtp-Source: AHgI3IZUkeoExb6+0h+lw9/R36+hyhgAUFjG5LT8LZ8o+/6knAiZP7X1SRCbUbeGhooURBNdJkHEoA== X-Received: by 2002:a05:660c:4c5:: with SMTP id v5mr1301094itk.104.1549327882934; Mon, 04 Feb 2019 16:51:22 -0800 (PST) Received: from kbuntu.fuzzbuzz.org (dhcp-24-53-242-107.cable.user.start.ca. [24.53.242.107]) by smtp.gmail.com with ESMTPSA id k4sm553660ioj.33.2019.02.04.16.51.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 16:51:22 -0800 (PST) From: Khalid Elmously To: kernel-team@lists.ubuntu.com Subject: [SRU][Bionic][PATCH 1/1] x86/speculation/l1tf: Exempt zeroed PTEs from inversion Date: Mon, 4 Feb 2019 19:51:15 -0500 Message-Id: <20190205005115.2215-2-khalid.elmously@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190205005115.2215-1-khalid.elmously@canonical.com> References: <20190205005115.2215-1-khalid.elmously@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: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Sean Christopherson BugLink: http://bugs.launchpad.net/bugs/1799237 It turns out that we should *not* invert all not-present mappings, because the all zeroes case is obviously special. clear_page() does not undergo the XOR logic to invert the address bits, i.e. PTE, PMD and PUD entries that have not been individually written will have val=0 and so will trigger __pte_needs_invert(). As a result, {pte,pmd,pud}_pfn() will return the wrong PFN value, i.e. all ones (adjusted by the max PFN mask) instead of zero. A zeroed entry is ok because the page at physical address 0 is reserved early in boot specifically to mitigate L1TF, so explicitly exempt them from the inversion when reading the PFN. Manifested as an unexpected mprotect(..., PROT_NONE) failure when called on a VMA that has VM_PFNMAP and was mmap'd to as something other than PROT_NONE but never used. mprotect() sends the PROT_NONE request down prot_none_walk(), which walks the PTEs to check the PFNs. prot_none_pte_entry() gets the bogus PFN from pte_pfn() and returns -EACCES because it thinks mprotect() is trying to adjust a high MMIO address. [ This is a very modified version of Sean's original patch, but all credit goes to Sean for doing this and also pointing out that sometimes the __pte_needs_invert() function only gets the protection bits, not the full eventual pte. But zero remains special even in just protection bits, so that's ok. - Linus ] Fixes: f22cc87f6c1f ("x86/speculation/l1tf: Invert all not present mappings") Signed-off-by: Sean Christopherson Acked-by: Andi Kleen Cc: Thomas Gleixner Cc: Josh Poimboeuf Cc: Michal Hocko Cc: Vlastimil Babka Cc: Dave Hansen Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds (cherry picked from commit f19f5c49bbc3ffcc9126cc245fc1b24cc29f4a37) Signed-off-by: Khalid Elmously Acked-by: Stefan Bader Acked-by: Kleber Sacilotto de Souza --- arch/x86/include/asm/pgtable-invert.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/pgtable-invert.h b/arch/x86/include/asm/pgtable-invert.h index 44b1203ece12..a0c1525f1b6f 100644 --- a/arch/x86/include/asm/pgtable-invert.h +++ b/arch/x86/include/asm/pgtable-invert.h @@ -4,9 +4,18 @@ #ifndef __ASSEMBLY__ +/* + * A clear pte value is special, and doesn't get inverted. + * + * Note that even users that only pass a pgprot_t (rather + * than a full pte) won't trigger the special zero case, + * because even PAGE_NONE has _PAGE_PROTNONE | _PAGE_ACCESSED + * set. So the all zero case really is limited to just the + * cleared page table entry case. + */ static inline bool __pte_needs_invert(u64 val) { - return !(val & _PAGE_PRESENT); + return val && !(val & _PAGE_PRESENT); } /* Get a mask to xor with the page table entry to get the correct pfn. */