Commit 47c7efa4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

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

Pull probes fixes from Masami Hiramatsu:

 - Clean up tprobe correctly when module unload

   Tracepoint probes do not set TRACEPOINT_STUB on the 'tpoint' pointer
   when unloading a module, thus they show as a normal 'fprobe' instead
   of 'tprobe' and never come back

 - Fix leakage of tprobe module refcount

   When a tprobe's target module is loaded, it gets the module's
   refcount in the module notifier but forgot to put it after
   registering the probe on it.

   Fix it by getting the refcount only when registering tprobe.

* tag 'probes-fixes-v6.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  tracing: tprobe-events: Fix leakage of module refcount
  tracing: tprobe-events: Fix to clean up tprobe correctly when module unload
parents 4701f33a ac91052f
Loading
Loading
Loading
Loading
+14 −16
Original line number Diff line number Diff line
@@ -920,13 +920,8 @@ static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mo

	if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
		data->tpoint = tp;
		if (!data->mod) {
		if (!data->mod)
			data->mod = mod;
			if (!try_module_get(data->mod)) {
				data->tpoint = NULL;
				data->mod = NULL;
			}
		}
	}
}

@@ -938,13 +933,7 @@ static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
		data->tpoint = tp;
}

/*
 * Find a tracepoint from kernel and module. If the tracepoint is in a module,
 * this increments the module refcount to prevent unloading until the
 * trace_fprobe is registered to the list. After registering the trace_fprobe
 * on the trace_fprobe list, the module refcount is decremented because
 * tracepoint_probe_module_cb will handle it.
 */
/* Find a tracepoint from kernel and module. */
static struct tracepoint *find_tracepoint(const char *tp_name,
					  struct module **tp_mod)
{
@@ -973,6 +962,7 @@ static void reenable_trace_fprobe(struct trace_fprobe *tf)
	}
}

/* Find a tracepoint from specified module. */
static struct tracepoint *find_tracepoint_in_module(struct module *mod,
						    const char *tp_name)
{
@@ -1008,12 +998,15 @@ static int __tracepoint_probe_module_cb(struct notifier_block *self,
					reenable_trace_fprobe(tf);
			}
		} else if (val == MODULE_STATE_GOING && tp_mod->mod == tf->mod) {
			unregister_fprobe(&tf->fp);
			if (trace_fprobe_is_tracepoint(tf)) {
				tracepoint_probe_unregister(tf->tpoint,
					tf->tpoint->probestub, NULL);
			tf->tpoint = NULL;
				tf->tpoint = TRACEPOINT_STUB;
				tf->mod = NULL;
			}
		}
	}
	mutex_unlock(&event_mutex);

	return NOTIFY_DONE;
@@ -1176,6 +1169,11 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
	if (is_tracepoint) {
		ctx->flags |= TPARG_FL_TPOINT;
		tpoint = find_tracepoint(symbol, &tp_mod);
		/* lock module until register this tprobe. */
		if (tp_mod && !try_module_get(tp_mod)) {
			tpoint = NULL;
			tp_mod = NULL;
		}
		if (tpoint) {
			ctx->funcname = kallsyms_lookup(
				(unsigned long)tpoint->probestub,