projects
/
cascardo
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
x86: Remove arbitrary instruction size limit in instruction decoder
[cascardo/linux.git]
/
arch
/
x86
/
kernel
/
cpu
/
perf_event_intel_ds.c
diff --git
a/arch/x86/kernel/cpu/perf_event_intel_ds.c
b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index
46211bc
..
6a94277
100644
(file)
--- a/
arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/
arch/x86/kernel/cpu/perf_event_intel_ds.c
@@
-724,6
+724,7
@@
static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
unsigned long ip = regs->ip;
int is_64bit = 0;
void *kaddr;
unsigned long ip = regs->ip;
int is_64bit = 0;
void *kaddr;
+ int size;
/*
* We don't need to fixup if the PEBS assist is fault like
/*
* We don't need to fixup if the PEBS assist is fault like
@@
-758,11
+759,12
@@
static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
return 1;
}
return 1;
}
+ size = ip - to;
if (!kernel_ip(ip)) {
if (!kernel_ip(ip)) {
- int
size,
bytes;
+ int bytes;
u8 *buf = this_cpu_read(insn_buffer);
u8 *buf = this_cpu_read(insn_buffer);
-
size = ip - to; /* M
ust fit our buffer, see above */
+
/* 'size' m
ust fit our buffer, see above */
bytes = copy_from_user_nmi(buf, (void __user *)to, size);
if (bytes != 0)
return 0;
bytes = copy_from_user_nmi(buf, (void __user *)to, size);
if (bytes != 0)
return 0;
@@
-780,11
+782,20
@@
static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
#ifdef CONFIG_X86_64
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
#endif
#ifdef CONFIG_X86_64
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
#endif
- insn_init(&insn, kaddr, is_64bit);
+ insn_init(&insn, kaddr,
size,
is_64bit);
insn_get_length(&insn);
insn_get_length(&insn);
+ /*
+ * Make sure there was not a problem decoding the
+ * instruction and getting the length. This is
+ * doubly important because we have an infinite
+ * loop if insn.length=0.
+ */
+ if (!insn.length)
+ break;
to += insn.length;
kaddr += insn.length;
to += insn.length;
kaddr += insn.length;
+ size -= insn.length;
} while (to < ip);
if (to == ip) {
} while (to < ip);
if (to == ip) {