diff options
Diffstat (limited to 'kernel/trace/trace_event_perf.c')
| -rw-r--r-- | kernel/trace/trace_event_perf.c | 35 | 
1 files changed, 29 insertions, 6 deletions
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 80c36bcf66e..5d12bb407b4 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -24,10 +24,32 @@ static int	total_ref_count;  static int perf_trace_event_perm(struct ftrace_event_call *tp_event,  				 struct perf_event *p_event)  { +	if (tp_event->perf_perm) { +		int ret = tp_event->perf_perm(tp_event, p_event); +		if (ret) +			return ret; +	} +  	/* The ftrace function trace is allowed only for root. */ -	if (ftrace_event_is_function(tp_event) && -	    perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) -		return -EPERM; +	if (ftrace_event_is_function(tp_event)) { +		if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) +			return -EPERM; + +		/* +		 * We don't allow user space callchains for  function trace +		 * event, due to issues with page faults while tracing page +		 * fault handler and its overall trickiness nature. +		 */ +		if (!p_event->attr.exclude_callchain_user) +			return -EINVAL; + +		/* +		 * Same reason to disable user stack dump as for user space +		 * callchains above. +		 */ +		if (p_event->attr.sample_type & PERF_SAMPLE_STACK_USER) +			return -EINVAL; +	}  	/* No tracing, just counting, so no obvious leak */  	if (!(p_event->attr.sample_type & PERF_SAMPLE_RAW)) @@ -173,7 +195,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,  int perf_trace_init(struct perf_event *p_event)  {  	struct ftrace_event_call *tp_event; -	int event_id = p_event->attr.config; +	u64 event_id = p_event->attr.config;  	int ret = -EINVAL;  	mutex_lock(&event_mutex); @@ -226,8 +248,8 @@ void perf_trace_del(struct perf_event *p_event, int flags)  	tp_event->class->reg(tp_event, TRACE_REG_PERF_DEL, p_event);  } -__kprobes void *perf_trace_buf_prepare(int size, unsigned short type, -				       struct pt_regs *regs, int *rctxp) +void *perf_trace_buf_prepare(int size, unsigned short type, +			     struct pt_regs *regs, int *rctxp)  {  	struct trace_entry *entry;  	unsigned long flags; @@ -259,6 +281,7 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,  	return raw_data;  }  EXPORT_SYMBOL_GPL(perf_trace_buf_prepare); +NOKPROBE_SYMBOL(perf_trace_buf_prepare);  #ifdef CONFIG_FUNCTION_TRACER  static void  | 
