diff mbox series

perf/core: Fix possible Spectre-v1 for perf_swevent_enabled

Message ID 20180731142557.GA12460@pjb1027-Latitude-E5410 (mailing list archive)
State New, archived
Headers show
Series perf/core: Fix possible Spectre-v1 for perf_swevent_enabled | expand

Commit Message

Jinbum Park July 31, 2018, 2:25 p.m. UTC
User controls @event_id which to be used as index of perf_swevent_enabled.
So, It can be exploited via Spectre-like attack. (speculative execution)

So sanitize @event_id before using it to prevent attack.

I leveraged strategy [1] to find this gadget.

[1] https://github.com/jinb-park/linux-exploit/
tree/master/exploit-remaining-spectre-gadget/

Signed-off-by: Jinbum Park <jinb.park7@gmail.com>
---
 kernel/events/core.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

kernel test robot July 31, 2018, 4:29 p.m. UTC | #1
Hi Jinbum,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tip/perf/core]
[also build test ERROR on v4.18-rc7 next-20180727]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jinbum-Park/perf-core-Fix-possible-Spectre-v1-for-perf_swevent_enabled/20180731-235311
config: i386-randconfig-x077-201830 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   Cyclomatic Complexity 11 kernel//events/core.c:perf_event_read_local
   Cyclomatic Complexity 4 kernel//events/core.c:perf_event_task_enable
   Cyclomatic Complexity 4 kernel//events/core.c:perf_event_task_disable
   Cyclomatic Complexity 1 kernel//events/core.c:arch_perf_update_userpage
   Cyclomatic Complexity 6 kernel//events/core.c:perf_event_update_userpage
   Cyclomatic Complexity 3 kernel//events/core.c:__perf_event_sync_stat
   Cyclomatic Complexity 8 kernel//events/core.c:perf_event_sync_stat
   Cyclomatic Complexity 15 kernel//events/core.c:perf_event_context_sched_out
   Cyclomatic Complexity 5 kernel//events/core.c:__perf_event_task_sched_out
   Cyclomatic Complexity 1 kernel//events/core.c:_perf_event_reset
   Cyclomatic Complexity 2 kernel//events/core.c:task_clock_event_add
   Cyclomatic Complexity 2 kernel//events/core.c:cpu_clock_event_add
   Cyclomatic Complexity 6 kernel//events/core.c:ring_buffer_get
   Cyclomatic Complexity 3 kernel//events/core.c:ring_buffer_put
   Cyclomatic Complexity 8 kernel//events/core.c:ring_buffer_attach
   Cyclomatic Complexity 8 kernel//events/core.c:_free_event
   Cyclomatic Complexity 3 kernel//events/core.c:free_event
   Cyclomatic Complexity 9 kernel//events/core.c:perf_event_create_kernel_counter
   Cyclomatic Complexity 10 kernel//events/core.c:inherit_event
   Cyclomatic Complexity 7 kernel//events/core.c:inherit_group
   Cyclomatic Complexity 5 kernel//events/core.c:inherit_task_group
   Cyclomatic Complexity 18 kernel//events/core.c:perf_event_init_context
   Cyclomatic Complexity 2 kernel//events/core.c:put_event
   Cyclomatic Complexity 14 kernel//events/core.c:perf_event_release_kernel
   Cyclomatic Complexity 1 kernel//events/core.c:perf_release
   Cyclomatic Complexity 3 kernel//events/core.c:perf_free_event
   Cyclomatic Complexity 44 kernel//events/core.c:perf_mmap
   Cyclomatic Complexity 14 kernel//events/core.c:perf_event_set_output
   Cyclomatic Complexity 84 kernel//events/core.c:__do_sys_perf_event_open
   Cyclomatic Complexity 1 kernel//events/core.c:__se_sys_perf_event_open
   Cyclomatic Complexity 23 kernel//events/core.c:_perf_ioctl
   Cyclomatic Complexity 1 kernel//events/core.c:perf_ioctl
   Cyclomatic Complexity 13 kernel//events/core.c:perf_mmap_close
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_wakeup
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_header__init_id
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event__output_id_sample
   Cyclomatic Complexity 3 kernel//events/core.c:perf_log_throttle
   Cyclomatic Complexity 12 kernel//events/core.c:perf_adjust_freq_unthr_context
   Cyclomatic Complexity 11 kernel//events/core.c:perf_event_task_tick
   Cyclomatic Complexity 6 kernel//events/core.c:__perf_event_account_interrupt
   Cyclomatic Complexity 6 kernel//events/core.c:__perf_event_overflow
   Cyclomatic Complexity 8 kernel//events/core.c:perf_swevent_hrtimer
   Cyclomatic Complexity 5 kernel//events/core.c:__perf_event_period
   Cyclomatic Complexity 5 kernel//events/core.c:perf_log_itrace_start
   Cyclomatic Complexity 12 kernel//events/core.c:event_sched_in
   Cyclomatic Complexity 14 kernel//events/core.c:group_sched_in
   Cyclomatic Complexity 6 kernel//events/core.c:pinned_sched_in
   Cyclomatic Complexity 5 kernel//events/core.c:flexible_sched_in
   Cyclomatic Complexity 5 kernel//events/core.c:perf_event_switch_output
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_task_output
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_comm_output
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_namespaces_output
   Cyclomatic Complexity 5 kernel//events/core.c:perf_event_mmap_output
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_read_event
   Cyclomatic Complexity 2 kernel//events/core.c:sync_child_event
   Cyclomatic Complexity 5 kernel//events/core.c:perf_event_exit_event
   Cyclomatic Complexity 8 kernel//events/core.c:perf_event_exit_task_context
   Cyclomatic Complexity 31 kernel//events/core.c:perf_output_sample
   Cyclomatic Complexity 5 kernel//events/core.c:perf_callchain
   Cyclomatic Complexity 19 kernel//events/core.c:perf_prepare_sample
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_output
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_exec
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_comm
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_namespaces
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_fork
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_mmap
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_aux_event
   Cyclomatic Complexity 2 kernel//events/core.c:perf_log_lost_samples
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_itrace_started
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_account_interrupt
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_overflow
   Cyclomatic Complexity 3 kernel//events/core.c:perf_swevent_set_period
   Cyclomatic Complexity 5 kernel//events/core.c:perf_swevent_overflow
   Cyclomatic Complexity 9 kernel//events/core.c:perf_swevent_event
   Cyclomatic Complexity 8 kernel//events/core.c:do_perf_sw_event
   Cyclomatic Complexity 4 kernel//events/core.c:perf_swevent_add
   Cyclomatic Complexity 1 kernel//events/core.c:perf_swevent_put_recursion_context
   Cyclomatic Complexity 5 kernel//events/core.c:perf_pending_event
   Cyclomatic Complexity 3 kernel//events/core.c:___perf_sw_event
   Cyclomatic Complexity 2 kernel//events/core.c:__perf_sw_event
   Cyclomatic Complexity 3 kernel//events/core.c:perf_bp_event
   Cyclomatic Complexity 7 kernel//events/core.c:perf_event_exit_task
   Cyclomatic Complexity 7 kernel//events/core.c:perf_event_free_task
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_delayed_put
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_get
   Cyclomatic Complexity 2 kernel//events/core.c:perf_get_event
   Cyclomatic Complexity 2 kernel//events/core.c:perf_event_attrs
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_init_task
   Cyclomatic Complexity 5 kernel//events/core.c:perf_swevent_init_cpu
   Cyclomatic Complexity 4 kernel//events/core.c:perf_event_init_cpu
   Cyclomatic Complexity 1 kernel//events/core.c:perf_event_exit_cpu
   Cyclomatic Complexity 2 kernel//events/core.c:perf_reboot
   Cyclomatic Complexity 3 kernel//events/core.c:perf_event_init
   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from kernel//events/core.c:12:
   kernel//events/core.c: In function 'perf_swevent_init':
