Unverified Commit f3a37f7c authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4587 [sync] PR-4562: v4 tracing: Backport bugfixes

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/4562 
 
PR sync from: Zheng Yejian <zhengyejian1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/PQI3ZSIHZZDDFAUE4YYKBMF3BNXKQYGK/ 
v3 -> v4:
  - Fix kabi breakage in struct trace_event_file

v2 -> v3:
  - Fix checkdepend failed

v1 -> v2:
  - Fix checkformat failed

Steven Rostedt (Google) (3):
  tracing: Increase trace array ref count on enable and filter files
  tracing: Have trace_event_file have ref counters
  tracing: Have event inject files inc the trace array ref count

Yang Jihong (1):
  trace: Fix kabi breakage in struct trace_event_file

Zheng Yejian (1):
  tracing: Fix uaf issue when open the hist or hist_debug file


-- 
2.25.1
 
https://gitee.com/openeuler/kernel/issues/I90MN1 
 
Link:https://gitee.com/openeuler/kernel/pulls/4587

 

Reviewed-by: default avatarXu Kuohai <xukuohai@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents b2e60ec9 c7d5ddfe
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -376,6 +376,7 @@ enum {
	EVENT_FILE_FL_TRIGGER_COND_BIT,
	EVENT_FILE_FL_PID_FILTER_BIT,
	EVENT_FILE_FL_WAS_ENABLED_BIT,
	EVENT_FILE_FL_FREED_BIT,
};

extern struct trace_event_file *trace_get_event_file(const char *instance,
@@ -514,6 +515,7 @@ extern int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...);
 *  TRIGGER_COND  - When set, one or more triggers has an associated filter
 *  PID_FILTER    - When set, the event is filtered based on pid
 *  WAS_ENABLED   - Set when enabled to know to clear trace on module removal
 *  FREED         - File descriptor is freed, all fields should be considered invalid
 */
