Commit 405e6c37 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'probes-fixes-v6.15-rc6' of...

Merge tag 'probes-fixes-v6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull probes fixes from Masami Hiramatsu:

 - fprobe: Fix RCU warning message in list traversal

   fprobe_module_callback() using hlist_for_each_entry_rcu() traverse
   the fprobe list but it locks fprobe_mutex() instead of rcu lock
   because it is enough. So add lockdep_is_held() to avoid warning.

 - tracing: eprobe: Add missing trace_probe_log_clear for eprobe

   __trace_eprobe_create() uses trace_probe_log but forgot to clear it
   at exit. Add trace_probe_log_clear() calls.

 - tracing: probes: Fix possible race in trace_probe_log APIs

   trace_probe_log APIs are used in probe event (dynamic_events,
   kprobe_events and uprobe_events) creation. Only dynamic_events uses
   the dyn_event_ops_mutex mutex to serialize it. This makes kprobe and
   uprobe events to lock the same mutex to serialize its creation to
   avoid race in trace_probe_log APIs.

* tag 'probes-fixes-v6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  tracing: probes: Fix a possible race in trace_probe_log APIs
  tracing: add missing trace_probe_log_clear for eprobes
  tracing: fprobe: Fix RCU warning message in list traversal
parents e9565e23 fd837de3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -454,7 +454,8 @@ static void fprobe_remove_node_in_module(struct module *mod, struct hlist_head *
	struct fprobe_hlist_node *node;
	int ret = 0;

	hlist_for_each_entry_rcu(node, head, hlist) {
	hlist_for_each_entry_rcu(node, head, hlist,
				 lockdep_is_held(&fprobe_mutex)) {
		if (!within_module(node->addr, mod))
			continue;
		if (delete_fprobe_node(node))
+15 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#include "trace_output.h"	/* for trace_event_sem */
#include "trace_dynevent.h"

static DEFINE_MUTEX(dyn_event_ops_mutex);
DEFINE_MUTEX(dyn_event_ops_mutex);
static LIST_HEAD(dyn_event_ops_list);

bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
@@ -116,6 +116,20 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
	return ret;
}

/*
 * Locked version of event creation. The event creation must be protected by
 * dyn_event_ops_mutex because of protecting trace_probe_log.
 */
int dyn_event_create(const char *raw_command, struct dyn_event_operations *type)
{
	int ret;

	mutex_lock(&dyn_event_ops_mutex);
	ret = type->create(raw_command);
	mutex_unlock(&dyn_event_ops_mutex);
	return ret;
}

static int create_dyn_event(const char *raw_command)
{
	struct dyn_event_operations *ops;
+1 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos);
void dyn_event_seq_stop(struct seq_file *m, void *v);
int dyn_events_release_all(struct dyn_event_operations *type);
int dyn_event_release(const char *raw_command, struct dyn_event_operations *type);
int dyn_event_create(const char *raw_command, struct dyn_event_operations *type);

/*
 * for_each_dyn_event	-	iterate over the dyn_event list
+3 −0
Original line number Diff line number Diff line
@@ -969,10 +969,13 @@ static int __trace_eprobe_create(int argc, const char *argv[])
			goto error;
		}
	}
	trace_probe_log_clear();
	return ret;

parse_error:
	ret = -EINVAL;
error:
	trace_probe_log_clear();
	trace_event_probe_cleanup(ep);
	return ret;
}
+1 −1
Original line number Diff line number Diff line
@@ -1089,7 +1089,7 @@ static int create_or_delete_trace_kprobe(const char *raw_command)
	if (raw_command[0] == '-')
		return dyn_event_release(raw_command, &trace_kprobe_ops);

	ret = trace_kprobe_create(raw_command);
	ret = dyn_event_create(raw_command, &trace_kprobe_ops);
	return ret == -ECANCELED ? -EINVAL : ret;
}

Loading