Browse Source

Merge branch 'akpm' (patches from Andrew)

Merge fixes from Andrew Morton:
 "13 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  dma-mapping: avoid oops when parameter cpu_addr is null
  mm/hugetlb: use EOPNOTSUPP in hugetlb sysctl handlers
  memremap: check pfn validity before passing to pfn_to_page()
  mm, thp: fix migration of PTE-mapped transparent huge pages
  dax: check return value of dax_radix_entry()
  ocfs2: fix return value from ocfs2_page_mkwrite()
  arm64: kasan: clear stale stack poison
  sched/kasan: remove stale KASAN poison after hotplug
  kasan: add functions to clear stack poison
  mm: fix mixed zone detection in devm_memremap_pages
  list: kill list_force_poison()
  mm: __delete_from_page_cache show Bad page if mapped
  mm/hugetlb: hugetlb_no_page: rate-limit warning message
Linus Torvalds 9 years ago
parent
commit
380173ff56

+ 4 - 0
arch/arm64/kernel/sleep.S

@@ -145,6 +145,10 @@ ENTRY(cpu_resume_mmu)
 ENDPROC(cpu_resume_mmu)
 ENDPROC(cpu_resume_mmu)
 	.popsection
 	.popsection
 cpu_resume_after_mmu:
 cpu_resume_after_mmu:
+#ifdef CONFIG_KASAN
+	mov	x0, sp
+	bl	kasan_unpoison_remaining_stack
+#endif
 	mov	x0, #0			// return zero on success
 	mov	x0, #0			// return zero on success
 	ldp	x19, x20, [sp, #16]
 	ldp	x19, x20, [sp, #16]
 	ldp	x21, x22, [sp, #32]
 	ldp	x21, x22, [sp, #32]

+ 8 - 1
fs/dax.c

@@ -1056,6 +1056,7 @@ EXPORT_SYMBOL_GPL(dax_pmd_fault);
 int dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 int dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 {
 	struct file *file = vma->vm_file;
 	struct file *file = vma->vm_file;
+	int error;
 
 
 	/*
 	/*
 	 * We pass NO_SECTOR to dax_radix_entry() because we expect that a
 	 * We pass NO_SECTOR to dax_radix_entry() because we expect that a
@@ -1065,7 +1066,13 @@ int dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	 * saves us from having to make a call to get_block() here to look
 	 * saves us from having to make a call to get_block() here to look
 	 * up the sector.
 	 * up the sector.
 	 */
 	 */
-	dax_radix_entry(file->f_mapping, vmf->pgoff, NO_SECTOR, false, true);
+	error = dax_radix_entry(file->f_mapping, vmf->pgoff, NO_SECTOR, false,
+			true);
+
+	if (error == -ENOMEM)
+		return VM_FAULT_OOM;
+	if (error)
+		return VM_FAULT_SIGBUS;
 	return VM_FAULT_NOPAGE;
 	return VM_FAULT_NOPAGE;
 }
 }
 EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);
 EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);

+ 4 - 0
fs/ocfs2/mmap.c

@@ -147,6 +147,10 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	ret = ocfs2_inode_lock(inode, &di_bh, 1);
 	ret = ocfs2_inode_lock(inode, &di_bh, 1);
 	if (ret < 0) {
 	if (ret < 0) {
 		mlog_errno(ret);
 		mlog_errno(ret);
+		if (ret == -ENOMEM)
+			ret = VM_FAULT_OOM;
+		else
+			ret = VM_FAULT_SIGBUS;
 		goto out;
 		goto out;
 	}
 	}
 
 

+ 1 - 1
include/linux/dma-mapping.h

@@ -386,7 +386,7 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
 	if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
 	if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
 		return;
 		return;
 
 
-	if (!ops->free)
+	if (!ops->free || !cpu_addr)
 		return;
 		return;
 
 
 	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
 	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);

+ 5 - 1
include/linux/kasan.h

@@ -1,6 +1,7 @@
 #ifndef _LINUX_KASAN_H
 #ifndef _LINUX_KASAN_H
 #define _LINUX_KASAN_H
 #define _LINUX_KASAN_H
 
 