enum {
	EVENT_FILE_FL_ENABLED		= (1 << EVENT_FILE_FL_ENABLED_BIT),
@@ -527,6 +529,7 @@ enum {
	EVENT_FILE_FL_TRIGGER_COND	= (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
	EVENT_FILE_FL_PID_FILTER	= (1 << EVENT_FILE_FL_PID_FILTER_BIT),
	EVENT_FILE_FL_WAS_ENABLED	= (1 << EVENT_FILE_FL_WAS_ENABLED_BIT),
	EVENT_FILE_FL_FREED		= (1 << EVENT_FILE_FL_FREED_BIT),
};

struct trace_event_file {
@@ -557,6 +560,8 @@ struct trace_event_file {
	unsigned long		flags;
	atomic_t		sm_ref;	/* soft-mode reference counter */
	atomic_t		tm_ref;	/* trigger-mode reference counter */

	KABI_EXTEND(atomic_t ref)	/* ref count for opened files */
};

#define __TRACE_EVENT_FLAGS(name, value)				\
+48 −0
Original line number Diff line number Diff line
@@ -4513,6 +4513,54 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp)
	return 0;
}

/*
 * The private pointer of the inode is the trace_event_file.
 * Update the tr ref count associated to it.
 */
int tracing_open_file_tr(struct inode *inode, struct file *filp)
{
	struct trace_event_file *file = inode->i_private;
	int ret;

	ret = tracing_check_open_get_tr(file->tr);
	if (ret)
		return ret;

	mutex_lock(&event_mutex);

	/* Fail if the file is marked for removal */
	if (file->flags & EVENT_FILE_FL_FREED) {
		trace_array_put(file->tr);
		ret = -ENODEV;
	} else {
		event_file_get(file);
	}

	mutex_unlock(&event_mutex);
	if (ret)
		return ret;

	filp->private_data = inode->i_private;

	return 0;
}

int tracing_release_file_tr(struct inode *inode, struct file *filp)
{
	struct trace_event_file *file = inode->i_private;

	trace_array_put(file->tr);
	event_file_put(file);

	return 0;
}

int tracing_single_release_file_tr(struct inode *inode, struct file *filp)
{
	tracing_release_file_tr(inode, filp);
	return single_release(inode, filp);
}

static int tracing_release(struct inode *inode, struct file *file)
{
	struct trace_array *tr = inode->i_private;
+6 −0
Original line number Diff line number Diff line
@@ -736,6 +736,9 @@ void tracing_reset_all_online_cpus(void);
void tracing_reset_all_online_cpus_unlocked(void);
int tracing_open_generic(struct inode *inode, struct file *filp);
int tracing_open_generic_tr(struct inode *inode, struct file *filp);
int tracing_open_file_tr(struct inode *inode, struct file *filp);
int tracing_release_file_tr(struct inode *inode, struct file *filp);
int tracing_single_release_file_tr(struct inode *inode, struct file *filp);
bool tracing_is_disabled(void);
bool tracer_tracing_is_on(struct trace_array *tr);
void tracer_tracing_on(struct trace_array *tr);
@@ -1780,6 +1783,9 @@ extern int register_event_command(struct event_command *cmd);
extern int unregister_event_command(struct event_command *cmd);
extern int register_trigger_hist_enable_disable_cmds(void);

extern void event_file_get(struct trace_event_file *file);
extern void event_file_put(struct trace_event_file *file);

/**
 * struct event_trigger_ops - callbacks for trace event triggers
 *
+32 −17
Original line number Diff line number Diff line
@@ -749,26 +749,38 @@ static void remove_subsystem(struct trace_subsystem_dir *dir)
	}
}

static void remove_event_file_dir(struct trace_event_file *file)
void event_file_get(struct trace_event_file *file)
{
	struct dentry *dir = file->dir;
	struct dentry *child;
	atomic_inc(&file->ref);
}

	if (dir) {
		spin_lock(&dir->d_lock);	/* probably unneeded */
		list_for_each_entry(child, &dir->d_subdirs, d_child) {
			if (d_really_is_positive(child))	/* probably unneeded */
				d_inode(child)->i_private = NULL;
void event_file_put(struct trace_event_file *file)
{
	if (WARN_ON_ONCE(!atomic_read(&file->ref))) {
		if (file->flags & EVENT_FILE_FL_FREED)
			kmem_cache_free(file_cachep, file);
		return;
	}
		spin_unlock(&dir->d_lock);

		tracefs_remove(dir);
	if (atomic_dec_and_test(&file->ref)) {
		/* Count should only go to zero when it is freed */
		if (WARN_ON_ONCE(!(file->flags & EVENT_FILE_FL_FREED)))
			return;
		kmem_cache_free(file_cachep, file);
	}
}

static void remove_event_file_dir(struct trace_event_file *file)
{
	struct dentry *dir = file->dir;

	tracefs_remove(dir);

	list_del(&file->list);
	remove_subsystem(file->system);
	free_event_filter(file->filter);
	kmem_cache_free(file_cachep, file);
	file->flags |= EVENT_FILE_FL_FREED;
	event_file_put(file);
}

/*
@@ -1141,7 +1153,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
		flags = file->flags;
	mutex_unlock(&event_mutex);

	if (!file)
	if (!file || flags & EVENT_FILE_FL_FREED)
		return -ENODEV;

	if (flags & EVENT_FILE_FL_ENABLED &&
@@ -1179,7 +1191,7 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
		ret = -ENODEV;
		mutex_lock(&event_mutex);
		file = event_file_data(filp);
		if (likely(file))
		if (likely(file && !(file->flags & EVENT_FILE_FL_FREED)))
			ret = ftrace_event_enable_disable(file, val);
		mutex_unlock(&event_mutex);
		break;
@@ -1448,7 +1460,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,

	mutex_lock(&event_mutex);
	file = event_file_data(filp);
	if (file)
	if (file && !(file->flags & EVENT_FILE_FL_FREED))
		print_event_filter(file, s);
	mutex_unlock(&event_mutex);

@@ -1858,9 +1870,10 @@ static const struct file_operations ftrace_set_event_notrace_pid_fops = {
};

static const struct file_operations ftrace_enable_fops = {
	.open = tracing_open_generic,
	.open = tracing_open_file_tr,
	.read = event_enable_read,
	.write = event_enable_write,
	.release = tracing_release_file_tr,
	.llseek = default_llseek,
};

@@ -1877,9 +1890,10 @@ static const struct file_operations ftrace_event_id_fops = {
};

static const struct file_operations ftrace_event_filter_fops = {
	.open = tracing_open_generic,
	.open = tracing_open_file_tr,
	.read = event_filter_read,
	.write = event_filter_write,
	.release = tracing_release_file_tr,
	.llseek = default_llseek,
};

@@ -2482,6 +2496,7 @@ trace_create_new_event(struct trace_event_call *call,
	atomic_set(&file->tm_ref, 0);
	INIT_LIST_HEAD(&file->triggers);
	list_add(&file->list, &tr->events);
	event_file_get(file);

	return file;
}
+3 −0
Original line number Diff line number Diff line
@@ -1893,6 +1893,9 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
	struct event_filter *filter = NULL;
	int err;

	if (file->flags & EVENT_FILE_FL_FREED)
		return -ENODEV;

	if (!strcmp(strstrip(filter_string), "0")) {
		filter_disable(file);
		filter = event_filter(file);
Loading