Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp878642pxk; Thu, 17 Sep 2020 20:07:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzTeKo4Zp6SrRmDgj9xahhq+5BLmoOXWYy4xeoALCd6f5n7MAmMnjns8TTdhkQbVEkJ9FwL X-Received: by 2002:a17:906:24d2:: with SMTP id f18mr33329259ejb.510.1600398469301; Thu, 17 Sep 2020 20:07:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600398469; cv=none; d=google.com; s=arc-20160816; b=kV6HNP4a03SLzhXCUrwK3+ieL3nv6xNI/2513pyi2rKf8fNgVcqiVupranKMP+m4mh LO+eZkNE02r8X9RfewNhfe0+4B2Q2ncRfPyUYqDyAiQLibCUn5y/1JfjrqTUd+3euWju QqLEMtrngyAT9J+IiNQmhP94WWHtrnL9Xb/l/xCtKDAan7Boc1c5DP1x1sGjjL0uWLKO 8Vo7nr35xYtLTsLHr+7ToklQqu3ycMqmTYjgJulIiHM6dXu+yfLVNzm97iZ6kO1sEFCM sPDZwdKj6J4MCwdK6w801Z/8uoOAvGT5w+No3lRd6J3ZrfHhFUbLTrFnsZyMpvNRctDS 1vOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=F5xMdmMYZmlycrzW2j9VxB7NV0oKbR2M5pbigkGL/XQ=; b=sifm2Q2odgL2cO6dCDcvFcHFGBsKdLeYndBTbIcR9au4pi+K0JsrdwBbwDuFB9apJ8 e0Lbpvse3MXE/PgJ7ICjUWFwHKPk1GE1B0zs2DCFJZwt/6iuy6BK43u0Bl9KeNO8dCvK ZqFg4zErwBgNFZejy6pRaKdGnolLzNtXbZ667iL60Qv4P5EdOzerwUWx4Dga69b3eQcb FCNgBtuLy0FYK+ea6ddgy8ta+vHMQ/Yo1AawsrEXTczbsKOY1hS8+yfHqyPZOzndgywQ XnQ01p/TLdrMh7qDK6z2RdRA2bZ8Vq+9vGxeiJJCbE21HgkEoak2rR2v3AeloRhsHBOC cTgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=wCgY5jIr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ga5si1518992ejb.547.2020.09.17.20.07.26; Thu, 17 Sep 2020 20:07:49 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=wCgY5jIr; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730618AbgIRDFY (ORCPT + 99 others); Thu, 17 Sep 2020 23:05:24 -0400 Received: from mail.kernel.org ([198.145.29.99]:51690 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727300AbgIRCEY (ORCPT ); Thu, 17 Sep 2020 22:04:24 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D0650235F8; Fri, 18 Sep 2020 02:04:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600394663; bh=Xjo3TJpoMf2lYr0X6xlZPYO6N54YXYKVfBwFjhmx8Aw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wCgY5jIrs44FoQX5DFobdhHQuxblcRkg93PRAME80IZb1nJutJ7iHAZQ7L44gzOKc DbIGPXoHtTShhLnrLpnZcZGN9zcXyjgjYoCGB0Gj+EU5tG1/vnalKNrHro/oQN8JbS yKI6CAeF2kLtMn4g+6IU1AzF+ZAz1VJD3yrTBGXM= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: "Kirill A. Shutemov" , Jeff Moyer , Andrew Morton , "Kirill A . Shutemov" , Justin He , Dan Williams , Linus Torvalds , Sasha Levin , linux-mm@kvack.org Subject: [PATCH AUTOSEL 5.4 157/330] mm: avoid data corruption on CoW fault into PFN-mapped VMA Date: Thu, 17 Sep 2020 21:58:17 -0400 Message-Id: <20200918020110.2063155-157-sashal@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200918020110.2063155-1-sashal@kernel.org> References: <20200918020110.2063155-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Kirill A. Shutemov" [ Upstream commit c3e5ea6ee574ae5e845a40ac8198de1fb63bb3ab ] Jeff Moyer has reported that one of xfstests triggers a warning when run on DAX-enabled filesystem: WARNING: CPU: 76 PID: 51024 at mm/memory.c:2317 wp_page_copy+0xc40/0xd50 ... wp_page_copy+0x98c/0xd50 (unreliable) do_wp_page+0xd8/0xad0 __handle_mm_fault+0x748/0x1b90 handle_mm_fault+0x120/0x1f0 __do_page_fault+0x240/0xd70 do_page_fault+0x38/0xd0 handle_page_fault+0x10/0x30 The warning happens on failed __copy_from_user_inatomic() which tries to copy data into a CoW page. This happens because of race between MADV_DONTNEED and CoW page fault: CPU0 CPU1 handle_mm_fault() do_wp_page() wp_page_copy() do_wp_page() madvise(MADV_DONTNEED) zap_page_range() zap_pte_range() ptep_get_and_clear_full() __copy_from_user_inatomic() sees empty PTE and fails WARN_ON_ONCE(1) clear_page() The solution is to re-try __copy_from_user_inatomic() under PTL after checking that PTE is matches the orig_pte. The second copy attempt can still fail, like due to non-readable PTE, but there's nothing reasonable we can do about, except clearing the CoW page. Reported-by: Jeff Moyer Signed-off-by: Andrew Morton Signed-off-by: Kirill A. Shutemov Tested-by: Jeff Moyer Cc: Cc: Justin He Cc: Dan Williams Link: http://lkml.kernel.org/r/20200218154151.13349-1-kirill.shutemov@linux.intel.com Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- mm/memory.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 9ea917e28ef4e..2157bb28117ac 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2163,7 +2163,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, bool ret; void *kaddr; void __user *uaddr; - bool force_mkyoung; + bool locked = false; struct vm_area_struct *vma = vmf->vma; struct mm_struct *mm = vma->vm_mm; unsigned long addr = vmf->address; @@ -2188,11 +2188,11 @@ static inline bool cow_user_page(struct page *dst, struct page *src, * On architectures with software "accessed" bits, we would * take a double page fault, so mark it accessed here. */ - force_mkyoung = arch_faults_on_old_pte() && !pte_young(vmf->orig_pte); - if (force_mkyoung) { + if (arch_faults_on_old_pte() && !pte_young(vmf->orig_pte)) { pte_t entry; vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl); + locked = true; if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) { /* * Other thread has already handled the fault @@ -2216,18 +2216,37 @@ static inline bool cow_user_page(struct page *dst, struct page *src, * zeroes. */ if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) { + if (locked) + goto warn; + + /* Re-validate under PTL if the page is still mapped */ + vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl); + locked = true; + if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) { + /* The PTE changed under us. Retry page fault. */ + ret = false; + goto pte_unlock; + } + /* - * Give a warn in case there can be some obscure - * use-case + * The same page can be mapped back since last copy attampt. + * Try to copy again under PTL. */ - WARN_ON_ONCE(1); - clear_page(kaddr); + if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) { + /* + * Give a warn in case there can be some obscure + * use-case + */ +warn: + WARN_ON_ONCE(1); + clear_page(kaddr); + } } ret = true; pte_unlock: - if (force_mkyoung) + if (locked) pte_unmap_unlock(vmf->pte, vmf->ptl); kunmap_atomic(kaddr); flush_dcache_page(dst); -- 2.25.1