mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk, Michal Hocko <mhocko@suse.cz>,
	Larry Woodman <lwoodman@redhat.com>, Mel Gorman <mgorman@suse.de>,
	Rik van Riel <riel@redhat.com>,
	David Gibson <david@gibson.dropbear.id.au>,
	Ken Chen <kenchen@google.com>,
	Cong Wang <xiyou.wangcong@gmail.com>,
	Hillf Danton <dhillf@gmail.com>
Subject: [ 72/95] mm: hugetlbfs: correctly populate shared pmd
Date: Sun, 09 Sep 2012 23:43:02 +0100	[thread overview]
Message-ID: <20120909224200.524032792@decadent.org.uk> (raw)
In-Reply-To: <20120909224150.641491654@decadent.org.uk>

3.2-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Michal Hocko <mhocko@suse.cz>

commit eb48c071464757414538c68a6033c8f8c15196f8 upstream.

Each page mapped in a process's address space must be correctly
accounted for in _mapcount.  Normally the rules for this are
straightforward but hugetlbfs page table sharing is different.  The page
table pages at the PMD level are reference counted while the mapcount
remains the same.

If this accounting is wrong, it causes bugs like this one reported by
Larry Woodman:

  kernel BUG at mm/filemap.c:135!
  invalid opcode: 0000 [#1] SMP
  CPU 22
  Modules linked in: bridge stp llc sunrpc binfmt_misc dcdbas microcode pcspkr acpi_pad acpi]
  Pid: 18001, comm: mpitest Tainted: G        W    3.3.0+ #4 Dell Inc. PowerEdge R620/07NDJ2
  RIP: 0010:[<ffffffff8112cfed>]  [<ffffffff8112cfed>] __delete_from_page_cache+0x15d/0x170
  Process mpitest (pid: 18001, threadinfo ffff880428972000, task ffff880428b5cc20)
  Call Trace:
    delete_from_page_cache+0x40/0x80
    truncate_hugepages+0x115/0x1f0
    hugetlbfs_evict_inode+0x18/0x30
    evict+0x9f/0x1b0
    iput_final+0xe3/0x1e0
    iput+0x3e/0x50
    d_kill+0xf8/0x110
    dput+0xe2/0x1b0
    __fput+0x162/0x240

During fork(), copy_hugetlb_page_range() detects if huge_pte_alloc()
shared page tables with the check dst_pte == src_pte.  The logic is if
the PMD page is the same, they must be shared.  This assumes that the
sharing is between the parent and child.  However, if the sharing is
with a different process entirely then this check fails as in this
diagram:

  parent
    |
    ------------>pmd
                 src_pte----------> data page
                                        ^
  other--------->pmd--------------------|
                  ^
  child-----------|
                 dst_pte

For this situation to occur, it must be possible for Parent and Other to
have faulted and failed to share page tables with each other.  This is
possible due to the following style of race.

  PROC A                                          PROC B
  copy_hugetlb_page_range                         copy_hugetlb_page_range
    src_pte == huge_pte_offset                      src_pte == huge_pte_offset
    !src_pte so no sharing                          !src_pte so no sharing

  (time passes)

  hugetlb_fault                                   hugetlb_fault
    huge_pte_alloc                                  huge_pte_alloc
      huge_pmd_share                                 huge_pmd_share
        LOCK(i_mmap_mutex)
        find nothing, no sharing
        UNLOCK(i_mmap_mutex)
                                                      LOCK(i_mmap_mutex)
                                                      find nothing, no sharing
                                                      UNLOCK(i_mmap_mutex)
      pmd_alloc                                       pmd_alloc
      LOCK(instantiation_mutex)
      fault
      UNLOCK(instantiation_mutex)
                                                  LOCK(instantiation_mutex)
                                                  fault
                                                  UNLOCK(instantiation_mutex)

These two processes are not poing to the same data page but are not
sharing page tables because the opportunity was missed.  When either
process later forks, the src_pte == dst pte is potentially insufficient.
As the check falls through, the wrong PTE information is copied in
(harmless but wrong) and the mapcount is bumped for a page mapped by a
shared page table leading to the BUG_ON.

