diff options
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/bpf_trace.c | 25 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_entries.h | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 14 | ||||
| -rw-r--r-- | kernel/trace/trace_events_hist.c | 12 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_uprobe.c | 35 | 
7 files changed, 56 insertions, 36 deletions
| diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index d88e96d4e12c..56ba0f2a01db 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -977,6 +977,7 @@ int perf_event_query_prog_array(struct perf_event *event, void __user *info)  {  	struct perf_event_query_bpf __user *uquery = info;  	struct perf_event_query_bpf query = {}; +	u32 *ids, prog_cnt, ids_len;  	int ret;  	if (!capable(CAP_SYS_ADMIN)) @@ -985,16 +986,32 @@ int perf_event_query_prog_array(struct perf_event *event, void __user *info)  		return -EINVAL;  	if (copy_from_user(&query, uquery, sizeof(query)))  		return -EFAULT; -	if (query.ids_len > BPF_TRACE_MAX_PROGS) + +	ids_len = query.ids_len; +	if (ids_len > BPF_TRACE_MAX_PROGS)  		return -E2BIG; +	ids = kcalloc(ids_len, sizeof(u32), GFP_USER | __GFP_NOWARN); +	if (!ids) +		return -ENOMEM; +	/* +	 * The above kcalloc returns ZERO_SIZE_PTR when ids_len = 0, which +	 * is required when user only wants to check for uquery->prog_cnt. +	 * There is no need to check for it since the case is handled +	 * gracefully in bpf_prog_array_copy_info. +	 */  	mutex_lock(&bpf_event_mutex);  	ret = bpf_prog_array_copy_info(event->tp_event->prog_array, -				       uquery->ids, -				       query.ids_len, -				       &uquery->prog_cnt); +				       ids, +				       ids_len, +				       &prog_cnt);  	mutex_unlock(&bpf_event_mutex); +	if (copy_to_user(&uquery->prog_cnt, &prog_cnt, sizeof(prog_cnt)) || +	    copy_to_user(uquery->ids, ids, ids_len * sizeof(u32))) +		ret = -EFAULT; + +	kfree(ids);  	return ret;  } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index dfbcf9ee1447..414d7210b2ec 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1165,7 +1165,7 @@ static struct {  	{ trace_clock,			"perf",		1 },  	{ ktime_get_mono_fast_ns,	"mono",		1 },  	{ ktime_get_raw_fast_ns,	"mono_raw",	1 }, -	{ ktime_get_mono_fast_ns,	"boot",		1 }, +	{ ktime_get_boot_fast_ns,	"boot",		1 },  	ARCH_TRACE_CLOCKS  }; diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index e954ae3d82c0..e3a658bac10f 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -356,7 +356,7 @@ FTRACE_ENTRY(hwlat, hwlat_entry,  		__field(	unsigned int,		seqnum		)  	), -	F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llunmi-ts:%llu\tnmi-count:%u\n", +	F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llu\tnmi-ts:%llu\tnmi-count:%u\n",  		 __entry->seqnum,  		 __entry->tv_sec,  		 __entry->tv_nsec, diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 9b4716bb8bb0..1f951b3df60c 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1499,14 +1499,14 @@ static int process_preds(struct trace_event_call *call,  		return ret;  	} -	if (!nr_preds) { -		prog = NULL; -	} else { -		prog = predicate_parse(filter_string, nr_parens, nr_preds, +	if (!nr_preds) +		return -EINVAL; + +	prog = predicate_parse(filter_string, nr_parens, nr_preds,  			       parse_pred, call, pe); -		if (IS_ERR(prog)) -			return PTR_ERR(prog); -	} +	if (IS_ERR(prog)) +		return PTR_ERR(prog); +  	rcu_assign_pointer(filter->prog, prog);  	return 0;  } diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 0d7b3ffbecc2..b9061ed59bbd 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -2466,6 +2466,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,  		else if (strcmp(modifier, "usecs") == 0)  			*flags |= HIST_FIELD_FL_TIMESTAMP_USECS;  		else { +			hist_err("Invalid field modifier: ", modifier);  			field = ERR_PTR(-EINVAL);  			goto out;  		} @@ -2481,6 +2482,7 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,  	else {  		field = trace_find_event_field(file->event_call, field_name);  		if (!field || !field->size) { +			hist_err("Couldn't find field: ", field_name);  			field = ERR_PTR(-EINVAL);  			goto out;  		} @@ -4913,6 +4915,16 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)  		seq_printf(m, "%s", field_name);  	} else if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP)  		seq_puts(m, "common_timestamp"); + +	if (hist_field->flags) { +		if (!(hist_field->flags & HIST_FIELD_FL_VAR_REF) && +		    !(hist_field->flags & HIST_FIELD_FL_EXPR)) { +			const char *flags = get_hist_field_flags(hist_field); + +			if (flags) +				seq_printf(m, ".%s", flags); +		} +	}  }  static int event_hist_trigger_print(struct seq_file *m, diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1cd3fb4d70f8..02aed76e0978 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -512,8 +512,6 @@ static int __register_trace_kprobe(struct trace_kprobe *tk)  	if (ret == 0)  		tk->tp.flags |= TP_FLAG_REGISTERED;  	else { -		pr_warn("Could not insert probe at %s+%lu: %d\n", -			trace_kprobe_symbol(tk), trace_kprobe_offset(tk), ret);  		if (ret == -ENOENT && trace_kprobe_is_on_module(tk)) {  			pr_warn("This probe might be able to register after target module is loaded. Continue.\n");  			ret = 0; diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 34fd0e0ec51d..ac892878dbe6 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -55,6 +55,7 @@ struct trace_uprobe {  	struct list_head		list;  	struct trace_uprobe_filter	filter;  	struct uprobe_consumer		consumer; +	struct path			path;  	struct inode			*inode;  	char				*filename;  	unsigned long			offset; @@ -289,7 +290,7 @@ static void free_trace_uprobe(struct trace_uprobe *tu)  	for (i = 0; i < tu->tp.nr_args; i++)  		traceprobe_free_probe_arg(&tu->tp.args[i]); -	iput(tu->inode); +	path_put(&tu->path);  	kfree(tu->tp.call.class->system);  	kfree(tu->tp.call.name);  	kfree(tu->filename); @@ -363,7 +364,6 @@ end:  static int create_trace_uprobe(int argc, char **argv)  {  	struct trace_uprobe *tu; -	struct inode *inode;  	char *arg, *event, *group, *filename;  	char buf[MAX_EVENT_NAME_LEN];  	struct path path; @@ -371,7 +371,6 @@ static int create_trace_uprobe(int argc, char **argv)  	bool is_delete, is_return;  	int i, ret; -	inode = NULL;  	ret = 0;  	is_delete = false;  	is_return = false; @@ -437,21 +436,16 @@ static int create_trace_uprobe(int argc, char **argv)  	}  	/* Find the last occurrence, in case the path contains ':' too. */  	arg = strrchr(argv[1], ':'); -	if (!arg) { -		ret = -EINVAL; -		goto fail_address_parse; -	} +	if (!arg) +		return -EINVAL;  	*arg++ = '\0';  	filename = argv[1];  	ret = kern_path(filename, LOOKUP_FOLLOW, &path);  	if (ret) -		goto fail_address_parse; - -	inode = igrab(d_real_inode(path.dentry)); -	path_put(&path); +		return ret; -	if (!inode || !S_ISREG(inode->i_mode)) { +	if (!d_is_reg(path.dentry)) {  		ret = -EINVAL;  		goto fail_address_parse;  	} @@ -490,7 +484,7 @@ static int create_trace_uprobe(int argc, char **argv)  		goto fail_address_parse;  	}  	tu->offset = offset; -	tu->inode = inode; +	tu->path = path;  	tu->filename = kstrdup(filename, GFP_KERNEL);  	if (!tu->filename) { @@ -558,7 +552,7 @@ error:  	return ret;  fail_address_parse: -	iput(inode); +	path_put(&path);  	pr_info("Failed to parse address or file.\n"); @@ -922,6 +916,7 @@ probe_event_enable(struct trace_uprobe *tu, struct trace_event_file *file,  		goto err_flags;  	tu->consumer.filter = filter; +	tu->inode = d_real_inode(tu->path.dentry);  	ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);  	if (ret)  		goto err_buffer; @@ -967,6 +962,7 @@ probe_event_disable(struct trace_uprobe *tu, struct trace_event_file *file)  	WARN_ON(!uprobe_filter_is_empty(&tu->filter));  	uprobe_unregister(tu->inode, tu->offset, &tu->consumer); +	tu->inode = NULL;  	tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE;  	uprobe_buffer_disable(); @@ -1337,7 +1333,6 @@ struct trace_event_call *  create_local_trace_uprobe(char *name, unsigned long offs, bool is_return)  {  	struct trace_uprobe *tu; -	struct inode *inode;  	struct path path;  	int ret; @@ -1345,11 +1340,8 @@ create_local_trace_uprobe(char *name, unsigned long offs, bool is_return)  	if (ret)  		return ERR_PTR(ret); -	inode = igrab(d_inode(path.dentry)); -	path_put(&path); - -	if (!inode || !S_ISREG(inode->i_mode)) { -		iput(inode); +	if (!d_is_reg(path.dentry)) { +		path_put(&path);  		return ERR_PTR(-EINVAL);  	} @@ -1364,11 +1356,12 @@ create_local_trace_uprobe(char *name, unsigned long offs, bool is_return)  	if (IS_ERR(tu)) {  		pr_info("Failed to allocate trace_uprobe.(%d)\n",  			(int)PTR_ERR(tu)); +		path_put(&path);  		return ERR_CAST(tu);  	}  	tu->offset = offs; -	tu->inode = inode; +	tu->path = path;  	tu->filename = kstrdup(name, GFP_KERNEL);  	init_trace_event_call(tu, &tu->tp.call); |