+#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/types.h>
 
 
 struct kmem_cache;
 struct kmem_cache;
@@ -13,7 +14,6 @@ struct vm_struct;
 
 
 #include <asm/kasan.h>
 #include <asm/kasan.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable.h>
-#include <linux/sched.h>
 
 
 extern unsigned char kasan_zero_page[PAGE_SIZE];
 extern unsigned char kasan_zero_page[PAGE_SIZE];
 extern pte_t kasan_zero_pte[PTRS_PER_PTE];
 extern pte_t kasan_zero_pte[PTRS_PER_PTE];
@@ -43,6 +43,8 @@ static inline void kasan_disable_current(void)
 
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 void kasan_unpoison_shadow(const void *address, size_t size);
 
 
+void kasan_unpoison_task_stack(struct task_struct *task);
+
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
 
 
@@ -66,6 +68,8 @@ void kasan_free_shadow(const struct vm_struct *vm);
 
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
 
 
+static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
+
 static inline void kasan_enable_current(void) {}
 static inline void kasan_enable_current(void) {}
 static inline void kasan_disable_current(void) {}
 static inline void kasan_disable_current(void) {}
 
 

+ 0 - 11
include/linux/list.h

@@ -113,17 +113,6 @@ extern void __list_del_entry(struct list_head *entry);
 extern void list_del(struct list_head *entry);
 extern void list_del(struct list_head *entry);
 #endif
 #endif
 
 
-#ifdef CONFIG_DEBUG_LIST
-/*
- * See devm_memremap_pages() which wants DEBUG_LIST=y to assert if one
- * of the pages it allocates is ever passed to list_add()
- */
-extern void list_force_poison(struct list_head *entry);
-#else
-/* fallback to the less strict LIST_POISON* definitions */
-#define list_force_poison list_del
-#endif
-
 /**
 /**
  * list_replace - replace old entry by new one
  * list_replace - replace old entry by new one
  * @old : the element to be replaced
  * @old : the element to be replaced

+ 15 - 9
kernel/memremap.c

@@ -29,10 +29,10 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
 
 
 static void *try_ram_remap(resource_size_t offset, size_t size)
 static void *try_ram_remap(resource_size_t offset, size_t size)
 {
 {
-	struct page *page = pfn_to_page(offset >> PAGE_SHIFT);
+	unsigned long pfn = PHYS_PFN(offset);
 
 
 	/* In the simple case just return the existing linear address */
 	/* In the simple case just return the existing linear address */
-	if (!PageHighMem(page))
+	if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)))
 		return __va(offset);
 		return __va(offset);
 	return NULL; /* fallback to ioremap_cache */
 	return NULL; /* fallback to ioremap_cache */
 }
 }