>> include/linux/compiler.h:339:38: error: call to '__compiletime_assert_8204' declared with attribute error: BUILD_BUG_ON failed: sizeof(_s) > sizeof(long)
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
                                         ^
   include/linux/compiler.h:319:4: note: in definition of macro '__compiletime_assert'
       prefix ## suffix();    \
       ^~~~~~
   include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert'
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
     ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert'
    #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                        ^~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:69:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
     BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
     ^~~~~~~~~~~~~~~~
>> include/linux/nospec.h:55:2: note: in expansion of macro 'BUILD_BUG_ON'
     BUILD_BUG_ON(sizeof(_i) > sizeof(long));   \
     ^~~~~~~~~~~~
>> kernel//events/core.c:8204:14: note: in expansion of macro 'array_index_nospec'
      event_id = array_index_nospec(event_id, PERF_COUNT_SW_MAX);
                 ^~~~~~~~~~~~~~~~~~
--
   Cyclomatic Complexity 11 kernel/events/core.c:perf_event_read_local
   Cyclomatic Complexity 4 kernel/events/core.c:perf_event_task_enable
   Cyclomatic Complexity 4 kernel/events/core.c:perf_event_task_disable
   Cyclomatic Complexity 1 kernel/events/core.c:arch_perf_update_userpage
   Cyclomatic Complexity 6 kernel/events/core.c:perf_event_update_userpage
   Cyclomatic Complexity 3 kernel/events/core.c:__perf_event_sync_stat
   Cyclomatic Complexity 8 kernel/events/core.c:perf_event_sync_stat
   Cyclomatic Complexity 15 kernel/events/core.c:perf_event_context_sched_out
   Cyclomatic Complexity 5 kernel/events/core.c:__perf_event_task_sched_out
   Cyclomatic Complexity 1 kernel/events/core.c:_perf_event_reset
   Cyclomatic Complexity 2 kernel/events/core.c:task_clock_event_add
   Cyclomatic Complexity 2 kernel/events/core.c:cpu_clock_event_add
   Cyclomatic Complexity 6 kernel/events/core.c:ring_buffer_get
   Cyclomatic Complexity 3 kernel/events/core.c:ring_buffer_put
   Cyclomatic Complexity 8 kernel/events/core.c:ring_buffer_attach
   Cyclomatic Complexity 8 kernel/events/core.c:_free_event
   Cyclomatic Complexity 3 kernel/events/core.c:free_event
   Cyclomatic Complexity 9 kernel/events/core.c:perf_event_create_kernel_counter
   Cyclomatic Complexity 10 kernel/events/core.c:inherit_event
   Cyclomatic Complexity 7 kernel/events/core.c:inherit_group
   Cyclomatic Complexity 5 kernel/events/core.c:inherit_task_group
   Cyclomatic Complexity 18 kernel/events/core.c:perf_event_init_context
   Cyclomatic Complexity 2 kernel/events/core.c:put_event
   Cyclomatic Complexity 14 kernel/events/core.c:perf_event_release_kernel
   Cyclomatic Complexity 1 kernel/events/core.c:perf_release
   Cyclomatic Complexity 3 kernel/events/core.c:perf_free_event
   Cyclomatic Complexity 44 kernel/events/core.c:perf_mmap
   Cyclomatic Complexity 14 kernel/events/core.c:perf_event_set_output
   Cyclomatic Complexity 84 kernel/events/core.c:__do_sys_perf_event_open
   Cyclomatic Complexity 1 kernel/events/core.c:__se_sys_perf_event_open
   Cyclomatic Complexity 23 kernel/events/core.c:_perf_ioctl
   Cyclomatic Complexity 1 kernel/events/core.c:perf_ioctl
   Cyclomatic Complexity 13 kernel/events/core.c:perf_mmap_close
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_wakeup
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_header__init_id
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event__output_id_sample
   Cyclomatic Complexity 3 kernel/events/core.c:perf_log_throttle
   Cyclomatic Complexity 12 kernel/events/core.c:perf_adjust_freq_unthr_context
   Cyclomatic Complexity 11 kernel/events/core.c:perf_event_task_tick
   Cyclomatic Complexity 6 kernel/events/core.c:__perf_event_account_interrupt
   Cyclomatic Complexity 6 kernel/events/core.c:__perf_event_overflow
   Cyclomatic Complexity 8 kernel/events/core.c:perf_swevent_hrtimer
   Cyclomatic Complexity 5 kernel/events/core.c:__perf_event_period
   Cyclomatic Complexity 5 kernel/events/core.c:perf_log_itrace_start
   Cyclomatic Complexity 12 kernel/events/core.c:event_sched_in
   Cyclomatic Complexity 14 kernel/events/core.c:group_sched_in
   Cyclomatic Complexity 6 kernel/events/core.c:pinned_sched_in
   Cyclomatic Complexity 5 kernel/events/core.c:flexible_sched_in
   Cyclomatic Complexity 5 kernel/events/core.c:perf_event_switch_output
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_task_output
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_comm_output
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_namespaces_output
   Cyclomatic Complexity 5 kernel/events/core.c:perf_event_mmap_output
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_read_event
   Cyclomatic Complexity 2 kernel/events/core.c:sync_child_event
   Cyclomatic Complexity 5 kernel/events/core.c:perf_event_exit_event
   Cyclomatic Complexity 8 kernel/events/core.c:perf_event_exit_task_context
   Cyclomatic Complexity 31 kernel/events/core.c:perf_output_sample
   Cyclomatic Complexity 5 kernel/events/core.c:perf_callchain
   Cyclomatic Complexity 19 kernel/events/core.c:perf_prepare_sample
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_output
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_exec
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_comm
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_namespaces
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_fork
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_mmap
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_aux_event
   Cyclomatic Complexity 2 kernel/events/core.c:perf_log_lost_samples
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_itrace_started
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_account_interrupt
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_overflow
   Cyclomatic Complexity 3 kernel/events/core.c:perf_swevent_set_period
   Cyclomatic Complexity 5 kernel/events/core.c:perf_swevent_overflow
   Cyclomatic Complexity 9 kernel/events/core.c:perf_swevent_event
   Cyclomatic Complexity 8 kernel/events/core.c:do_perf_sw_event
   Cyclomatic Complexity 4 kernel/events/core.c:perf_swevent_add
   Cyclomatic Complexity 1 kernel/events/core.c:perf_swevent_put_recursion_context
   Cyclomatic Complexity 5 kernel/events/core.c:perf_pending_event
   Cyclomatic Complexity 3 kernel/events/core.c:___perf_sw_event
   Cyclomatic Complexity 2 kernel/events/core.c:__perf_sw_event
   Cyclomatic Complexity 3 kernel/events/core.c:perf_bp_event
   Cyclomatic Complexity 7 kernel/events/core.c:perf_event_exit_task
   Cyclomatic Complexity 7 kernel/events/core.c:perf_event_free_task
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_delayed_put
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_get
   Cyclomatic Complexity 2 kernel/events/core.c:perf_get_event
   Cyclomatic Complexity 2 kernel/events/core.c:perf_event_attrs
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_init_task
   Cyclomatic Complexity 5 kernel/events/core.c:perf_swevent_init_cpu
   Cyclomatic Complexity 4 kernel/events/core.c:perf_event_init_cpu
   Cyclomatic Complexity 1 kernel/events/core.c:perf_event_exit_cpu
   Cyclomatic Complexity 2 kernel/events/core.c:perf_reboot
   Cyclomatic Complexity 3 kernel/events/core.c:perf_event_init
   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:9,
                    from include/linux/wait.h:7,
                    from include/linux/wait_bit.h:8,
                    from include/linux/fs.h:6,
                    from kernel/events/core.c:12:
   kernel/events/core.c: In function 'perf_swevent_init':
