diff options
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r-- | arch/powerpc/kernel/process.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index f3d4dd580dd6..972b2acbe713 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -818,6 +818,35 @@ out: | |||
818 | return error; | 818 | return error; |
819 | } | 819 | } |
820 | 820 | ||
821 | #ifdef CONFIG_IRQSTACKS | ||
822 | static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, | ||
823 | unsigned long nbytes) | ||
824 | { | ||
825 | unsigned long stack_page; | ||
826 | unsigned long cpu = task_cpu(p); | ||
827 | |||
828 | /* | ||
829 | * Avoid crashing if the stack has overflowed and corrupted | ||
830 | * task_cpu(p), which is in the thread_info struct. | ||
831 | */ | ||
832 | if (cpu < NR_CPUS && cpu_possible(cpu)) { | ||
833 | stack_page = (unsigned long) hardirq_ctx[cpu]; | ||
834 | if (sp >= stack_page + sizeof(struct thread_struct) | ||
835 | && sp <= stack_page + THREAD_SIZE - nbytes) | ||
836 | return 1; | ||
837 | |||
838 | stack_page = (unsigned long) softirq_ctx[cpu]; | ||
839 | if (sp >= stack_page + sizeof(struct thread_struct) | ||
840 | && sp <= stack_page + THREAD_SIZE - nbytes) | ||
841 | return 1; | ||
842 | } | ||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | #else | ||
847 | #define valid_irq_stack(sp, p, nb) 0 | ||
848 | #endif /* CONFIG_IRQSTACKS */ | ||
849 | |||
821 | int validate_sp(unsigned long sp, struct task_struct *p, | 850 | int validate_sp(unsigned long sp, struct task_struct *p, |
822 | unsigned long nbytes) | 851 | unsigned long nbytes) |
823 | { | 852 | { |
@@ -827,19 +856,7 @@ int validate_sp(unsigned long sp, struct task_struct *p, | |||
827 | && sp <= stack_page + THREAD_SIZE - nbytes) | 856 | && sp <= stack_page + THREAD_SIZE - nbytes) |
828 | return 1; | 857 | return 1; |
829 | 858 | ||
830 | #ifdef CONFIG_IRQSTACKS | 859 | return valid_irq_stack(sp, p, nbytes); |
831 | stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; | ||
832 | if (sp >= stack_page + sizeof(struct thread_struct) | ||
833 | && sp <= stack_page + THREAD_SIZE - nbytes) | ||
834 | return 1; | ||
835 | |||
836 | stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; | ||
837 | if (sp >= stack_page + sizeof(struct thread_struct) | ||
838 | && sp <= stack_page + THREAD_SIZE - nbytes) | ||
839 | return 1; | ||
840 | #endif | ||
841 | |||
842 | return 0; | ||
843 | } | 860 | } |
844 | 861 | ||
845 | #ifdef CONFIG_PPC64 | 862 | #ifdef CONFIG_PPC64 |