| From: Peter Zijlstra <peterz@infradead.org> |
| Date: Fri, 20 Apr 2018 14:06:29 +0200 |
| Subject: perf/x86: Fix possible Spectre-v1 indexing for hw_perf_event cache_* |
| |
| commit ef9ee4ad38445a30909c48998624861716f2a994 upstream. |
| |
| > arch/x86/events/core.c:319 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_event_ids[cache_type]' (local cap) |
| > arch/x86/events/core.c:319 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_event_ids' (local cap) |
| > arch/x86/events/core.c:328 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_extra_regs[cache_type]' (local cap) |
| > arch/x86/events/core.c:328 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_extra_regs' (local cap) |
| |
| Userspace controls @config which contains 3 (byte) fields used for a 3 |
| dimensional array deref. |
| |
| Reported-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> |
| Cc: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Cc: Jiri Olsa <jolsa@redhat.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Stephane Eranian <eranian@google.com> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Vince Weaver <vincent.weaver@maine.edu> |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| [bwh: Backported to 3.16: adjust filename] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| arch/x86/kernel/cpu/perf_event.c | 5 ++++- |
| 1 file changed, 4 insertions(+), 1 deletion(-) |
| |
| --- a/arch/x86/kernel/cpu/perf_event.c |
| +++ b/arch/x86/kernel/cpu/perf_event.c |
| @@ -274,17 +274,20 @@ set_ext_hw_attr(struct hw_perf_event *hw |
| |
| config = attr->config; |
| |
| - cache_type = (config >> 0) & 0xff; |
| + cache_type = (config >> 0) & 0xff; |
| if (cache_type >= PERF_COUNT_HW_CACHE_MAX) |
| return -EINVAL; |
| + cache_type = array_index_nospec(cache_type, PERF_COUNT_HW_CACHE_MAX); |
| |
| cache_op = (config >> 8) & 0xff; |
| if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) |
| return -EINVAL; |
| + cache_op = array_index_nospec(cache_op, PERF_COUNT_HW_CACHE_OP_MAX); |
| |
| cache_result = (config >> 16) & 0xff; |
| if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) |
| return -EINVAL; |
| + cache_result = array_index_nospec(cache_result, PERF_COUNT_HW_CACHE_RESULT_MAX); |
| |
| val = hw_cache_event_ids[cache_type][cache_op][cache_result]; |
| |