Skip to contentSkip to conversation

Patch "proc/pagemap: walk page tables under pte lock" has been added to the 3.14-stable tree

PATCH [email protected] 1 participant 1 message Apr 26, 2015

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

proc/pagemap: walk page tables under pte lock

to the 3.14-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:
proc-pagemap-walk-page-tables-under-pte-lock.patch
and it can be found in the queue-3.14 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 05fbf357d94152171bc50f8a369390f1f16efd89 Mon Sep 17 00:00:00 2001

From: Konstantin Khlebnikov <[email protected]>
Date: Wed, 11 Feb 2015 15:27:31 -0800
Subject: proc/pagemap: walk page tables under pte lock

From: Konstantin Khlebnikov <[email protected]>

commit 05fbf357d94152171bc50f8a369390f1f16efd89 upstream.

Lockless access to pte in pagemap_pte_range() might race with page migration and trigger BUG_ON(!PageLocked()) in migration_entry_to_page():

CPU A (pagemap) CPU B (migration)

                                          lock_page()
                                          try_to_unmap(page, TTU_MIGRATION...)
                                               make_migration_entry()
                                               set_pte_at()

<read *pte>
pte_to_pagemap_entry()
remove_migration_ptes() unlock_page()
if(is_migration_entry())
migration_entry_to_page()
BUG_ON(!PageLocked(page))

Also lockless read might be non-atomic if pte is larger than wordsize. Other pte walkers (smaps, numa_maps, clear_refs) already lock ptes.

---
 fs/proc/task_mmu.c |   14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
fs/proc/task_mmu.c +9 -5
@@ -993,7 +993,7 @@ static int pagemap_pte_range(pmd_t *pmd,
 	struct vm_area_struct *vma;
 	struct pagemapread *pm = walk->private;
 	spinlock_t *ptl;
-	pte_t *pte;
+	pte_t *pte, *orig_pte;
 	int err = 0;
 
 	/* find the first VMA at or above 'addr' */
@@ -1054,15 +1054,19 @@ static int pagemap_pte_range(pmd_t *pmd,
 		BUG_ON(is_vm_hugetlb_page(vma));
 
 		/* Addresses in the VMA. */
-		for (; addr < min(end, vma->vm_end); addr += PAGE_SIZE) {
+		orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+		for (; addr < min(end, vma->vm_end); pte++, addr += PAGE_SIZE) {
 			pagemap_entry_t pme;
-			pte = pte_offset_map(pmd, addr);
+
 			pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
-			pte_unmap(pte);
 			err = add_to_pagemap(addr, &pme, pm);
 			if (err)
-				return err;
+				break;
 		}
+		pte_unmap_unlock(orig_pte, ptl);
+
+		if (err)
+			return err;
 
 		if (addr == end)
 			break;

Patches currently in stable-queue which might be from [email protected] are

queue-3.14/proc-pagemap-walk-page-tables-under-pte-lock.patch