>> include/linux/compiler.h:339:38: error: call to '__compiletime_assert_8204' declared with attribute error: BUILD_BUG_ON failed: sizeof(_s) > sizeof(long)
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
                                         ^
   include/linux/compiler.h:319:4: note: in definition of macro '__compiletime_assert'
       prefix ## suffix();    \
       ^~~~~~
   include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert'
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
     ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert'
    #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                        ^~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:69:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
     BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
     ^~~~~~~~~~~~~~~~
>> include/linux/nospec.h:55:2: note: in expansion of macro 'BUILD_BUG_ON'
     BUILD_BUG_ON(sizeof(_i) > sizeof(long));   \
     ^~~~~~~~~~~~
   kernel/events/core.c:8204:14: note: in expansion of macro 'array_index_nospec'
      event_id = array_index_nospec(event_id, PERF_COUNT_SW_MAX);
                 ^~~~~~~~~~~~~~~~~~

vim +/BUILD_BUG_ON +55 include/linux/nospec.h

8fa80c503 Will Deacon      2018-02-05  34  
8fa80c503 Will Deacon      2018-02-05  35  /*
f38042033 Dan Williams     2018-01-29  36   * array_index_nospec - sanitize an array index after a bounds check
f38042033 Dan Williams     2018-01-29  37   *
f38042033 Dan Williams     2018-01-29  38   * For a code sequence like:
f38042033 Dan Williams     2018-01-29  39   *
f38042033 Dan Williams     2018-01-29  40   *     if (index < size) {
f38042033 Dan Williams     2018-01-29  41   *         index = array_index_nospec(index, size);
f38042033 Dan Williams     2018-01-29  42   *         val = array[index];
f38042033 Dan Williams     2018-01-29  43   *     }
f38042033 Dan Williams     2018-01-29  44   *
f38042033 Dan Williams     2018-01-29  45   * ...if the CPU speculates past the bounds check then
f38042033 Dan Williams     2018-01-29  46   * array_index_nospec() will clamp the index within the range of [0,
f38042033 Dan Williams     2018-01-29  47   * size).
f38042033 Dan Williams     2018-01-29  48   */
f38042033 Dan Williams     2018-01-29  49  #define array_index_nospec(index, size)					\
f38042033 Dan Williams     2018-01-29  50  ({									\
f38042033 Dan Williams     2018-01-29  51  	typeof(index) _i = (index);					\
f38042033 Dan Williams     2018-01-29  52  	typeof(size) _s = (size);					\
1d91c1d2c Dan Williams     2018-02-16  53  	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
f38042033 Dan Williams     2018-01-29  54  									\
f38042033 Dan Williams     2018-01-29 @55  	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
f38042033 Dan Williams     2018-01-29  56  	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\
f38042033 Dan Williams     2018-01-29  57  									\
b98c6a160 Rasmus Villemoes 2018-02-16  58  	(typeof(_i)) (_i & _mask);					\
f38042033 Dan Williams     2018-01-29  59  })
b617cfc85 Thomas Gleixner  2018-04-29  60  

:::::: The code at line 55 was first introduced by commit
:::::: f3804203306e098dae9ca51540fcd5eb700d7f40 array_index_nospec: Sanitize speculative array de-references

:::::: TO: Dan Williams <dan.j.williams@intel.com>
:::::: CC: Thomas Gleixner <tglx@linutronix.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox series

Patch

diff --git a/kernel/events/core.c b/kernel/events/core.c
index f6ea33a..3313552 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -50,6 +50,7 @@ 
 #include <linux/sched/mm.h>
 #include <linux/proc_ns.h>
 #include <linux/mount.h>
+#include <linux/nospec.h>
 
 #include "internal.h"
 
@@ -8200,6 +8201,7 @@  static int perf_swevent_init(struct perf_event *event)
 		if (err)
 			return err;
 
+		event_id = array_index_nospec(event_id, PERF_COUNT_SW_MAX);
 		static_key_slow_inc(&perf_swevent_enabled[event_id]);
 		event->destroy = sw_perf_event_destroy;
 	}