@@ -270,13 +270,16 @@ struct dev_pagemap *find_dev_pagemap(resource_size_t phys)
 void *devm_memremap_pages(struct device *dev, struct resource *res,
 void *devm_memremap_pages(struct device *dev, struct resource *res,
 		struct percpu_ref *ref, struct vmem_altmap *altmap)
 		struct percpu_ref *ref, struct vmem_altmap *altmap)
 {
 {
-	int is_ram = region_intersects(res->start, resource_size(res),
-			"System RAM");
 	resource_size_t key, align_start, align_size, align_end;
 	resource_size_t key, align_start, align_size, align_end;
 	struct dev_pagemap *pgmap;
 	struct dev_pagemap *pgmap;
 	struct page_map *page_map;
 	struct page_map *page_map;
+	int error, nid, is_ram;
 	unsigned long pfn;
 	unsigned long pfn;
-	int error, nid;
+
+	align_start = res->start & ~(SECTION_SIZE - 1);
+	align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
+		- align_start;
+	is_ram = region_intersects(align_start, align_size, "System RAM");
 
 
 	if (is_ram == REGION_MIXED) {
 	if (is_ram == REGION_MIXED) {
 		WARN_ONCE(1, "%s attempted on mixed region %pr\n",
 		WARN_ONCE(1, "%s attempted on mixed region %pr\n",
@@ -314,8 +317,6 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
 
 
 	mutex_lock(&pgmap_lock);
 	mutex_lock(&pgmap_lock);
 	error = 0;
 	error = 0;
-	align_start = res->start & ~(SECTION_SIZE - 1);
-	align_size = ALIGN(resource_size(res), SECTION_SIZE);
 	align_end = align_start + align_size - 1;
 	align_end = align_start + align_size - 1;
 	for (key = align_start; key <= align_end; key += SECTION_SIZE) {
 	for (key = align_start; key <= align_end; key += SECTION_SIZE) {
 		struct dev_pagemap *dup;
 		struct dev_pagemap *dup;
@@ -351,8 +352,13 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
 	for_each_device_pfn(pfn, page_map) {
 	for_each_device_pfn(pfn, page_map) {
 		struct page *page = pfn_to_page(pfn);
 		struct page *page = pfn_to_page(pfn);
 
 
-		/* ZONE_DEVICE pages must never appear on a slab lru */
-		list_force_poison(&page->lru);
+		/*
+		 * ZONE_DEVICE pages union ->lru with a ->pgmap back
+		 * pointer.  It is a bug if a ZONE_DEVICE page is ever
+		 * freed or placed on a driver-private list.  Seed the
+		 * storage with LIST_POISON* values.
+		 */
+		list_del(&page->lru);
 		page->pgmap = pgmap;
 		page->pgmap = pgmap;
 	}
 	}
 	devres_add(dev, page_map);
 	devres_add(dev, page_map);

+ 3 - 0
kernel/sched/core.c

@@ -26,6 +26,7 @@
  *              Thomas Gleixner, Mike Kravetz
  *              Thomas Gleixner, Mike Kravetz
  */
  */
 
 
+#include <linux/kasan.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/nmi.h>
@@ -5096,6 +5097,8 @@ void init_idle(struct task_struct *idle, int cpu)
 	idle->state = TASK_RUNNING;
 	idle->state = TASK_RUNNING;
 	idle->se.exec_start = sched_clock();
 	idle->se.exec_start = sched_clock();
 
 
+	kasan_unpoison_task_stack(idle);
+
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
 	/*
 	/*
 	 * Its possible that init_idle() gets called multiple times on a task,
 	 * Its possible that init_idle() gets called multiple times on a task,

+ 0 - 9
lib/list_debug.c

@@ -12,13 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/rculist.h>
 #include <linux/rculist.h>
 
 
-static struct list_head force_poison;
-void list_force_poison(struct list_head *entry)
-{
-	entry->next = &force_poison;
-	entry->prev = &force_poison;
-}
-
 /*
 /*
  * Insert a new entry between two known consecutive entries.
  * Insert a new entry between two known consecutive entries.
  *
  *
@@ -30,8 +23,6 @@ void __list_add(struct list_head *new,
 			      struct list_head *prev,
 			      struct list_head *prev,
 			      struct list_head *next)
 			      struct list_head *next)
 {
 {
-	WARN(new->next == &force_poison || new->prev == &force_poison,
-		"list_add attempted on force-poisoned entry\n");
 	WARN(next->prev != prev,
 	WARN(next->prev != prev,
 		"list_add corruption. next->prev should be "
 		"list_add corruption. next->prev should be "
 		"prev (%p), but was %p. (next=%p).\n",
 		"prev (%p), but was %p. (next=%p).\n",

+ 24 - 1
mm/filemap.c

@@ -195,6 +195,30 @@ void __delete_from_page_cache(struct page *page, void *shadow,
 	else
 	else
 		cleancache_invalidate_page(mapping, page);
 		cleancache_invalidate_page(mapping, page);
 
 
+	VM_BUG_ON_PAGE(page_mapped(page), page);
+	if (!IS_ENABLED(CONFIG_DEBUG_VM) && unlikely(page_mapped(page))) {
+		int mapcount;
+
+		pr_alert("BUG: Bad page cache in process %s  pfn:%05lx\n",
+			 current->comm, page_to_pfn(page));
+		dump_page(page, "still mapped when deleted");
+		dump_stack();
+		add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
+
+		mapcount = page_mapcount(page);
+		if (mapping_exiting(mapping) &&
+		    page_count(page) >= mapcount + 2) {
+			/*
+			 * All vmas have already been torn down, so it's
+			 * a good bet that actually the page is unmapped,
+			 * and we'd prefer not to leak it: if we're wrong,
+			 * some other bad page check should catch it later.
+			 */
+			page_mapcount_reset(page);
+			atomic_sub(mapcount, &page->_count);
+		}
+	}
+
 	page_cache_tree_delete(mapping, page, shadow);
 	page_cache_tree_delete(mapping, page, shadow);
 
 
 	page->mapping = NULL;
 	page->mapping = NULL;
@@ -205,7 +229,6 @@ void __delete_from_page_cache(struct page *page, void *shadow,
 		__dec_zone_page_state(page, NR_FILE_PAGES);
 		__dec_zone_page_state(page, NR_FILE_PAGES);
 	if (PageSwapBacked(page))
 	if (PageSwapBacked(page))
 		__dec_zone_page_state(page, NR_SHMEM);
 		__dec_zone_page_state(page, NR_SHMEM);
-	VM_BUG_ON_PAGE(page_mapped(page), page);
 
 
 	/*
 	/*
 	 * At this point page must be either written or cleaned by truncate.
 	 * At this point page must be either written or cleaned by truncate.

+ 3 - 3
mm/hugetlb.c

@@ -2751,7 +2751,7 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
 	int ret;
 	int ret;
 
 
 	if (!hugepages_supported())
 	if (!hugepages_supported())
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 
 	table->data = &tmp;
 	table->data = &tmp;
 	table->maxlen = sizeof(unsigned long);
 	table->maxlen = sizeof(unsigned long);
@@ -2792,7 +2792,7 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
 	int ret;
 	int ret;
 
 
 	if (!hugepages_supported())
 	if (!hugepages_supported())
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 
 	tmp = h->nr_overcommit_huge_pages;
 	tmp = h->nr_overcommit_huge_pages;
 
 
@@ -3502,7 +3502,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 	 * COW. Warn that such a situation has occurred as it may not be obvious
 	 * COW. Warn that such a situation has occurred as it may not be obvious
 	 */
 	 */
 	if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) {
 	if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) {
-		pr_warning("PID %d killed due to inadequate hugepage pool\n",
+		pr_warn_ratelimited("PID %d killed due to inadequate hugepage pool\n",
 			   current->pid);
 			   current->pid);
 		return ret;
 		return ret;
 	}
 	}

+ 20 - 0
mm/kasan/kasan.c

@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/kmemleak.h>
 #include <linux/kmemleak.h>
+#include <linux/linkage.h>
 #include <linux/memblock.h>
 #include <linux/memblock.h>
 #include <linux/memory.h>
 #include <linux/memory.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
@@ -60,6 +61,25 @@ void kasan_unpoison_shadow(const void *address, size_t size)
 	}
 	}
 }
 }
 
 
+static void __kasan_unpoison_stack(struct task_struct *task, void *sp)
+{
+	void *base = task_stack_page(task);
+	size_t size = sp - base;
+
+	kasan_unpoison_shadow(base, size);
+}
+
+/* Unpoison the entire stack for a task. */
+void kasan_unpoison_task_stack(struct task_struct *task)
+{
+	__kasan_unpoison_stack(task, task_stack_page(task) + THREAD_SIZE);
+}
+
+/* Unpoison the stack for the current task beyond a watermark sp value. */
+asmlinkage void kasan_unpoison_remaining_stack(void *sp)
+{
+	__kasan_unpoison_stack(current, sp);
+}
 
 
 /*
 /*
  * All functions below always inlined so compiler could
  * All functions below always inlined so compiler could

+ 1 - 1
mm/mempolicy.c

@@ -532,7 +532,7 @@ retry:
 		nid = page_to_nid(page);
 		nid = page_to_nid(page);
 		if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT))
 		if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT))
 			continue;
 			continue;
-		if (PageTail(page) && PageAnon(page)) {
+		if (PageTransCompound(page) && PageAnon(page)) {
 			get_page(page);
 			get_page(page);
 			pte_unmap_unlock(pte, ptl);
 			pte_unmap_unlock(pte, ptl);
 			lock_page(page);
 			lock_page(page);