mirror of
https://github.com/torvalds/linux.git
synced 2026-10-25 16:45:02 +01:00
perf/x86: Use scoped user access for the user callchain frames
The user callchain walkers read each two-word stack frame with __get_user(), after checking the frame with valid_user_frame(), which is just __access_ok(). They run with page faults disabled, since they can be called from NMI context. Read each frame inside a scoped_user_read_access() instead, which does the range check itself and needs only a single stac/clac pair for both loads. That leaves valid_user_frame() unused, so remove it. This is part of getting rid of __get_user() and __put_user() entirely. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
7941b97fdd
commit
0f697d307c
|
|
@ -2902,12 +2902,6 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
|
|||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
valid_user_frame(const void __user *fp, unsigned long size)
|
||||
{
|
||||
return __access_ok(fp, size);
|
||||
}
|
||||
|
||||
static unsigned long get_segment_base(unsigned int segment)
|
||||
{
|
||||
struct desc_struct *desc;
|
||||
|
|
@ -2971,17 +2965,15 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
|
|||
perf_callchain_store(entry, ret_addr);
|
||||
|
||||
while (entry->nr < entry->max_stack) {
|
||||
if (!valid_user_frame(fp, sizeof(frame)))
|
||||
break;
|
||||
|
||||
if (__get_user(frame.next_frame, &fp->next_frame))
|
||||
break;
|
||||
if (__get_user(frame.return_address, &fp->return_address))
|
||||
break;
|
||||
scoped_user_read_access(fp, out) {
|
||||
unsafe_get_user(frame.next_frame, &fp->next_frame, out);
|
||||
unsafe_get_user(frame.return_address, &fp->return_address, out);
|
||||
}
|
||||
|
||||
perf_callchain_store(entry, cs_base + frame.return_address);
|
||||
fp = compat_ptr(ss_base + frame.next_frame);
|
||||
}
|
||||
out:
|
||||
pagefault_enable();
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -3036,17 +3028,15 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
|
|||
perf_callchain_store(entry, ret_addr);
|
||||
|
||||
while (entry->nr < entry->max_stack) {
|
||||
if (!valid_user_frame(fp, sizeof(frame)))
|
||||
break;
|
||||
|
||||
if (__get_user(frame.next_frame, &fp->next_frame))
|
||||
break;
|
||||
if (__get_user(frame.return_address, &fp->return_address))
|
||||
break;
|
||||
scoped_user_read_access(fp, out) {
|
||||
unsafe_get_user(frame.next_frame, &fp->next_frame, out);
|
||||
unsafe_get_user(frame.return_address, &fp->return_address, out);
|
||||
}
|
||||
|
||||
perf_callchain_store(entry, frame.return_address);
|
||||
fp = (void __user *)frame.next_frame;
|
||||
}
|
||||
out:
|
||||
pagefault_enable();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user