lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1448309082-20851-1-git-send-email-toshi.kani@hpe.com>
Date:	Mon, 23 Nov 2015 13:04:42 -0700
From:	Toshi Kani <toshi.kani@....com>
To:	akpm@...ux-foundation.org
Cc:	kirill.shutemov@...ux.intel.com, willy@...ux.intel.com,
	ross.zwisler@...ux.intel.com, dan.j.williams@...el.com,
	mauricio.porto@....com, linux-mm@...ck.org,
	linux-fsdevel@...r.kernel.org, linux-nvdimm@...ts.01.org,
	linux-kernel@...r.kernel.org, Toshi Kani <toshi.kani@....com>
Subject: [PATCH] mm: Fix mmap MAP_POPULATE for DAX pmd mapping

The following oops was observed when mmap() with MAP_POPULATE
pre-faulted pmd mappings of a DAX file.  follow_trans_huge_pmd()
expects that a target address has a struct page.

  BUG: unable to handle kernel paging request at ffffea0012220000
  follow_trans_huge_pmd+0xba/0x390
  follow_page_mask+0x33d/0x420
  __get_user_pages+0xdc/0x800
  populate_vma_page_range+0xb5/0xe0
  __mm_populate+0xc5/0x150
  vm_mmap_pgoff+0xd5/0xe0
  SyS_mmap_pgoff+0x1c1/0x290
  SyS_mmap+0x1b/0x30

Fix it by making the PMD pre-fault handling consistent with PTE.
After pre-faulted in faultin_page(), follow_page_mask() calls
follow_trans_huge_pmd(), which is changed to call follow_pfn_pmd()
for VM_PFNMAP or VM_MIXEDMAP.  follow_pfn_pmd() handles FOLL_TOUCH
and returns with -EEXIST.

Reported-by: Mauricio Porto <mauricio.porto@....com>
Signed-off-by: Toshi Kani <toshi.kani@....com>
Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: Kirill A. Shutemov <kirill.shutemov@...ux.intel.com>
Cc: Matthew Wilcox <willy@...ux.intel.com>
Cc: Dan Williams <dan.j.williams@...el.com>
Cc: Ross Zwisler <ross.zwisler@...ux.intel.com>
---
 mm/huge_memory.c |   34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d5b8920..f56e034 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1267,6 +1267,32 @@ out_unlock:
 	return ret;
 }
 
+/*
+ * Follow a pmd inserted by vmf_insert_pfn_pmd(). See follow_pfn_pte() for pte.
+ */
+static int follow_pfn_pmd(struct vm_area_struct *vma, unsigned long address,
+		pmd_t *pmd, unsigned int flags)
+{
+	/* No page to get reference */
+	if (flags & FOLL_GET)
+		return -EFAULT;
+
+	if (flags & FOLL_TOUCH) {
+		pmd_t entry = *pmd;
+
+		/* Set the dirty bit per follow_trans_huge_pmd() */
+		entry = pmd_mkyoung(pmd_mkdirty(entry));
+
+		if (!pmd_same(*pmd, entry)) {
+			set_pmd_at(vma->vm_mm, address, pmd, entry);
+			update_mmu_cache_pmd(vma, address, pmd);
+		}
+	}
+
+	/* Proper page table entry exists, but no corresponding struct page */
+	return -EEXIST;
+}
+
 struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 				   unsigned long addr,
 				   pmd_t *pmd,
@@ -1274,6 +1300,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct page *page = NULL;
+	int ret;
 
 	assert_spin_locked(pmd_lockptr(mm, pmd));
 
@@ -1288,6 +1315,13 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 	if ((flags & FOLL_NUMA) && pmd_protnone(*pmd))
 		goto out;
 
+	/* pfn map does not have a struct page */
+	if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) {
+		ret = follow_pfn_pmd(vma, addr, pmd, flags);
+		page = ERR_PTR(ret);
+		goto out;
+	}
+
 	page = pmd_page(*pmd);
 	VM_BUG_ON_PAGE(!PageHead(page), page);
 	if (flags & FOLL_TOUCH) {
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