aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_sysprof.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
index 7f6fcccffb88..f9a09fe705b0 100644
--- a/kernel/trace/trace_sysprof.c
+++ b/kernel/trace/trace_sysprof.c
@@ -37,21 +37,26 @@ struct stack_frame {
37 37
38static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) 38static int copy_stack_frame(const void __user *fp, struct stack_frame *frame)
39{ 39{
40 int ret;
41
40 if (!access_ok(VERIFY_READ, fp, sizeof(*frame))) 42 if (!access_ok(VERIFY_READ, fp, sizeof(*frame)))
41 return 0; 43 return 0;
42 44
43 if (__copy_from_user_inatomic(frame, frame_pointer, sizeof(*frame))) 45 ret = 1;
44 return 0; 46 pagefault_disable();
47 if (__copy_from_user_inatomic(frame, fp, sizeof(*frame)))
48 ret = 0;
49 pagefault_enable();
45 50
46 return 1; 51 return ret;
47} 52}
48 53
49static void timer_notify(struct pt_regs *regs, int cpu) 54static void timer_notify(struct pt_regs *regs, int cpu)
50{ 55{
51 const void __user *frame_pointer;
52 struct trace_array_cpu *data; 56 struct trace_array_cpu *data;
53 struct stack_frame frame; 57 struct stack_frame frame;
54 struct trace_array *tr; 58 struct trace_array *tr;
59 const void __user *fp;
55 int is_user; 60 int is_user;
56 int i; 61 int i;
57 62
@@ -77,21 +82,26 @@ static void timer_notify(struct pt_regs *regs, int cpu)
77 82
78 trace_special(tr, data, 0, current->pid, regs->ip); 83 trace_special(tr, data, 0, current->pid, regs->ip);
79 84
80 frame_pointer = (void __user *)regs->bp; 85 fp = (void __user *)regs->bp;
81 86
82 for (i = 0; i < sample_max_depth; i++) { 87 for (i = 0; i < sample_max_depth; i++) {
83 if (!copy_stack_frame(frame_pointer, &frame)) 88 frame.next_fp = 0;
89 frame.return_address = 0;
90 if (!copy_stack_frame(fp, &frame))
84 break; 91 break;
85 if ((unsigned long)frame_pointer < regs->sp) 92 if ((unsigned long)fp < regs->sp)
86 break; 93 break;
87 94
88 trace_special(tr, data, 1, frame.return_address, 95 trace_special(tr, data, 1, frame.return_address,
89 (unsigned long)frame_pointer); 96 (unsigned long)fp);
90 frame_pointer = frame.next_fp; 97 fp = frame.next_fp;
91 } 98 }
92 99
93 trace_special(tr, data, 2, current->pid, i); 100 trace_special(tr, data, 2, current->pid, i);
94 101
102 /*
103 * Special trace entry if we overflow the max depth:
104 */
95 if (i == sample_max_depth) 105 if (i == sample_max_depth)
96 trace_special(tr, data, -1, -1, -1); 106 trace_special(tr, data, -1, -1, -1);
97} 107}