diff options
Diffstat (limited to 'arch/powerpc/kernel/process.c')
| -rw-r--r-- | arch/powerpc/kernel/process.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index fb7049c054c0..eac064948780 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -33,7 +33,10 @@ | |||
| 33 | #include <linux/mqueue.h> | 33 | #include <linux/mqueue.h> |
| 34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
| 35 | #include <linux/utsname.h> | 35 | #include <linux/utsname.h> |
| 36 | #include <linux/ftrace.h> | ||
| 36 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
| 38 | #include <linux/personality.h> | ||
| 39 | #include <linux/random.h> | ||
| 37 | 40 | ||
| 38 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
| 39 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
| @@ -1008,6 +1011,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
| 1008 | unsigned long sp, ip, lr, newsp; | 1011 | unsigned long sp, ip, lr, newsp; |
| 1009 | int count = 0; | 1012 | int count = 0; |
| 1010 | int firstframe = 1; | 1013 | int firstframe = 1; |
| 1014 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 1015 | int curr_frame = current->curr_ret_stack; | ||
| 1016 | extern void return_to_handler(void); | ||
| 1017 | unsigned long addr = (unsigned long)return_to_handler; | ||
| 1018 | #ifdef CONFIG_PPC64 | ||
| 1019 | addr = *(unsigned long*)addr; | ||
| 1020 | #endif | ||
| 1021 | #endif | ||
| 1011 | 1022 | ||
| 1012 | sp = (unsigned long) stack; | 1023 | sp = (unsigned long) stack; |
| 1013 | if (tsk == NULL) | 1024 | if (tsk == NULL) |
| @@ -1030,6 +1041,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
| 1030 | ip = stack[STACK_FRAME_LR_SAVE]; | 1041 | ip = stack[STACK_FRAME_LR_SAVE]; |
| 1031 | if (!firstframe || ip != lr) { | 1042 | if (!firstframe || ip != lr) { |
| 1032 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); | 1043 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); |
| 1044 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 1045 | if (ip == addr && curr_frame >= 0) { | ||
| 1046 | printk(" (%pS)", | ||
| 1047 | (void *)current->ret_stack[curr_frame].ret); | ||
| 1048 | curr_frame--; | ||
| 1049 | } | ||
| 1050 | #endif | ||
| 1033 | if (firstframe) | 1051 | if (firstframe) |
| 1034 | printk(" (unreliable)"); | 1052 | printk(" (unreliable)"); |
| 1035 | printk("\n"); | 1053 | printk("\n"); |
| @@ -1122,3 +1140,43 @@ void thread_info_cache_init(void) | |||
| 1122 | } | 1140 | } |
| 1123 | 1141 | ||
| 1124 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | 1142 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ |
| 1143 | |||
| 1144 | unsigned long arch_align_stack(unsigned long sp) | ||
| 1145 | { | ||
| 1146 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
| 1147 | sp -= get_random_int() & ~PAGE_MASK; | ||
| 1148 | return sp & ~0xf; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | static inline unsigned long brk_rnd(void) | ||
| 1152 | { | ||
| 1153 | unsigned long rnd = 0; | ||
| 1154 | |||
| 1155 | /* 8MB for 32bit, 1GB for 64bit */ | ||
| 1156 | if (is_32bit_task()) | ||
| 1157 | rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT))); | ||
| 1158 | else | ||
| 1159 | rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT))); | ||
| 1160 | |||
| 1161 | return rnd << PAGE_SHIFT; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | unsigned long arch_randomize_brk(struct mm_struct *mm) | ||
| 1165 | { | ||
| 1166 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | ||
| 1167 | |||
| 1168 | if (ret < mm->brk) | ||
| 1169 | return mm->brk; | ||
| 1170 | |||
| 1171 | return ret; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | unsigned long randomize_et_dyn(unsigned long base) | ||
| 1175 | { | ||
| 1176 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | ||
| 1177 | |||
| 1178 | if (ret < base) | ||
| 1179 | return base; | ||
| 1180 | |||
| 1181 | return ret; | ||
| 1182 | } | ||
