On Wed, Jan 30, 2019 at 07:36:48PM +0100, Jiri Olsa wrote:
> On Fri, Jan 25, 2019 at 12:16:27PM +0530, Ravi Bangoria wrote:
> 
> SNIP
> 
> > [ 1432.176374] general protection fault: 0000 [#1] SMP PTI         
> > [ 1432.182253] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G        W         
> > 5.0.0-rc3-ravi-pfuzzer+ #1                                                  
> >                             
> > [ 1432.192088] Hardware name: IBM CPU PLANAR                                
> >            -[8722xyz]-/00FL808, BIOS -[KOE162DUS-2.30]- 08/27/2018          
> >                 [264/488]
> > [ 1432.206120] RIP: 0010:perf_prepare_sample+0x8f/0x510                     
> >          
> > [ 1432.211679] Code: ff ff 41 f6 c4 01 0f 85 22 02 00 00 41 f6 c4 20 74 26 
> > 4d 85 e4 0f 88 0c 01 00 00 4c 89 f6 4c 89 ff e8 f5 fe ff ff 49 89 45 70 
> > <48> 8b 00 8d 04 c5 08 00 00 0
> > 0 66 01 43 06 41 f7 c4 00 04 00 00 74                                       
> >     
> > [ 1432.232699] RSP: 0000:ffff95b3ff843a78 EFLAGS: 00010082                  
> >          
> > [ 1432.238548] RAX: 8d1217eb826cce00 RBX: ffff95b3ff843ad8 RCX: 
> > 000000000000001f
> > [ 1432.246536] RDX: 0000000000000000 RSI: 00000000355563e5 RDI: 
> > 0000000000000000
> > [ 1432.254522] RBP: ffff95b3ff843ab0 R08: ffffd016493f3b42 R09: 
> > 0000000000000000
> > [ 1432.262508] R10: ffff95b3ff843a08 R11: 0000000000000000 R12: 
> > 80000000000306e5
> > [ 1432.270495] R13: ffff95b3ff843bc0 R14: ffff95b3ff843b18 R15: 
> > ffff95b3f6b65800                                                            
> >                                      
> > [ 1432.278483] FS:  0000000000000000(0000) GS:ffff95b3ff840000(0000) 
> > knlGS:0000000000000000
> > [ 1432.287539] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > [ 1432.293969] CR2: 000055bf7f768c90 CR3: 0000001fd220e005 CR4: 
> > 00000000000606e0
> > [ 1432.301956] Call Trace:                                                  
> >     
> > [ 1432.304697]  <IRQ>                                                       
> >                                                                             
> >                          
> > [ 1432.306956]  ? intel_pmu_drain_bts_buffer+0x194/0x230                    
> >                                                                             
> >                          
> > [ 1432.312615]  intel_pmu_drain_bts_buffer+0x160/0x230                      
> >                                                                             
> >                          
> > [ 1432.318078]  ? tick_nohz_irq_exit+0x31/0x40                              
> >                                                                             
> >                          
> > [ 1432.322765]  ? smp_call_function_single_interrupt+0x48/0xe0
> > [ 1432.328993]  ? call_function_single_interrupt+0xf/0x20    
> > [ 1432.334745]  ? call_function_single_interrupt+0xa/0x20                   
> >                            
> > [ 1432.340501]  ? x86_schedule_events+0x1a0/0x2f0                           
> >                                                                             
> >                          
> > [ 1432.345475]  ? x86_pmu_commit_txn+0xb4/0x100                             
> >                                                                             
> >                          
> > [ 1432.350258]  ? find_busiest_group+0x47/0x5d0                             
> >                                                                             
> >                          
> > [ 1432.355039]  ? perf_event_set_state.part.42+0x12/0x50                    
> >                                                                             
> >                          
> > [ 1432.360694]  ? perf_mux_hrtimer_restart+0x40/0xb0                        
> >     
> > [ 1432.365960]  intel_pmu_disable_event+0xae/0x100                          
> >                        
> > [ 1432.371031]  ? intel_pmu_disable_event+0xae/0x100                        
> >                                                                   
> > [ 1432.376297]  x86_pmu_stop+0x7a/0xb0                                      
> >     
> > [ 1432.380201]  x86_pmu_del+0x57/0x120                                      
> >                                                                             
> >                          
> > [ 1432.384105]  event_sched_out.isra.101+0x83/0x180             
> > [ 1432.389272]  group_sched_out.part.103+0x57/0xe0                          
> >     
> > [ 1432.394343]  ctx_sched_out+0x188/0x240                                   
> >     
> > [ 1432.398539]  ctx_resched+0xa8/0xd0                                       
> >                                              
> > [ 1432.402345]  __perf_event_enable+0x193/0x1e0                             
> >          
> > [ 1432.407125]  event_function+0x8e/0xc0                                    
> >     
> > [ 1432.411222]  remote_function+0x41/0x50                                   
> >                                                                             
> >                          
> > [ 1432.415418]  flush_smp_call_function_queue+0x68/0x100                    
> >                            
> > [ 1432.421071]  generic_smp_call_function_single_interrupt+0x13/0x30        
> >                                                                             
> >                          
> > [ 1432.427893]  smp_call_function_single_interrupt+0x3e/0xe0                
> >                                                                             
> >                          
> > [ 1432.433936]  call_function_single_interrupt+0xf/0x20                     
> >                                                                             
> >                          
> > [ 1432.440204]  </IRQ>                                                      
> >                                                                             
> >                          
> 
> hi,
> I finaly managed to reproduced this one ;-)

