From 07fa7a0a8a586c01a8b416358c7012dcb9dc688d Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 8 Apr 2011 17:29:36 +0200 Subject: powerpc, hw_breakpoints: Fix racy access to ptrace breakpoints While the tracer accesses ptrace breakpoints, the child task may concurrently exit due to a SIGKILL and thus release its breakpoints at the same time. We can then dereference some freed pointers. To fix this, hold a reference on the child breakpoints before manipulating them. Reported-by: Oleg Nesterov Signed-off-by: Frederic Weisbecker Acked-by: Prasad Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Will Deacon Cc: Paul Mundt Cc: v2.6.33.. Link: http://lkml.kernel.org/r/1302284067-7860-4-git-send-email-fweisbec@gmail.com --- arch/powerpc/kernel/ptrace.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 55613e33e26..4edeeb32542 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -1591,7 +1591,10 @@ long arch_ptrace(struct task_struct *child, long request, } case PTRACE_SET_DEBUGREG: + if (ptrace_get_breakpoints(child) < 0) + return -ESRCH; ret = ptrace_set_debugreg(child, addr, data); + ptrace_put_breakpoints(child); break; #ifdef CONFIG_PPC64 -- cgit v1.2.3-70-g09d2 From 925f83c085e1bb08435556c5b4844a60de002e31 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 6 May 2011 01:53:18 +0200 Subject: hw_breakpoints, powerpc: Fix CONFIG_HAVE_HW_BREAKPOINT off-case in ptrace_set_debugreg() We make use of ptrace_get_breakpoints() / ptrace_put_breakpoints() to protect ptrace_set_debugreg() even if CONFIG_HAVE_HW_BREAKPOINT if off. However in this case, these APIs are not implemented. To fix this, push the protection down inside the relevant ifdef. Best would be to export the code inside CONFIG_HAVE_HW_BREAKPOINT into a standalone function to cleanup the ifdefury there and call the breakpoint ref API inside. But as it is more invasive, this should be rather made in an -rc1. Fixes this build error: arch/powerpc/kernel/ptrace.c:1594: error: implicit declaration of function 'ptrace_get_breakpoints' make[2]: *** Reported-by: Ingo Molnar Signed-off-by: Frederic Weisbecker Cc: LPPC Cc: Prasad Cc: v2.6.33.. Link: http://lkml.kernel.org/r/1304639598-4707-1-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- arch/powerpc/kernel/ptrace.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 4edeeb32542..a6ae1cfad86 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -933,12 +933,16 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, if (data && !(data & DABR_TRANSLATION)) return -EIO; #ifdef CONFIG_HAVE_HW_BREAKPOINT + if (ptrace_get_breakpoints(task) < 0) + return -ESRCH; + bp = thread->ptrace_bps[0]; if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) { if (bp) { unregister_hw_breakpoint(bp); thread->ptrace_bps[0] = NULL; } + ptrace_put_breakpoints(task); return 0; } if (bp) { @@ -948,9 +952,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, (DABR_DATA_WRITE | DABR_DATA_READ), &attr.bp_type); ret = modify_user_hw_breakpoint(bp, &attr); - if (ret) + if (ret) { + ptrace_put_breakpoints(task); return ret; + } thread->ptrace_bps[0] = bp; + ptrace_put_breakpoints(task); thread->dabr = data; return 0; } @@ -965,9 +972,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, ptrace_triggered, task); if (IS_ERR(bp)) { thread->ptrace_bps[0] = NULL; + ptrace_put_breakpoints(task); return PTR_ERR(bp); } + ptrace_put_breakpoints(task); + #endif /* CONFIG_HAVE_HW_BREAKPOINT */ /* Move contents to the DABR register */ @@ -1591,10 +1601,7 @@ long arch_ptrace(struct task_struct *child, long request, } case PTRACE_SET_DEBUGREG: - if (ptrace_get_breakpoints(child) < 0) - return -ESRCH; ret = ptrace_set_debugreg(child, addr, data); - ptrace_put_breakpoints(child); break; #ifdef CONFIG_PPC64 -- cgit v1.2.3-70-g09d2 From 69e3cea8d5fd52677f2b6219542d0f8b53fe4c80 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 19 May 2011 13:07:12 +1000 Subject: powerpc/smp: Make start_secondary_resume available to all CPU variants This should fix SMP & Hotplug builds on FSL BookE and 476 Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/head_32.S | 9 --------- arch/powerpc/kernel/misc_32.S | 11 +++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index c5c24beb838..98c4b29a56f 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -890,15 +890,6 @@ __secondary_start: mtspr SPRN_SRR1,r4 SYNC RFI - -_GLOBAL(start_secondary_resume) - /* Reset stack */ - rlwinm r1,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ - addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD - li r3,0 - std r3,0(r1) /* Zero the stack frame pointer */ - bl start_secondary - b . #endif /* CONFIG_SMP */ #ifdef CONFIG_KVM_BOOK3S_HANDLER diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 094bd9821ad..402560e957b 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -694,6 +694,17 @@ _GLOBAL(kernel_thread) addi r1,r1,16 blr +#ifdef CONFIG_SMP +_GLOBAL(start_secondary_resume) + /* Reset stack */ + rlwinm r1,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ + addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD + li r3,0 + std r3,0(r1) /* Zero the stack frame pointer */ + bl start_secondary + b . +#endif /* CONFIG_SMP */ + /* * This routine is just here to keep GCC happy - sigh... */ -- cgit v1.2.3-70-g09d2 From 35d215fbe4f4d3569f2adabd8d53510a26ecb9c5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 24 Apr 2011 15:04:31 +0000 Subject: powerpc/kexec: Fix build failure on 32-bit SMP Commit b987812b3fcaf70fdf0037589e5d2f5f2453e6ce left crash_kexec_wait_realmode() undefined for UP. Commit 7c7a81b53e581d727d069cc45df5510516faac31 defined it for UP but left it undefined for 32-bit SMP. Seems like people are getting confused by nested #ifdef's, so move the definitions of crash_kexec_wait_realmode() after the #ifdef CONFIG_SMP section. Compile-tested with 32-bit UP, 32-bit SMP and 64-bit SMP configurations. Signed-off-by: Ben Hutchings Tested-by: Paul Gortmaker Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/crash.c | 59 +++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 5b5e1f002a8..5eb0ee37f6c 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c @@ -162,34 +162,6 @@ static void crash_kexec_prepare_cpus(int cpu) /* Leave the IPI callback set */ } -/* wait for all the CPUs to hit real mode but timeout if they don't come in */ -#ifdef CONFIG_PPC_STD_MMU_64 -static void crash_kexec_wait_realmode(int cpu) -{ - unsigned int msecs; - int i; - - msecs = 10000; - for (i=0; i < NR_CPUS && msecs > 0; i++) { - if (i == cpu) - continue; - - while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) { - barrier(); - if (!cpu_possible(i)) { - break; - } - if (!cpu_online(i)) { - break; - } - msecs--; - mdelay(1); - } - } - mb(); -} -#endif /* CONFIG_PPC_STD_MMU_64 */ - /* * This function will be called by secondary cpus or by kexec cpu * if soft-reset is activated to stop some CPUs. @@ -234,7 +206,6 @@ void crash_kexec_secondary(struct pt_regs *regs) } #else /* ! CONFIG_SMP */ -static inline void crash_kexec_wait_realmode(int cpu) {} static void crash_kexec_prepare_cpus(int cpu) { @@ -257,6 +228,36 @@ void crash_kexec_secondary(struct pt_regs *regs) } #endif /* CONFIG_SMP */ +/* wait for all the CPUs to hit real mode but timeout if they don't come in */ +#if defined(CONFIG_SMP) && defined(CONFIG_PPC_STD_MMU_64) +static void crash_kexec_wait_realmode(int cpu) +{ + unsigned int msecs; + int i; + + msecs = 10000; + for (i=0; i < NR_CPUS && msecs > 0; i++) { + if (i == cpu) + continue; + + while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) { + barrier(); + if (!cpu_possible(i)) { + break; + } + if (!cpu_online(i)) { + break; + } + msecs--; + mdelay(1); + } + } + mb(); +} +#else +static inline void crash_kexec_wait_realmode(int cpu) {} +#endif /* CONFIG_SMP && CONFIG_PPC_STD_MMU_64 */ + /* * Register a function to be called on shutdown. Only use this if you * can't reset your device in the second kernel. -- cgit v1.2.3-70-g09d2 From c560bbceaf6b06e52f1ef20131b76a3fdc0a2c19 Mon Sep 17 00:00:00 2001 From: kerstin jonsson Date: Tue, 17 May 2011 23:57:11 +0000 Subject: powerpc/4xx: Fix regression in SMP on 476 commit c56e58537d504706954a06570b4034c04e5b7500 breaks SMP support in PPC_47x chip. secondary_ti must be set to current thread info before callin kick_cpu or else start_secondary_47x will jump into void when trying to return to c-code. In the current setup secondary_ti is initialized before the CPU idle task is started and only the boot core will start. I am not sure this is the correct solution, but it makes SMP possible in my chip. Note! The HOTPLUG support probably need some fixing to, There is no trampoline code available in head_44x.S - start_secondary_resume? Signed-off-by: Kerstin Jonsson Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/smp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index cbdbb14be4b..f2dcab7aadc 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -410,8 +410,6 @@ int __cpuinit __cpu_up(unsigned int cpu) { int rc, c; - secondary_ti = current_set[cpu]; - if (smp_ops == NULL || (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) return -EINVAL; @@ -421,6 +419,8 @@ int __cpuinit __cpu_up(unsigned int cpu) if (rc) return rc; + secondary_ti = current_set[cpu]; + /* Make sure callin-map entry is 0 (can be leftover a CPU * hotplug */ -- cgit v1.2.3-70-g09d2