|
@@ -2250,12 +2250,19 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
|
|
ss_base = get_segment_base(regs->ss);
|
|
ss_base = get_segment_base(regs->ss);
|
|
|
|
|
|
fp = compat_ptr(ss_base + regs->bp);
|
|
fp = compat_ptr(ss_base + regs->bp);
|
|
|
|
+ pagefault_disable();
|
|
while (entry->nr < PERF_MAX_STACK_DEPTH) {
|
|
while (entry->nr < PERF_MAX_STACK_DEPTH) {
|
|
unsigned long bytes;
|
|
unsigned long bytes;
|
|
frame.next_frame = 0;
|
|
frame.next_frame = 0;
|
|
frame.return_address = 0;
|
|
frame.return_address = 0;
|
|
|
|
|
|
- bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
|
|
|
|
|
|
+ if (!access_ok(VERIFY_READ, fp, 8))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4);
|
|
|
|
+ if (bytes != 0)
|
|
|
|
+ break;
|
|
|
|
+ bytes = __copy_from_user_nmi(&frame.return_address, fp+4, 4);
|
|
if (bytes != 0)
|
|
if (bytes != 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -2265,6 +2272,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
|
|
perf_callchain_store(entry, cs_base + frame.return_address);
|
|
perf_callchain_store(entry, cs_base + frame.return_address);
|
|
fp = compat_ptr(ss_base + frame.next_frame);
|
|
fp = compat_ptr(ss_base + frame.next_frame);
|
|
}
|
|
}
|
|
|
|
+ pagefault_enable();
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
#else
|
|
#else
|
|
@@ -2302,12 +2310,19 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
|
|
if (perf_callchain_user32(regs, entry))
|
|
if (perf_callchain_user32(regs, entry))
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ pagefault_disable();
|
|
while (entry->nr < PERF_MAX_STACK_DEPTH) {
|
|
while (entry->nr < PERF_MAX_STACK_DEPTH) {
|
|
unsigned long bytes;
|
|
unsigned long bytes;
|
|
frame.next_frame = NULL;
|
|
frame.next_frame = NULL;
|
|
frame.return_address = 0;
|
|
frame.return_address = 0;
|
|
|
|
|
|
- bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
|
|
|
|
|
|
+ if (!access_ok(VERIFY_READ, fp, 16))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
|
|
|
|
+ if (bytes != 0)
|
|
|
|
+ break;
|
|
|
|
+ bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
|
|
if (bytes != 0)
|
|
if (bytes != 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -2315,8 +2330,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
|
|
break;
|
|
break;
|
|
|
|
|
|
perf_callchain_store(entry, frame.return_address);
|
|
perf_callchain_store(entry, frame.return_address);
|
|
- fp = frame.next_frame;
|
|
|
|
|
|
+ fp = (void __user *)frame.next_frame;
|
|
}
|
|
}
|
|
|
|
+ pagefault_enable();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|