Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp2985722imm; Sun, 1 Jul 2018 09:44:02 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfuJnL8CeXIWbXdn61QbKiiKmb2L4b7H/nUfWpVxd+hOxIoZet3+DOt4HdsBhHyqwda2Ehv X-Received: by 2002:a65:498c:: with SMTP id r12-v6mr10507088pgs.112.1530463442492; Sun, 01 Jul 2018 09:44:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530463442; cv=none; d=google.com; s=arc-20160816; b=LijtCklRo30A2SMPHiRpal0TJjC9TdlkCCpuivGvsEtP82Vda5ZGfWqhBhHXB1cURO 1FWXzjmGyY/lH8CYKN7Li1QqN/AbLs7ccSJfHpm1+uI1visklaVVwtWXvFY1L1dRL8Gs JnulLebD6UEEtM1kYOyHjDOtWCZ2PJSUht5GDauHi5ejlplFQeen3o5eSzdIqPkNiX91 vxbz5eSKnyL598qo8au3j5DhRCFbTwduuGUi0XwdFv8oPomBRMdTmWTvF7rzn6N+0bKZ /CMXuq5YlZxpIdI9THGkcZbtAzhSgAE/Fn/p7NpWz+2DYNdP/mqT0HNoJ4HHb91BnHxC zEtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=N63x/1Be2Ltv14ME2JiHn/crBn1baHwIX+K5dlg8A3c=; b=e9F7rHLQkcylIlM+9yl3IJb0c3u+V/wG1rk/B1qgi5camQbjB7ZpkJ2DquqnEjexG7 76OSm2+9jkEBDLpRq3BIDZXJB+4khGDGAWvEihOcA4CnXSBPeI+R2y3r9MuYkXyiZG45 cpdpT8TQ+Chw9dw0U2lQryeXrSYMAfAmN1cYdxW1Ja/uJ6xXkaaJLH6Qo7HAnazzggjU xrO2VtTIJZ+ztWqp3/tisazfeh9rXGnFP1YKlGR28ejK2ZnVVJDMpKEx8IlM33i3e/cQ c87ZtNZcexTPI/IglfHs4LZu7iJmeZey8x2QkYnV6HBIjwYOVi2xQOAx0nZz+4OMHuKL ZLjg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s2-v6si14173854plq.372.2018.07.01.09.43.48; Sun, 01 Jul 2018 09:44:02 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1032220AbeGAQmj (ORCPT + 99 others); Sun, 1 Jul 2018 12:42:39 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:37652 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031805AbeGAQmf (ORCPT ); Sun, 1 Jul 2018 12:42:35 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 70B52AA6; Sun, 1 Jul 2018 16:42:34 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jan Kara , Dan Williams Subject: [PATCH 4.17 131/220] mm: fix __gup_device_huge vs unmap Date: Sun, 1 Jul 2018 18:22:35 +0200 Message-Id: <20180701160913.799552728@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180701160908.272447118@linuxfoundation.org> References: <20180701160908.272447118@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.17-stable review patch. If anyone has any objections, please let me know. ------------------ From: Dan Williams commit a9b6de77b1a3ff729f7bfc54b2e17711776a416c upstream. get_user_pages_fast() for device pages is missing the typical validation that all page references have been taken while the mapping was valid. Without this validation truncate operations can not reliably coordinate against new page reference events like O_DIRECT. Cc: Fixes: 3565fce3a659 ("mm, x86: get_user_pages() for dax mappings") Reported-by: Jan Kara Reviewed-by: Jan Kara Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- mm/gup.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) --- a/mm/gup.c +++ b/mm/gup.c @@ -1459,32 +1459,48 @@ static int __gup_device_huge(unsigned lo return 1; } -static int __gup_device_huge_pmd(pmd_t pmd, unsigned long addr, +static int __gup_device_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { unsigned long fault_pfn; + int nr_start = *nr; - fault_pfn = pmd_pfn(pmd) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); - return __gup_device_huge(fault_pfn, addr, end, pages, nr); + fault_pfn = pmd_pfn(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); + if (!__gup_device_huge(fault_pfn, addr, end, pages, nr)) + return 0; + + if (unlikely(pmd_val(orig) != pmd_val(*pmdp))) { + undo_dev_pagemap(nr, nr_start, pages); + return 0; + } + return 1; } -static int __gup_device_huge_pud(pud_t pud, unsigned long addr, +static int __gup_device_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { unsigned long fault_pfn; + int nr_start = *nr; - fault_pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); - return __gup_device_huge(fault_pfn, addr, end, pages, nr); + fault_pfn = pud_pfn(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); + if (!__gup_device_huge(fault_pfn, addr, end, pages, nr)) + return 0; + + if (unlikely(pud_val(orig) != pud_val(*pudp))) { + undo_dev_pagemap(nr, nr_start, pages); + return 0; + } + return 1; } #else -static int __gup_device_huge_pmd(pmd_t pmd, unsigned long addr, +static int __gup_device_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { BUILD_BUG(); return 0; } -static int __gup_device_huge_pud(pud_t pud, unsigned long addr, +static int __gup_device_huge_pud(pud_t pud, pud_t *pudp, unsigned long addr, unsigned long end, struct page **pages, int *nr) { BUILD_BUG(); @@ -1502,7 +1518,7 @@ static int gup_huge_pmd(pmd_t orig, pmd_ return 0; if (pmd_devmap(orig)) - return __gup_device_huge_pmd(orig, addr, end, pages, nr); + return __gup_device_huge_pmd(orig, pmdp, addr, end, pages, nr); refs = 0; page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); @@ -1540,7 +1556,7 @@ static int gup_huge_pud(pud_t orig, pud_ return 0; if (pud_devmap(orig)) - return __gup_device_huge_pud(orig, addr, end, pages, nr); + return __gup_device_huge_pud(orig, pudp, addr, end, pages, nr); refs = 0; page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);