This patch addresses the issue by moving pmd_alloc into huge_pmd_share
which guarantees that the shared pud is populated in the same critical
section as pmd.  This also means that huge_pte_offset test in
huge_pmd_share is serialized correctly now which in turn means that the
success of the sharing will be higher as the racing tasks see the pud
and pmd populated together.

Race identified and changelog written mostly by Mel Gorman.

{akpm@linux-foundation.org: attempt to make the huge_pmd_share() comment comprehensible, clean up coding style]
Reported-by: Larry Woodman <lwoodman@redhat.com>
Tested-by: Larry Woodman <lwoodman@redhat.com>
Reviewed-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Michal Hocko <mhocko@suse.cz>
Reviewed-by: Rik van Riel <riel@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Ken Chen <kenchen@google.com>
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Cc: Hillf Danton <dhillf@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/mm/hugetlbpage.c |   21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index f6679a7..b91e485 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)
 }
 
 /*
- * search for a shareable pmd page for hugetlb.
+ * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
+ * and returns the corresponding pte. While this is not necessary for the
+ * !shared pmd case because we can allocate the pmd later as well, it makes the
+ * code much cleaner. pmd allocation is essential for the shared case because
+ * pud has to be populated inside the same i_mmap_mutex section - otherwise
+ * racing tasks could either miss the sharing (see huge_pte_offset) or select a
+ * bad pmd for sharing.
  */
