Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758183AbZCCQBg (ORCPT ); Tue, 3 Mar 2009 11:01:36 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751584AbZCCQB1 (ORCPT ); Tue, 3 Mar 2009 11:01:27 -0500 Received: from ti-out-0910.google.com ([209.85.142.191]:53676 "EHLO ti-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750756AbZCCQBZ (ORCPT ); Tue, 3 Mar 2009 11:01:25 -0500 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=i4onFO3tyOyE7bVX1+XlJ0+piWPgfYAmm5Ec1Nnm4wvn8DflVFUrO4rbWro/xlXFj0 D3qOy65wTUb+9ngMbM5YMHmAFZVonG/o37NJvVEXK1HQxXXXMaKEjfaTB67u1TVxuFsa /PpVWVTnNebJlUYke+8yovSf2U9Mpl1S2cFgo= Date: Wed, 4 Mar 2009 01:01:04 +0900 From: Akinobu Mita To: linux-kernel@vger.kernel.org Cc: linux-arch@vger.kernel.org, linux-mm@kvack.org, akpm@linux-foundation.org Subject: [PATCH] generic debug pagealloc Message-ID: <20090303160103.GB5812@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-2022-jp Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9969 Lines: 316 CONFIG_DEBUG_PAGEALLOC is now supported by x86, powerpc, sparc (64bit), and s390. This patch implements it for the rest of the architectures by filling the pages with poison byte patterns after free_pages() and verifying the poison patterns before alloc_pages(). This generic one cannot detect invalid read accesses and it can only detect invalid write accesses after a long delay. But it is an feasible way for nommu architectures. Signed-off-by: Akinobu Mita Cc: linux-arch@vger.kernel.org Cc: linux-mm@kvack.org --- arch/avr32/mm/fault.c | 18 ---------- arch/powerpc/Kconfig | 3 + arch/powerpc/Kconfig.debug | 1 arch/s390/Kconfig | 3 + arch/s390/Kconfig.debug | 1 arch/sparc/Kconfig | 3 + arch/sparc/Kconfig.debug | 3 + arch/x86/Kconfig | 3 + arch/x86/Kconfig.debug | 1 include/linux/mm_types.h | 4 ++ include/linux/poison.h | 3 + lib/Kconfig.debug | 1 mm/Kconfig.debug | 8 ++++ mm/Makefile | 1 mm/debug-pagealloc.c | 81 +++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 115 insertions(+), 19 deletions(-) Index: 2.6-poison/include/linux/poison.h =================================================================== --- 2.6-poison.orig/include/linux/poison.h +++ 2.6-poison/include/linux/poison.h @@ -17,6 +17,9 @@ */ #define TIMER_ENTRY_STATIC ((void *) 0x74737461) +/********** mm/debug-pagealloc.c **********/ +#define PAGE_POISON 0xaa + /********** mm/slab.c **********/ /* * Magic nums for obj red zoning. Index: 2.6-poison/mm/debug-pagealloc.c =================================================================== --- /dev/null +++ 2.6-poison/mm/debug-pagealloc.c @@ -0,0 +1,81 @@ +#include +#include + +static void poison_page(struct page *page) +{ + void *addr; + + page->poison = true; + addr = kmap_atomic(page, KM_USER0); + memset(addr, PAGE_POISON, PAGE_SIZE); + kunmap_atomic(addr, KM_USER0); +} + +static void poison_pages(struct page *page, int n) +{ + int i; + + for (i = 0; i < n; i++) + poison_page(page + i); +} + +static void dump_broken_mem(unsigned char *mem) +{ + int i; + int start = 0; + int end = PAGE_SIZE - 1; + + for (i = 0; i < PAGE_SIZE; i++) { + if (mem[i] != PAGE_POISON) { + start = i; + break; + } + } + for (i = PAGE_SIZE - 1; i >= start; i--) { + if (mem[i] != PAGE_POISON) { + end = i; + break; + } + } + printk(KERN_ERR "Page corruption: %p-%p\n", mem + start, mem + end); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, mem + start, + end - start + 1, 1); +} + +static void unpoison_page(struct page *page) +{ + unsigned char *mem; + int i; + + if (!page->poison) + return; + + mem = kmap_atomic(page, KM_USER0); + for (i = 0; i < PAGE_SIZE; i++) { + if (mem[i] != PAGE_POISON) { + dump_broken_mem(mem); + break; + } + } + kunmap_atomic(mem, KM_USER0); + page->poison = false; +} + +static void unpoison_pages(struct page *page, int n) +{ + int i; + + for (i = 0; i < n; i++) + unpoison_page(page + i); +} + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (!debug_pagealloc_enabled) + return; + + if (enable) + unpoison_pages(page, numpages); + else + poison_pages(page, numpages); +} Index: 2.6-poison/mm/Kconfig.debug =================================================================== --- /dev/null +++ 2.6-poison/mm/Kconfig.debug @@ -0,0 +1,8 @@ +config PAGE_POISONING + bool "Debug page memory allocations" + depends on !ARCH_SUPPORTS_DEBUG_PAGEALLOC + select DEBUG_PAGEALLOC + help + Fill the pages with poison patterns after free_pages() and verify + the patterns before alloc_pages(). This results in a large slowdown, + but helps to find certain types of memory corruptions. Index: 2.6-poison/mm/Makefile =================================================================== --- 2.6-poison.orig/mm/Makefile +++ 2.6-poison/mm/Makefile @@ -33,3 +33,4 @@ obj-$(CONFIG_MIGRATION) += migrate.o obj-$(CONFIG_SMP) += allocpercpu.o obj-$(CONFIG_QUICKLIST) += quicklist.o obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o +obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o Index: 2.6-poison/lib/Kconfig.debug =================================================================== --- 2.6-poison.orig/lib/Kconfig.debug +++ 2.6-poison/lib/Kconfig.debug @@ -796,6 +796,7 @@ config SYSCTL_SYSCALL_CHECK to properly maintain and use. This enables checks that help you to keep things correct. +source mm/Kconfig.debug source kernel/trace/Kconfig config PROVIDE_OHCI1394_DMA_INIT Index: 2.6-poison/arch/powerpc/Kconfig.debug =================================================================== --- 2.6-poison.orig/arch/powerpc/Kconfig.debug +++ 2.6-poison/arch/powerpc/Kconfig.debug @@ -30,6 +30,7 @@ config DEBUG_STACK_USAGE config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL && !HIBERNATION + depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC help Unmap pages from the kernel linear mapping after free_pages(). This results in a large slowdown, but helps to find certain types Index: 2.6-poison/arch/s390/Kconfig.debug =================================================================== --- 2.6-poison.orig/arch/s390/Kconfig.debug +++ 2.6-poison/arch/s390/Kconfig.debug @@ -9,6 +9,7 @@ source "lib/Kconfig.debug" config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL + depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC help Unmap pages from the kernel linear mapping after free_pages(). This results in a slowdown, but helps to find certain types of Index: 2.6-poison/arch/sparc/Kconfig.debug =================================================================== --- 2.6-poison.orig/arch/sparc/Kconfig.debug +++ 2.6-poison/arch/sparc/Kconfig.debug @@ -24,7 +24,8 @@ config STACK_DEBUG config DEBUG_PAGEALLOC bool "Debug page memory allocations" - depends on SPARC64 && DEBUG_KERNEL && !HIBERNATION + depends on DEBUG_KERNEL && !HIBERNATION + depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC help Unmap pages from the kernel linear mapping after free_pages(). This results in a large slowdown, but helps to find certain types Index: 2.6-poison/arch/x86/Kconfig =================================================================== --- 2.6-poison.orig/arch/x86/Kconfig +++ 2.6-poison/arch/x86/Kconfig @@ -160,6 +160,9 @@ config AUDIT_ARCH config ARCH_SUPPORTS_OPTIMIZED_INLINING def_bool y +config ARCH_SUPPORTS_DEBUG_PAGEALLOC + def_bool y + # Use the generic interrupt handling code in kernel/irq/: config GENERIC_HARDIRQS bool Index: 2.6-poison/arch/x86/Kconfig.debug =================================================================== --- 2.6-poison.orig/arch/x86/Kconfig.debug +++ 2.6-poison/arch/x86/Kconfig.debug @@ -75,6 +75,7 @@ config DEBUG_STACK_USAGE config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL + depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC help Unmap pages from the kernel linear mapping after free_pages(). This results in a large slowdown, but helps to find certain types Index: 2.6-poison/arch/powerpc/Kconfig =================================================================== --- 2.6-poison.orig/arch/powerpc/Kconfig +++ 2.6-poison/arch/powerpc/Kconfig @@ -227,6 +227,9 @@ config PPC_OF_PLATFORM_PCI depends on PPC64 # not supported on 32 bits yet default n +config ARCH_SUPPORTS_DEBUG_PAGEALLOC + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" Index: 2.6-poison/arch/sparc/Kconfig =================================================================== --- 2.6-poison.orig/arch/sparc/Kconfig +++ 2.6-poison/arch/sparc/Kconfig @@ -124,6 +124,9 @@ config ARCH_NO_VIRT_TO_BUS config OF def_bool y +config ARCH_SUPPORTS_DEBUG_PAGEALLOC + def_bool y if SPARC64 + source "init/Kconfig" source "kernel/Kconfig.freezer" Index: 2.6-poison/arch/avr32/mm/fault.c =================================================================== --- 2.6-poison.orig/arch/avr32/mm/fault.c +++ 2.6-poison/arch/avr32/mm/fault.c @@ -250,21 +250,3 @@ asmlinkage void do_bus_error(unsigned lo dump_dtlb(); die("Bus Error", regs, SIGKILL); } - -/* - * This functionality is currently not possible to implement because - * we're using segmentation to ensure a fixed mapping of the kernel - * virtual address space. - * - * It would be possible to implement this, but it would require us to - * disable segmentation at startup and load the kernel mappings into - * the TLB like any other pages. There will be lots of trickery to - * avoid recursive invocation of the TLB miss handler, though... - */ -#ifdef CONFIG_DEBUG_PAGEALLOC -void kernel_map_pages(struct page *page, int numpages, int enable) -{ - -} -EXPORT_SYMBOL(kernel_map_pages); -#endif Index: 2.6-poison/arch/s390/Kconfig =================================================================== --- 2.6-poison.orig/arch/s390/Kconfig +++ 2.6-poison/arch/s390/Kconfig @@ -72,6 +72,9 @@ config PGSTE config VIRT_CPU_ACCOUNTING def_bool y +config ARCH_SUPPORTS_DEBUG_PAGEALLOC + def_bool y + mainmenu "Linux Kernel Configuration" config S390 Index: 2.6-poison/include/linux/mm_types.h =================================================================== --- 2.6-poison.orig/include/linux/mm_types.h +++ 2.6-poison/include/linux/mm_types.h @@ -94,6 +94,10 @@ struct page { void *virtual; /* Kernel virtual address (NULL if not kmapped, ie. highmem) */ #endif /* WANT_PAGE_VIRTUAL */ + +#ifdef CONFIG_PAGE_POISONING + bool poison; +#endif /* CONFIG_PAGE_POISONING */ }; /* -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/