ugh.. and fuzzer managed to reproduce it again even with the patch below :-\
there's some other way the event could become bts with callchain

jirka

> 
> also I found reproducer for crash on my server, now I'm running
> the fuzzer to see if it cures it as well.. so far so good ;-)
> 
> the crash happens when I create 'almost bts' event with:
>   event = branch-instructions:up
>   sample_period = 2
>   sample_type = CALLCHAIN
> 
> after I open the event I change the sample_period via ioctl to '1',
> which will make the event 'full bts', but no bts checks are performed
> so the bts drain crashes
> 
> the patch adds check_eriod pmu callback.. I need to check if there's
> better way to do this, but so far it fixes the crash for me
> 
> if you guys could check this patch, that'd be great
> 
> thanks,
> jirka
> 
> 
> ---
>  arch/x86/events/core.c       |  6 ++++++
>  arch/x86/events/intel/core.c |  9 +++++++++
>  arch/x86/events/perf_event.h |  2 ++
>  include/linux/perf_event.h   |  5 +++++
>  kernel/events/core.c         | 31 +++++++++++++++++++++++++++++++
>  5 files changed, 53 insertions(+)
> 
> diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
> index 374a19712e20..e5db4fad517e 100644
> --- a/arch/x86/events/core.c
> +++ b/arch/x86/events/core.c
> @@ -2278,6 +2278,11 @@ void perf_check_microcode(void)
>               x86_pmu.check_microcode();
>  }
>  
> +static int x86_pmu_check_period(struct perf_event *event)
> +{
> +     return x86_pmu.check_period ? x86_pmu.check_period(event) : 0;
> +}
> +
>  static struct pmu pmu = {
>       .pmu_enable             = x86_pmu_enable,
>       .pmu_disable            = x86_pmu_disable,
> @@ -2302,6 +2307,7 @@ static struct pmu pmu = {
>       .event_idx              = x86_pmu_event_idx,
>       .sched_task             = x86_pmu_sched_task,
>       .task_ctx_size          = sizeof(struct x86_perf_task_context),
> +     .check_period           = x86_pmu_check_period,
>  };
>  
>  void arch_perf_update_userpage(struct perf_event *event,
> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
> index 40e12cfc87f6..125930e328c8 100644
> --- a/arch/x86/events/intel/core.c
> +++ b/arch/x86/events/intel/core.c
> @@ -3584,6 +3584,11 @@ static void intel_pmu_sched_task(struct 
> perf_event_context *ctx,
>       intel_pmu_lbr_sched_task(ctx, sched_in);
>  }
>  
> +static int intel_pmu_check_period(struct perf_event *event)
> +{
> +     return intel_pmu_has_bts(event) ? -EINVAL : 0;
> +}
> +
>  PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
>  
>  PMU_FORMAT_ATTR(ldlat, "config1:0-15");
> @@ -3663,6 +3668,8 @@ static __initconst const struct x86_pmu core_pmu = {
>       .cpu_prepare            = intel_pmu_cpu_prepare,
>       .cpu_starting           = intel_pmu_cpu_starting,
>       .cpu_dying              = intel_pmu_cpu_dying,
> +
> +     .check_period           = intel_pmu_check_period,
>  };
>  
>  static struct attribute *intel_pmu_attrs[];
> @@ -3705,6 +3712,8 @@ static __initconst const struct x86_pmu intel_pmu = {
>       .cpu_dying              = intel_pmu_cpu_dying,
>       .guest_get_msrs         = intel_guest_get_msrs,
>       .sched_task             = intel_pmu_sched_task,
> +
> +     .check_period           = intel_pmu_check_period,
>  };
>  
>  static __init void intel_clovertown_quirk(void)
> diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
> index 78d7b7031bfc..170b58d48710 100644
> --- a/arch/x86/events/perf_event.h
> +++ b/arch/x86/events/perf_event.h
> @@ -646,6 +646,8 @@ struct x86_pmu {
>        * Intel host/guest support (KVM)
>        */
>       struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
> +
> +     int (*check_period) (struct perf_event *event);
>  };
>  
>  struct x86_perf_task_context {
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index a79e59fc3b7d..749a5c3110e2 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -447,6 +447,11 @@ struct pmu {
>        * Filter events for PMU-specific reasons.
>        */
>       int (*filter_match)             (struct perf_event *event); /* optional 
> */
> +
> +     /*
> +      * Check period for PERF_EVENT_IOC_PERIOD ioctl.
> +      */
> +     int (*check_period)             (struct perf_event *event); /* optional 
> */
>  };
>  
>  enum perf_addr_filter_action_t {
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 280a72b3a553..22ec63a0782e 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -4969,6 +4969,26 @@ static void __perf_event_period(struct perf_event 
> *event,
>       }
>  }
>  
> +static int check_period(struct perf_event *event, u64 value)
> +{
> +     u64 sample_period_attr = event->attr.sample_period;
> +     u64 sample_period_hw   = event->hw.sample_period;
> +     int ret;
> +
> +     if (event->attr.freq) {
> +             event->attr.sample_freq = value;
> +     } else {
> +             event->attr.sample_period = value;
> +             event->hw.sample_period = value;
> +     }
> +
> +     ret = event->pmu->check_period(event);
> +
> +     event->attr.sample_period = sample_period_attr;
> +     event->hw.sample_period   = sample_period_hw;
> +     return ret;
> +}
> +
>  static int perf_event_period(struct perf_event *event, u64 __user *arg)
>  {
>       u64 value;
> @@ -4985,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, 
> u64 __user *arg)
>       if (event->attr.freq && value > sysctl_perf_event_sample_rate)
>               return -EINVAL;
>  
> +     if (check_period(event, value))
> +             return -EINVAL;
> +
>       event_function_call(event, __perf_event_period, &value);
>  
>       return 0;
> @@ -9601,6 +9624,11 @@ static int perf_pmu_nop_int(struct pmu *pmu)
>       return 0;
>  }
>  
> +static int perf_event_nop_int(struct perf_event *event)
> +{
> +     return 0;
> +}
> +
>  static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
>  
>  static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
> @@ -9901,6 +9929,9 @@ int perf_pmu_register(struct pmu *pmu, const char 
> *name, int type)
>               pmu->pmu_disable = perf_pmu_nop_void;
>       }
>  
> +     if (!pmu->check_period)
> +             pmu->check_period = perf_event_nop_int;
> +
>       if (!pmu->event_idx)
>               pmu->event_idx = perf_event_idx_default;
>  
> -- 
> 2.17.2
> 

Reply via email to