From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linuxfoundation.org ([140.211.169.12]:48713 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933887AbcIEN57 (ORCPT ); Mon, 5 Sep 2016 09:57:59 -0400 Subject: Patch "soft_dirty: fix soft_dirty during THP split" has been added to the 4.7-stable tree To: aarcange@redhat.com, akpm@linux-foundation.org, gregkh@linuxfoundation.org, kirill@shutemov.name, torvalds@linux-foundation.org, xemul@virtuozzo.com Cc: , From: Date: Mon, 05 Sep 2016 15:55:34 +0200 Message-ID: <147308373437221@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ANSI_X3.4-1968 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org List-ID: This is a note to let you know that I've just added the patch titled soft_dirty: fix soft_dirty during THP split to the 4.7-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: soft_dirty-fix-soft_dirty-during-thp-split.patch and it can be found in the queue-4.7 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let know about it. >>From 804dd150468cfd920d92d4b3cf00536fedef3902 Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 25 Aug 2016 15:16:57 -0700 Subject: soft_dirty: fix soft_dirty during THP split From: Andrea Arcangeli commit 804dd150468cfd920d92d4b3cf00536fedef3902 upstream. While adding proper userfaultfd_wp support with bits in pagetable and swap entry to avoid false positives WP userfaults through swap/fork/ KSM/etc, I've been adding a framework that mostly mirrors soft dirty. So I noticed in one place I had to add uffd_wp support to the pagetables that wasn't covered by soft_dirty and I think it should have. Example: in the THP migration code migrate_misplaced_transhuge_page() pmd_mkdirty is called unconditionally after mk_huge_pmd. entry = mk_huge_pmd(new_page, vma->vm_page_prot); entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); That sets soft dirty too (it's a false positive for soft dirty, the soft dirty bit could be more finegrained and transfer the bit like uffd_wp will do.. pmd/pte_uffd_wp() enforces the invariant that when it's set pmd/pte_write is not set). However in the THP split there's no unconditional pmd_mkdirty after mk_huge_pmd and pte_swp_mksoft_dirty isn't called after the migration entry is created. The code sets the dirty bit in the struct page instead of setting it in the pagetable (which is fully equivalent as far as the real dirty bit is concerned, as the whole point of pagetable bits is to be eventually flushed out of to the page, but that is not equivalent for the soft-dirty bit that gets lost in translation). This was found by code review only and totally untested as I'm working to actually replace soft dirty and I don't have time to test potential soft dirty bugfixes as well :). Transfer the soft_dirty from pmd to pte during THP splits. This fix avoids losing the soft_dirty bit and avoids userland memory corruption in the checkpoint. Fixes: eef1b3ba053aa6 ("thp: implement split_huge_pmd()") Link: http://lkml.kernel.org/r/1471610515-30229-2-git-send-email-aarcange@redhat.com Signed-off-by: Andrea Arcangeli Acked-by: Pavel Emelyanov Cc: "Kirill A. Shutemov" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/huge_memory.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2872,7 +2872,7 @@ static void __split_huge_pmd_locked(stru struct page *page; pgtable_t pgtable; pmd_t _pmd; - bool young, write, dirty; + bool young, write, dirty, soft_dirty; unsigned long addr; int i; @@ -2898,6 +2898,7 @@ static void __split_huge_pmd_locked(stru write = pmd_write(*pmd); young = pmd_young(*pmd); dirty = pmd_dirty(*pmd); + soft_dirty = pmd_soft_dirty(*pmd); pmdp_huge_split_prepare(vma, haddr, pmd); pgtable = pgtable_trans_huge_withdraw(mm, pmd); @@ -2914,6 +2915,8 @@ static void __split_huge_pmd_locked(stru swp_entry_t swp_entry; swp_entry = make_migration_entry(page + i, write); entry = swp_entry_to_pte(swp_entry); + if (soft_dirty) + entry = pte_swp_mksoft_dirty(entry); } else { entry = mk_pte(page + i, vma->vm_page_prot); entry = maybe_mkwrite(entry, vma); @@ -2921,6 +2924,8 @@ static void __split_huge_pmd_locked(stru entry = pte_wrprotect(entry); if (!young) entry = pte_mkold(entry); + if (soft_dirty) + entry = pte_mksoft_dirty(entry); } if (dirty) SetPageDirty(page + i); Patches currently in stable-queue which might be from aarcange@redhat.com are queue-4.7/soft_dirty-fix-soft_dirty-during-thp-split.patch