-static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
+static pte_t *
+huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 {
 	struct vm_area_struct *vma = find_vma(mm, addr);
 	struct address_space *mapping = vma->vm_file->f_mapping;
@@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 	struct vm_area_struct *svma;
 	unsigned long saddr;
 	pte_t *spte = NULL;
+	pte_t *pte;
 
 	if (!vma_shareable(vma, addr))
-		return;
+		return (pte_t *)pmd_alloc(mm, pud, addr);
 
 	mutex_lock(&mapping->i_mmap_mutex);
 	vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) {
@@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 		put_page(virt_to_page(spte));
 	spin_unlock(&mm->page_table_lock);
 out:
+	pte = (pte_t *)pmd_alloc(mm, pud, addr);
 	mutex_unlock(&mapping->i_mmap_mutex);
+	return pte;
 }
 
 /*
@@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,
 		} else {
 			BUG_ON(sz != PMD_SIZE);
 			if (pud_none(*pud))
-				huge_pmd_share(mm, addr, pud);
-			pte = (pte_t *) pmd_alloc(mm, pud, addr);
+				pte = huge_pmd_share(mm, addr, pud);
+			else
+				pte = (pte_t *)pmd_alloc(mm, pud, addr);
 		}
 	}
 	BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte));



  parent reply	other threads:[~2012-09-09 23:27 UTC|newest]

Thread overview: 112+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-09 22:41 [ 00/95] 3.2.29-stable review Ben Hutchings
2012-09-09 22:41 ` [ 01/95] HID: add ASUS AIO keyboard model AK1D Ben Hutchings
2012-09-09 22:41 ` [ 02/95] nfs: tear down caches in nfs_init_writepagecache when allocation fails Ben Hutchings
2012-09-09 22:41 ` [ 03/95] NFS: Use kcalloc() when allocating arrays Ben Hutchings
2012-09-09 22:41 ` [ 04/95] NFSv4.1 fix page number calculation bug for filelayout decode buffers Ben Hutchings
2012-09-09 22:41 ` [ 05/95] fix page number calculation bug for block layout decode buffer Ben Hutchings
2012-09-09 22:41 ` [ 06/95] pnfs: defer release of pages in layoutget Ben Hutchings
2012-09-09 22:41 ` [ 07/95] ext4: avoid kmemcheck complaint from reading uninitialized memory Ben Hutchings
2012-09-09 22:41 ` [ 08/95] fuse: verify all ioctl retry iov elements Ben Hutchings
2012-09-09 22:41 ` [ 09/95] Bluetooth: Fix legacy pairing with some devices Ben Hutchings
2012-09-09 22:42 ` [ 10/95] xhci: Increase reset timeout for Renesas 720201 host Ben Hutchings
2012-09-09 22:42 ` [ 11/95] xhci: Add Etron XHCI_TRUST_TX_LENGTH quirk Ben Hutchings
2012-09-09 22:42 ` [ 12/95] xhci: Switch PPT ports to EHCI on shutdown Ben Hutchings
2012-09-10 11:09   ` Denis Turischev
2012-09-10 15:18     ` Ben Hutchings
2012-09-09 22:42 ` [ 13/95] USB: ftdi_sio: Add VID/PID for Kondo Serial USB Ben Hutchings
2012-09-09 22:42 ` [ 14/95] USB: option: Add Vodafone/Huawei K5005 support Ben Hutchings
2012-09-09 22:42 ` [ 15/95] USB: add USB_VENDOR_AND_INTERFACE_INFO() macro Ben Hutchings
2012-09-09 22:42 ` [ 16/95] USB: support the new interfaces of Huawei Data Card devices in option driver Ben Hutchings
2012-09-09 22:42 ` [ 17/95] usb: serial: mos7840: Fixup mos7840_chars_in_buffer() Ben Hutchings
2012-09-09 22:42 ` [ 18/95] usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop Ben Hutchings
2012-09-09 22:42 ` [ 19/95] ARM: 7483/1: vfp: only advertise VFPv4 in hwcaps if CONFIG_VFPv3 is enabled Ben Hutchings
2012-09-09 22:42 ` [ 20/95] ARM: 7488/1: mm: use 5 bits for swapfile type encoding Ben Hutchings
2012-09-09 22:42 ` [ 21/95] ARM: 7489/1: errata: fix workaround for erratum #720789 on UP systems Ben Hutchings
2012-09-09 22:42 ` [ 22/95] drm/i915: ignore eDP bpc settings from vbt Ben Hutchings
2012-09-09 22:42 ` [ 23/95] ALSA: hda - fix Copyright debug message Ben Hutchings
2012-09-09 22:42 ` [ 24/95] sched: fix divide by zero at {thread_group,task}_times Ben Hutchings
2012-09-09 22:42 ` [ 25/95] mutex: Place lock in contended state after fastpath_lock failure Ben Hutchings
2012-09-09 23:34   ` Nicolas Pitre
2012-09-09 23:42     ` Ben Hutchings
2012-09-09 22:42 ` [ 26/95] ath9k: fix decrypt_error initialization in ath_rx_tasklet() Ben Hutchings
2012-09-09 22:42 ` [ 27/95] drm/nvd0/disp: mask off high 16 bit of negative cursor x-coordinate Ben Hutchings
2012-09-09 22:42 ` [ 28/95] drm/i915: reorder edp disabling to fix ivb MacBook Air Ben Hutchings
2012-09-09 22:42 ` [ 29/95] audit: dont free_chunk() after fsnotify_add_mark() Ben Hutchings
2012-09-09 22:42 ` [ 30/95] audit: fix refcounting in audit-tree Ben Hutchings
2012-09-09 22:42 ` [ 31/95] vfs: canonicalize create mode in build_open_flags() Ben Hutchings
2012-09-09 22:42 ` [ 32/95] PCI: EHCI: Fix crash during hibernation on ASUS computers Ben Hutchings
2012-09-09 22:42 ` [ 33/95] IB/srp: Fix a race condition Ben Hutchings
2012-09-09 22:42 ` [ 34/95] USB: option: add ZTE K5006-Z Ben Hutchings
2012-09-10 17:11   ` Thomas Schäfer
2012-09-11  7:43     ` Bjørn Mork
2012-09-12  2:29       ` Ben Hutchings
2012-09-13 15:22         ` Thomas Schäfer
2012-09-16 16:44           ` Ben Hutchings
2012-09-09 22:42 ` [ 35/95] dccp: check ccid before dereferencing Ben Hutchings
2012-09-10  6:17   ` Mathias Krause
2012-09-10  6:47     ` David Miller
2012-09-10  7:10       ` Mathias Krause
2012-09-09 22:42 ` [ 36/95] md: Dont truncate size at 4TB for RAID0 and Linear Ben Hutchings
2012-09-09 22:42 ` [ 37/95] NFS: Alias the nfs module to nfs4 Ben Hutchings
2012-09-09 22:42 ` [ 38/95] target: fix NULL pointer dereference bug alloc_page() fails to get memory Ben Hutchings
2012-09-09 22:42 ` [ 39/95] ext4: fix long mount times on very big file systems Ben Hutchings
2012-09-09 22:42 ` [ 40/95] PM / Runtime: Fix rpm_resume() return value for power.no_callbacks set Ben Hutchings
2012-09-09 22:42 ` [ 41/95] PM / Runtime: Clear power.deferred_resume on success in rpm_suspend() Ben Hutchings
2012-09-09 22:42 ` [ 42/95] ASoC: wm9712: Fix microphone source selection Ben Hutchings
2012-09-09 22:42 ` [ 43/95] USB: smsusb: remove __devinit* from the struct usb_device_id table Ben Hutchings
2012-09-09 22:42 ` [ 44/95] USB: spca506: " Ben Hutchings
2012-09-09 22:42 ` [ 45/95] USB: p54usb: " Ben Hutchings
2012-09-09 22:42 ` [ 46/95] USB: rtl8187: " Ben Hutchings
2012-09-09 22:42 ` [ 47/95] USB: vt6656: " Ben Hutchings
2012-09-09 22:42 ` [ 48/95] USB: winbond: " Ben Hutchings
2012-09-09 22:42 ` [ 49/95] USB: emi62: " Ben Hutchings
2012-09-09 22:42 ` [ 50/95] USB: CDC ACM: Fix NULL pointer dereference Ben Hutchings
2012-09-09 22:42 ` [ 51/95] alpha: Dont export SOCK_NONBLOCK to user space Ben Hutchings
2012-09-09 22:42 ` [ 52/95] Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts Ben Hutchings
2012-09-09 22:42 ` [ 53/95] ALSA: hda - dont create dysfunctional mixer controls for ca0132 Ben Hutchings
2012-09-09 22:42 ` [ 54/95] netconsole: remove a redundant netconsole_target_put() Ben Hutchings
2012-09-09 22:42 ` [ 55/95] drm/radeon/kms: upstream atombios.h updates Ben Hutchings
2012-09-09 22:42 ` [ 56/95] drm/radeon/kms: extend the Fujitsu D3003-S2 board connector quirk to cover later silicon stepping Ben Hutchings
2012-09-09 22:42 ` [ 57/95] drm/radeon: implement ACPI VFCT vbios fetch (v3) Ben Hutchings
2012-09-09 22:42 ` [ 58/95] ACPI: export symbol acpi_get_table_with_size Ben Hutchings
2012-09-09 22:42 ` [ 59/95] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size Ben Hutchings
2012-09-09 22:42 ` [ 60/95] drm/radeon: fix invalid memory access in radeon_atrm_get_bios() Ben Hutchings
2012-09-09 22:42 ` [ 61/95] drm/radeon: finish getting bios earlier Ben Hutchings
2012-09-09 22:42 ` [ 62/95] drm/radeon: fix use after free in ATRM bios reading code Ben Hutchings
2012-09-09 22:42 ` [ 63/95] drm/radeon: split ATRM support out from the ATPX handler (v3) Ben Hutchings
2012-09-09 22:42 ` [ 64/95] NFSv3: Ensure that do_proc_get_root() reports errors correctly Ben Hutchings
2012-09-09 22:42 ` [ 65/95] vfs: missed source of ->f_pos races Ben Hutchings
2012-09-09 22:42 ` [ 66/95] svcrpc: fix BUG() in svc_tcp_clear_pages Ben Hutchings
2012-09-09 22:42 ` [ 67/95] svcrpc: sends on closed socket should stop immediately Ben Hutchings
2012-09-09 22:42 ` [ 68/95] svcrpc: fix svc_xprt_enqueue/svc_recv busy-looping Ben Hutchings
2012-09-09 22:42 ` [ 69/95] Revert "drm/radeon: fix bo creation retry path" Ben Hutchings
2012-09-09 22:43 ` [ 70/95] fbcon: fix race condition between console lock and cursor timer (v1.1) Ben Hutchings
2012-09-09 22:43 ` [ 71/95] cciss: fix incorrect scsi status reporting Ben Hutchings
2012-09-09 22:43 ` Ben Hutchings [this message]
2012-09-09 22:43 ` [ 73/95] drivers/misc/sgi-xp/xpc_uv.c: SGI XPC fails to load when cpu 0 is out of IRQ resources Ben Hutchings
2012-09-09 22:43 ` [ 74/95] drivers/rtc/rtc-rs5c348.c: fix hour decoding in 12-hour mode Ben Hutchings
2012-09-09 22:43 ` [ 75/95] rapidio/tsi721: fix inbound doorbell interrupt handling Ben Hutchings
2012-09-09 22:43 ` [ 76/95] rapidio/tsi721: fix unused variable compiler warning Ben Hutchings
2012-09-09 22:43 ` [ 77/95] fs/buffer.c: remove BUG() in possible but rare condition Ben Hutchings
2012-09-09 22:43 ` [ 78/95] block: replace __getblk_slow misfix by grow_dev_page fix Ben Hutchings
2012-09-09 22:43 ` [ 79/95] Bluetooth: Fix using uninitialized option in RFCMode Ben Hutchings
2012-09-09 22:43 ` [ 80/95] drivers/char/random.c: fix boot id uniqueness race Ben Hutchings
2012-09-09 22:43 ` [ 81/95] MAINTAINERS: Theodore Tso is taking over the random driver Ben Hutchings
2012-09-09 22:43 ` [ 82/95] random: Add comment to random_initialize() Ben Hutchings
2012-09-09 22:43 ` [ 83/95] dmi: Feed DMI table to /dev/random driver Ben Hutchings
2012-09-09 22:43 ` [ 84/95] virtio_blk: fix config handler race Ben Hutchings
2012-09-10  2:26   ` Rusty Russell
2012-09-10  2:45     ` Asias He
2012-09-10 15:25     ` Ben Hutchings
2012-09-09 22:43 ` [ 85/95] virtio_blk: Drop unused request tracking list Ben Hutchings
2012-09-09 22:43 ` [ 86/95] virtio-blk: Fix hot-unplug race in remove method Ben Hutchings
2012-09-09 22:43 ` [ 87/95] virtio-blk: Call del_gendisk() before disable guest kick Ben Hutchings
2012-09-09 22:43 ` [ 88/95] virtio-blk: Reset device after blk_cleanup_queue() Ben Hutchings
2012-09-09 22:43 ` [ 89/95] HID: add support for Cypress barcode scanner 04B4:ED81 Ben Hutchings
2012-09-09 22:43 ` [ 90/95] pmac_zilog,kdb: Fix console poll hook to return instead of loop Ben Hutchings
2012-09-09 22:43 ` [ 91/95] Staging: speakup: fix an improperly-declared variable Ben Hutchings
2012-09-09 22:43 ` [ 92/95] NFS: Fix Oopses in nfs_lookup_revalidate and nfs4_lookup_revalidate Ben Hutchings
2012-09-12  6:45   ` Suresh Jayaraman
2012-09-09 22:43 ` [ 93/95] asus-nb-wmi: add some video toggle keys Ben Hutchings
2012-09-09 22:43 ` [ 94/95] Squashfs: fix mount time sanity check for corrupted superblock Ben Hutchings
2012-09-09 22:43 ` [ 95/95] mm: avoid swapping out with swappiness==0 Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120909224200.524032792@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=david@gibson.dropbear.id.au \
    --cc=dhillf@gmail.com \
    --cc=kenchen@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lwoodman@redhat.com \
    --cc=mgorman@suse.de \
    --cc=mhocko@suse.cz \
    --cc=riel@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®