diff options
Diffstat (limited to 'kernel/trace/trace_event_perf.c')
| -rw-r--r-- | kernel/trace/trace_event_perf.c | 31 | 
1 files changed, 30 insertions, 1 deletions
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 39c059ca670..19a359d5e6d 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -21,17 +21,46 @@ typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])  /* Count the events in use (per event id, not per instance) */  static int	total_ref_count; +static int perf_trace_event_perm(struct ftrace_event_call *tp_event, +				 struct perf_event *p_event) +{ +	/* No tracing, just counting, so no obvious leak */ +	if (!(p_event->attr.sample_type & PERF_SAMPLE_RAW)) +		return 0; + +	/* Some events are ok to be traced by non-root users... */ +	if (p_event->attach_state == PERF_ATTACH_TASK) { +		if (tp_event->flags & TRACE_EVENT_FL_CAP_ANY) +			return 0; +	} + +	/* +	 * ...otherwise raw tracepoint data can be a severe data leak, +	 * only allow root to have these. +	 */ +	if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) +		return -EPERM; + +	return 0; +} +  static int perf_trace_event_init(struct ftrace_event_call *tp_event,  				 struct perf_event *p_event)  {  	struct hlist_head __percpu *list; -	int ret = -ENOMEM; +	int ret;  	int cpu; +	ret = perf_trace_event_perm(tp_event, p_event); +	if (ret) +		return ret; +  	p_event->tp_event = tp_event;  	if (tp_event->perf_refcount++ > 0)  		return 0; +	ret = -ENOMEM; +  	list = alloc_percpu(struct hlist_head);  	if (!list)  		goto fail;  |