From 42d7896ebc5f7268b1fe6bbd20f2282e20ae7895 Mon Sep 17 00:00:00 2001 From: James Morris Date: Wed, 26 Dec 2007 15:12:37 +1100 Subject: Security: remove security.h include from mm.h Remove security.h include from mm.h, as it is only needed for a single extern declaration, and pulls in all kinds of crud. Fine-by-me: David Chinner Acked-by: Eric Paris Signed-off-by: James Morris --- include/linux/mm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux/mm.h') diff --git a/include/linux/mm.h b/include/linux/mm.h index 1b7b95c67aca..1897ca223eca 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -12,7 +12,6 @@ #include #include #include -#include struct mempolicy; struct anon_vma; @@ -34,6 +33,8 @@ extern int sysctl_legacy_va_layout; #define sysctl_legacy_va_layout 0 #endif +extern unsigned long mmap_min_addr; + #include #include #include -- cgit v1.2.3 From 03252919b79891063cf99145612360efbdf9500b Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 30 Jan 2008 13:33:18 +0100 Subject: x86: print which shared library/executable faulted in segfault etc. messages v3 They now look like: hal-resmgr[13791]: segfault at 3c rip 2b9c8caec182 rsp 7fff1e825d30 error 4 in libacl.so.1.1.0[2b9c8caea000+6000] This makes it easier to pinpoint bugs to specific libraries. And printing the offset into a mapping also always allows to find the correct fault point in a library even with randomized mappings. Previously there was no way to actually find the correct code address inside the randomized mapping. Relies on earlier patch to shorten the printk formats. They are often now longer than 80 characters, but I think that's worth it. [includes fix from Eric Dumazet to check d_path error value] Signed-off-by: Andi Kleen Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/signal_32.c | 7 +++++-- arch/x86/kernel/signal_64.c | 7 +++++-- arch/x86/kernel/traps_32.c | 7 +++++-- arch/x86/kernel/traps_64.c | 14 ++++++++++---- arch/x86/mm/fault_32.c | 4 +++- arch/x86/mm/fault_64.c | 4 +++- include/linux/mm.h | 1 + mm/memory.c | 31 +++++++++++++++++++++++++++++++ 8 files changed, 63 insertions(+), 12 deletions(-) (limited to 'include/linux/mm.h') diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 74df55895c8c..89a690edf999 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c @@ -198,12 +198,15 @@ asmlinkage int sys_sigreturn(unsigned long __unused) return ax; badframe: - if (show_unhandled_signals && printk_ratelimit()) + if (show_unhandled_signals && printk_ratelimit()) { printk("%s%s[%d] bad frame in sigreturn frame:%p ip:%lx" - " sp:%lx oeax:%lx\n", + " sp:%lx oeax:%lx", task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, current->comm, task_pid_nr(current), frame, regs->ip, regs->sp, regs->orig_ax); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } force_sig(SIGSEGV, current); return 0; diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 4eb751c60390..7347bb14e306 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c @@ -484,9 +484,12 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) void signal_fault(struct pt_regs *regs, void __user *frame, char *where) { struct task_struct *me = current; - if (show_unhandled_signals && printk_ratelimit()) - printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx\n", + if (show_unhandled_signals && printk_ratelimit()) { + printk("%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx", me->comm,me->pid,where,frame,regs->ip,regs->sp,regs->orig_ax); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } force_sig(SIGSEGV, me); } diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 6f3bb287c702..270cfd483160 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -609,11 +609,14 @@ void __kprobes do_general_protection(struct pt_regs * regs, current->thread.error_code = error_code; current->thread.trap_no = 13; if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) && - printk_ratelimit()) + printk_ratelimit()) { printk(KERN_INFO - "%s[%d] general protection ip:%lx sp:%lx error:%lx\n", + "%s[%d] general protection ip:%lx sp:%lx error:%lx", current->comm, task_pid_nr(current), regs->ip, regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } force_sig(SIGSEGV, current); return; diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 814801f4eb9e..911ed28afff8 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -642,11 +642,14 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, tsk->thread.trap_no = trapnr; if (show_unhandled_signals && unhandled_signal(tsk, signr) && - printk_ratelimit()) + printk_ratelimit()) { printk(KERN_INFO - "%s[%d] trap %s ip:%lx sp:%lx error:%lx\n", + "%s[%d] trap %s ip:%lx sp:%lx error:%lx", tsk->comm, tsk->pid, str, regs->ip, regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } if (info) force_sig_info(signr, info, tsk); @@ -741,11 +744,14 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, tsk->thread.trap_no = 13; if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && - printk_ratelimit()) + printk_ratelimit()) { printk(KERN_INFO - "%s[%d] general protection ip:%lx sp:%lx error:%lx\n", + "%s[%d] general protection ip:%lx sp:%lx error:%lx", tsk->comm, tsk->pid, regs->ip, regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); + } force_sig(SIGSEGV, tsk); return; diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index 13d295506a17..276863dc4bdd 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c @@ -514,11 +514,13 @@ bad_area_nosemaphore: #ifdef CONFIG_X86_32 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx", #else - "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n", + "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx", #endif task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, tsk->comm, task_pid_nr(tsk), address, regs->ip, regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); } tsk->thread.cr2 = address; /* Kernel addresses are always protection faults */ diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index b606bdefbb72..9ef0306efe9e 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c @@ -552,11 +552,13 @@ bad_area_nosemaphore: #ifdef CONFIG_X86_32 "%s%s[%d]: segfault at %lx ip %08lx sp %08lx error %lx", #else - "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx\n", + "%s%s[%d]: segfault at %lx ip %lx sp %lx error %lx", #endif task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, tsk->comm, task_pid_nr(tsk), address, regs->ip, regs->sp, error_code); + print_vma_addr(" in ", regs->ip); + printk("\n"); } tsk->thread.cr2 = address; diff --git a/include/linux/mm.h b/include/linux/mm.h index 1897ca223eca..3c22d971afa7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1146,6 +1146,7 @@ extern int randomize_va_space; #endif const char * arch_vma_name(struct vm_area_struct *vma); +void print_vma_addr(char *prefix, unsigned long rip); struct page *sparse_mem_map_populate(unsigned long pnum, int nid); pgd_t *vmemmap_pgd_populate(unsigned long addr, int node); diff --git a/mm/memory.c b/mm/memory.c index 673ebbf499c7..d902d0e25edc 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2754,3 +2754,34 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in return buf - old_buf; } + +/* + * Print the name of a VMA. + */ +void print_vma_addr(char *prefix, unsigned long ip) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + + down_read(&mm->mmap_sem); + vma = find_vma(mm, ip); + if (vma && vma->vm_file) { + struct file *f = vma->vm_file; + char *buf = (char *)__get_free_page(GFP_KERNEL); + if (buf) { + char *p, *s; + + p = d_path(f->f_dentry, f->f_vfsmnt, buf, PAGE_SIZE); + if (IS_ERR(p)) + p = "?"; + s = strrchr(p, '/'); + if (s) + p = s+1; + printk("%s%s[%lx+%lx]", prefix, p, + vma->vm_start, + vma->vm_end - vma->vm_start); + free_page((unsigned long)buf); + } + } + up_read(¤t->mm->mmap_sem); +} -- cgit v1.2.3 From 12d6f21eacc21d84a809829543f2fe45c7e37319 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 30 Jan 2008 13:33:58 +0100 Subject: x86: do not PSE on CONFIG_DEBUG_PAGEALLOC=y get more testing of the c_p_a() code done by not turning off PSE on DEBUG_PAGEALLOC. this simplifies the early pagetable setup code, and tests the largepage-splitup code quite heavily. In the end, all the largepages will be split up pretty quickly, so there's no difference to how DEBUG_PAGEALLOC worked before. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/common.c | 7 ------- arch/x86/mm/pageattr_32.c | 12 +++++++++++- include/asm-x86/cacheflush.h | 5 ----- include/linux/mm.h | 14 +++++++++++++- init/main.c | 5 +++++ 5 files changed, 29 insertions(+), 14 deletions(-) (limited to 'include/linux/mm.h') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index bba850b05d0e..db28aa9e2f69 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -641,13 +641,6 @@ void __init early_cpu_init(void) nexgen_init_cpu(); umc_init_cpu(); early_cpu_detect(); - -#ifdef CONFIG_DEBUG_PAGEALLOC - /* pse is not compatible with on-the-fly unmapping, - * disable it even if the cpus claim to support it. - */ - setup_clear_cpu_cap(X86_FEATURE_PSE); -#endif } /* Make sure %fs is initialized properly in idle threads */ diff --git a/arch/x86/mm/pageattr_32.c b/arch/x86/mm/pageattr_32.c index 9cf2fea54eb5..dd49b16b3a0e 100644 --- a/arch/x86/mm/pageattr_32.c +++ b/arch/x86/mm/pageattr_32.c @@ -61,13 +61,17 @@ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) static int split_large_page(pte_t *kpte, unsigned long address) { pgprot_t ref_prot = pte_pgprot(pte_clrhuge(*kpte)); + gfp_t gfp_flags = GFP_KERNEL; unsigned long flags; unsigned long addr; pte_t *pbase, *tmp; struct page *base; int i, level; - base = alloc_pages(GFP_KERNEL, 0); +#ifdef CONFIG_DEBUG_PAGEALLOC + gfp_flags = GFP_ATOMIC; +#endif + base = alloc_pages(gfp_flags, 0); if (!base) return -ENOMEM; @@ -218,6 +222,12 @@ void kernel_map_pages(struct page *page, int numpages, int enable) numpages * PAGE_SIZE); } + /* + * If page allocator is not up yet then do not call c_p_a(): + */ + if (!debug_pagealloc_enabled) + return; + /* * the return value is ignored - the calls cannot fail, * large pages are disabled at boot time. diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index 9411a2d3f19c..fccb563e2305 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -29,11 +29,6 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot); int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot); void clflush_cache_range(void *addr, int size); -#ifdef CONFIG_DEBUG_PAGEALLOC -/* internal debugging function */ -void kernel_map_pages(struct page *page, int numpages, int enable); -#endif - #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); #endif diff --git a/include/linux/mm.h b/include/linux/mm.h index 3c22d971afa7..1bba6789a50a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1118,9 +1118,21 @@ static inline void vm_stat_account(struct mm_struct *mm, } #endif /* CONFIG_PROC_FS */ -#ifndef CONFIG_DEBUG_PAGEALLOC +#ifdef CONFIG_DEBUG_PAGEALLOC +extern int debug_pagealloc_enabled; + +extern void kernel_map_pages(struct page *page, int numpages, int enable); + +static inline void enable_debug_pagealloc(void) +{ + debug_pagealloc_enabled = 1; +} +#else static inline void kernel_map_pages(struct page *page, int numpages, int enable) {} +static inline void enable_debug_pagealloc(void) +{ +} #endif extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk); diff --git a/init/main.c b/init/main.c index 3316dffe3e57..cb81ed116f62 100644 --- a/init/main.c +++ b/init/main.c @@ -318,6 +318,10 @@ static int __init unknown_bootoption(char *param, char *val) return 0; } +#ifdef CONFIG_DEBUG_PAGEALLOC +int __read_mostly debug_pagealloc_enabled = 0; +#endif + static int __init init_setup(char *str) { unsigned int i; @@ -552,6 +556,7 @@ asmlinkage void __init start_kernel(void) preempt_disable(); build_all_zonelists(); page_alloc_init(); + enable_debug_pagealloc(); printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line); parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, -- cgit v1.2.3