Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp3705573pxk; Tue, 29 Sep 2020 04:18:42 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzG5W74z5fnuNHGcOyfJINuoI8Ti/vmTdyrnTHRPfxEQRF/SvoipvfjmSklkvcgXzFB+57A X-Received: by 2002:a17:906:9701:: with SMTP id k1mr3496400ejx.0.1601378322635; Tue, 29 Sep 2020 04:18:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1601378322; cv=none; d=google.com; s=arc-20160816; b=Nf+A//R6kQVB9pRPr2G1EBv3rqwxJRgunEoV/F8NNDGo6QTISrnzo4kZ7AmNwMozi/ FQQQ7yRdy9NdKeNlYFDcVxSAo0aCTi7gP+z8+SxhWDQnoEhg1/3SLLlwJYVrGdqswxtt oP2iqj3bPyPyOR+GJuo5tXJo4wAy81mFsv9gRaSiULJvS5o5IE+iT6efzFzSjz3+AZGn 2JBQd9m0VH6RImf+Pi5Ej4VUnFs7hbHXHJhppSNsRqBwQLshH0dvjnpXpFwh5BXuvLiE qqTTR8qKlgQfWdxA/oU2mGEYVDxPnjmsg6BKYeIDQSqLG50zIeSUpUaOIGlFp+/jbk+K vC/Q== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=9nGCjqJm8Hm8Rk8E0KtwyVr/UCU2QfTsP4Fn0F8rP4o=; b=Tz2TGd2DFNB6PsZur/JZ0ddWxgOEzOHfHy00goE8fETowlz+HfSvOJVKqZPB+zXAIJ BouWXNCiekO8qr7kaKaYIkv6p+9DfGjIFkKgPI4mIgkKUC4bNgI/0U2sG1zCwP0RuqYG 4b6Z31isCsYQootUYpuOfHynlpiHVAeszu7i3yDzfhYlpiZ4/pcPNJr+55CBDgvuvsve 2hPu4HXz8eiLIMHRMkeJkgL8Oe4AZTaasbGHKxBALQJ8QfTXhmXckdYflR0w4GYbT5E/ evvgUIBBKLusDJEbkEvwHffJ5K9C7vBYdPlPx1mbuqRIFORGpZeXoWKV9wfWH1nDil3g GAiQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=r0opcSiN; 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=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 10si2514653ejv.6.2020.09.29.04.18.20; Tue, 29 Sep 2020 04:18:42 -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=r0opcSiN; 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=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729547AbgI2LP4 (ORCPT + 99 others); Tue, 29 Sep 2020 07:15:56 -0400 Received: from mail.kernel.org ([198.145.29.99]:60252 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728693AbgI2LPn (ORCPT ); Tue, 29 Sep 2020 07:15:43 -0400 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (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 473B920848; Tue, 29 Sep 2020 11:15:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1601378142; bh=A5azr1jqf+aG9NBHIhCPuIzi6s5vhkempY8UyLBvW0A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r0opcSiNQoOe45jxIyef9AjN3MQQNOgVuHVTYEo9kGDpgqizmHULU9Ee8V0X/iLUv yol8R5btO9c/yzYz0GXnVVtX0HCtLm91qgWyjjCuJI0jaNMF1Yj+NfsAz0wKd45ySd 1hUm43zT1LUfvx87efs9KZv4sVtmQkT2Oh/4vjco= 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 , Sasha Levin Subject: [PATCH 4.14 076/166] mm: avoid data corruption on CoW fault into PFN-mapped VMA Date: Tue, 29 Sep 2020 12:59:48 +0200 Message-Id: <20200929105939.013468048@linuxfoundation.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200929105935.184737111@linuxfoundation.org> References: <20200929105935.184737111@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 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 07188929a30a1..caefa5526b20c 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2342,7 +2342,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; @@ -2367,11 +2367,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 @@ -2395,18 +2395,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