Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp682663ybh; Tue, 10 Mar 2020 06:24:23 -0700 (PDT) X-Google-Smtp-Source: ADFU+vt505tUjQ79tC20URgyjURethgi1hW2MLCn55HP871LU0Q8lTg7iajxz7JFC8uP4uCnLYAl X-Received: by 2002:a05:6808:64e:: with SMTP id z14mr1057461oih.79.1583846663525; Tue, 10 Mar 2020 06:24:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583846663; cv=none; d=google.com; s=arc-20160816; b=d6hY+z7A4FQq63MrrNc+S6WH/9NaOUuhqikgf1yaenfFSuK1/Dgj8kxHaz9g8QciQH BJQe3Pzx/kwA0fvjboYCjyVRz1sHQRFR9vrKYatYYqS3/zVNtakCTSp6SuGUGaXnsO5/ 4RKD8cHs+bua2D8V2JZ9yDvxJ/hJprY4HUbylLWVl68wyPlFeEflEKOWWM9MaL92JtTO qOXdit2u7WAoGGWsTXwr9qGeVGSNOecd2szycVVb/ZBZbYXpC0QWBjCMaSuIjZzJXYgx CwEaZ0T+P0ekRsGNBRjVl+DNgTAFfTD+lNElo8zRI5VE6ISjNiFqxMBqET4B2ZZki+Er Z5xQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=yzAwtjWHYEEHQPYLN5mh+FcUcHOL2uNr3RGeFp2qk4M=; b=vc7sjHts/23kFfsVLepfA3FFNNnSkf56MKEoUqybT1Ccl6RHr3vAMFFZ1+lvs+QdzS S6euq8sxb8lMOezFgotBwAlb6VXALchz/u2GJmZTK+IbilM3h1R+mhFyDhXU9QWzTS1J BZqAvNr+K7MlVSPCdfsphr1tEUzAcFhSXQITp2SObkpYfW5+N9bwvAxs/Bsgdq/nLZ1X Tji+LKFmGGSS5OeOR6xYCoMk/5JUBZdU4GzEObdwGrLMGbptxb0QkRcPBgPsWwEAykLM eB+KpmI/VKdjMlT5Uv0gm0UyIR0NWxtx2drNg8ELMV1jnFk5c2Sko/3pMfcNhTNIXet7 0YNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rEs8qV5k; 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 s14si5017005otp.243.2020.03.10.06.24.10; Tue, 10 Mar 2020 06:24:23 -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; dkim=pass header.i=@kernel.org header.s=default header.b=rEs8qV5k; 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 S1730221AbgCJNBF (ORCPT + 99 others); Tue, 10 Mar 2020 09:01:05 -0400 Received: from mail.kernel.org ([198.145.29.99]:42010 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730206AbgCJNBA (ORCPT ); Tue, 10 Mar 2020 09:01:00 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 64D152468C; Tue, 10 Mar 2020 13:00:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583845259; bh=FMmLwfHpyJGEYDfcJbbf8o4v84coP75xaSgbbjb5eKY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rEs8qV5kzdycxVqtAs44ekpQBvW+giXN5yKN2XnJlTNf9Z3NEvvEMdNB97tpseluK i6c3BsZ1EAGUUPJuF97d/+sD2Ze/4AZyzRgtBBnCV5QTDGfUBvErlBrZ7T6+8ogqcf aJbdcnbmc6s5skHAUxuV+BmFoggdhN6FqwWhZwTU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jeff Moyer , Andrew Morton , "Kirill A. Shutemov" , Justin He , Dan Williams , Linus Torvalds Subject: [PATCH 5.5 081/189] mm: avoid data corruption on CoW fault into PFN-mapped VMA Date: Tue, 10 Mar 2020 13:38:38 +0100 Message-Id: <20200310123647.851968509@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200310123639.608886314@linuxfoundation.org> References: <20200310123639.608886314@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kirill A. Shutemov commit c3e5ea6ee574ae5e845a40ac8198de1fb63bb3ab upstream. 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: Greg Kroah-Hartman --- mm/memory.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) --- a/mm/memory.c +++ b/mm/memory.c @@ -2221,7 +2221,7 @@ static inline bool cow_user_page(struct 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; @@ -2246,11 +2246,11 @@ static inline bool cow_user_page(struct * 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 @@ -2274,18 +2274,37 @@ static inline bool cow_user_page(struct * 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);