Merge 91bd008d4e ("Merge tag 'probes-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace") into android-mainline

Steps on the way to v6.11-rc1

Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: I229f4672092932defd8be23469df40b5a9984547
This commit is contained in:
Lee Jones
2024-08-12 09:58:04 +01:00
2703 changed files with 438266 additions and 50574 deletions
+111 -81
View File
@@ -678,6 +678,21 @@ end:
}
#ifdef CONFIG_MODULES
static int validate_module_probe_symbol(const char *modname, const char *symbol);
static int register_module_trace_kprobe(struct module *mod, struct trace_kprobe *tk)
{
const char *p;
int ret = 0;
p = strchr(trace_kprobe_symbol(tk), ':');
if (p)
ret = validate_module_probe_symbol(module_name(mod), p + 1);
if (!ret)
ret = __register_trace_kprobe(tk);
return ret;
}
/* Module notifier call back, checking event on the module */
static int trace_kprobe_module_callback(struct notifier_block *nb,
unsigned long val, void *data)
@@ -696,7 +711,7 @@ static int trace_kprobe_module_callback(struct notifier_block *nb,
if (trace_kprobe_within_module(tk, mod)) {
/* Don't need to check busy - this should have gone. */
__unregister_trace_kprobe(tk);
ret = __register_trace_kprobe(tk);
ret = register_module_trace_kprobe(mod, tk);
if (ret)
pr_warn("Failed to re-register probe %s on %s: %d\n",
trace_probe_name(&tk->tp),
@@ -747,17 +762,81 @@ static int count_mod_symbols(void *data, const char *name, unsigned long unused)
return 0;
}
static unsigned int number_of_same_symbols(char *func_name)
static unsigned int number_of_same_symbols(const char *mod, const char *func_name)
{
struct sym_count_ctx ctx = { .count = 0, .name = func_name };
kallsyms_on_each_match_symbol(count_symbols, func_name, &ctx.count);
if (!mod)
kallsyms_on_each_match_symbol(count_symbols, func_name, &ctx.count);
module_kallsyms_on_each_symbol(NULL, count_mod_symbols, &ctx);
module_kallsyms_on_each_symbol(mod, count_mod_symbols, &ctx);
return ctx.count;
}
static int validate_module_probe_symbol(const char *modname, const char *symbol)
{
unsigned int count = number_of_same_symbols(modname, symbol);
if (count > 1) {
/*
* Users should use ADDR to remove the ambiguity of
* using KSYM only.
*/
return -EADDRNOTAVAIL;
} else if (count == 0) {
/*
* We can return ENOENT earlier than when register the
* kprobe.
*/
return -ENOENT;
}
return 0;
}
#ifdef CONFIG_MODULES
/* Return NULL if the module is not loaded or under unloading. */
static struct module *try_module_get_by_name(const char *name)
{
struct module *mod;
rcu_read_lock_sched();
mod = find_module(name);
if (mod && !try_module_get(mod))
mod = NULL;
rcu_read_unlock_sched();
return mod;
}
#else
#define try_module_get_by_name(name) (NULL)
#endif
static int validate_probe_symbol(char *symbol)
{
struct module *mod = NULL;
char *modname = NULL, *p;
int ret = 0;
p = strchr(symbol, ':');
if (p) {
modname = symbol;
symbol = p + 1;
*p = '\0';
mod = try_module_get_by_name(modname);
if (!mod)
goto out;
}
ret = validate_module_probe_symbol(modname, symbol);
out:
if (p)
*p = ':';
if (mod)
module_put(mod);
return ret;
}
static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
struct pt_regs *regs);
@@ -881,6 +960,14 @@ static int __trace_kprobe_create(int argc, const char *argv[])
trace_probe_log_err(0, BAD_PROBE_ADDR);
goto parse_error;
}
ret = validate_probe_symbol(symbol);
if (ret) {
if (ret == -EADDRNOTAVAIL)
trace_probe_log_err(0, NON_UNIQ_SYMBOL);
else
trace_probe_log_err(0, BAD_PROBE_ADDR);
goto parse_error;
}
if (is_return)
ctx.flags |= TPARG_FL_RETURN;
ret = kprobe_on_func_entry(NULL, symbol, offset);
@@ -893,31 +980,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
}
}
if (symbol && !strchr(symbol, ':')) {
unsigned int count;
count = number_of_same_symbols(symbol);
if (count > 1) {
/*
* Users should use ADDR to remove the ambiguity of
* using KSYM only.
*/
trace_probe_log_err(0, NON_UNIQ_SYMBOL);
ret = -EADDRNOTAVAIL;
goto error;
} else if (count == 0) {
/*
* We can return ENOENT earlier than when register the
* kprobe.
*/
trace_probe_log_err(0, BAD_PROBE_ADDR);
ret = -ENOENT;
goto error;
}
}
trace_probe_log_set_index(0);
if (event) {
ret = traceprobe_parse_event_name(&event, &group, gbuf,
@@ -1835,21 +1897,9 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
char *event;
if (func) {
unsigned int count;
count = number_of_same_symbols(func);
if (count > 1)
/*
* Users should use addr to remove the ambiguity of
* using func only.
*/
return ERR_PTR(-EADDRNOTAVAIL);
else if (count == 0)
/*
* We can return ENOENT earlier than when register the
* kprobe.
*/
return ERR_PTR(-ENOENT);
ret = validate_probe_symbol(func);
if (ret)
return ERR_PTR(ret);
}
/*
@@ -2023,19 +2073,16 @@ static __init int kprobe_trace_self_tests_init(void)
pr_info("Testing kprobe tracing: ");
ret = create_or_delete_trace_kprobe("p:testprobe kprobe_trace_selftest_target $stack $stack0 +0($stack)");
if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function entry.\n");
if (WARN_ONCE(ret, "error on probing function entry.")) {
warn++;
} else {
/* Enable trace point */
tk = find_trace_kprobe("testprobe", KPROBE_EVENT_SYSTEM);
if (WARN_ON_ONCE(tk == NULL)) {
pr_warn("error on getting new probe.\n");
if (WARN_ONCE(tk == NULL, "error on probing function entry.")) {
warn++;
} else {
file = find_trace_probe_file(tk, top_trace_array());
if (WARN_ON_ONCE(file == NULL)) {
pr_warn("error on getting probe file.\n");
if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
warn++;
} else
enable_trace_kprobe(
@@ -2044,19 +2091,16 @@ static __init int kprobe_trace_self_tests_init(void)
}
ret = create_or_delete_trace_kprobe("r:testprobe2 kprobe_trace_selftest_target $retval");
if (WARN_ON_ONCE(ret)) {
pr_warn("error on probing function return.\n");
if (WARN_ONCE(ret, "error on probing function return.")) {
warn++;
} else {
/* Enable trace point */
tk = find_trace_kprobe("testprobe2", KPROBE_EVENT_SYSTEM);
if (WARN_ON_ONCE(tk == NULL)) {
pr_warn("error on getting 2nd new probe.\n");
if (WARN_ONCE(tk == NULL, "error on getting 2nd new probe.")) {
warn++;
} else {
file = find_trace_probe_file(tk, top_trace_array());
if (WARN_ON_ONCE(file == NULL)) {
pr_warn("error on getting probe file.\n");
if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
warn++;
} else
enable_trace_kprobe(
@@ -2079,18 +2123,15 @@ static __init int kprobe_trace_self_tests_init(void)
/* Disable trace points before removing it */
tk = find_trace_kprobe("testprobe", KPROBE_EVENT_SYSTEM);
if (WARN_ON_ONCE(tk == NULL)) {
pr_warn("error on getting test probe.\n");
if (WARN_ONCE(tk == NULL, "error on getting test probe.")) {
warn++;
} else {
if (trace_kprobe_nhit(tk) != 1) {
pr_warn("incorrect number of testprobe hits\n");
if (WARN_ONCE(trace_kprobe_nhit(tk) != 1,
"incorrect number of testprobe hits."))
warn++;
}
file = find_trace_probe_file(tk, top_trace_array());
if (WARN_ON_ONCE(file == NULL)) {
pr_warn("error on getting probe file.\n");
if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
warn++;
} else
disable_trace_kprobe(
@@ -2098,18 +2139,15 @@ static __init int kprobe_trace_self_tests_init(void)
}
tk = find_trace_kprobe("testprobe2", KPROBE_EVENT_SYSTEM);
if (WARN_ON_ONCE(tk == NULL)) {
pr_warn("error on getting 2nd test probe.\n");
if (WARN_ONCE(tk == NULL, "error on getting 2nd test probe.")) {
warn++;
} else {
if (trace_kprobe_nhit(tk) != 1) {
pr_warn("incorrect number of testprobe2 hits\n");
if (WARN_ONCE(trace_kprobe_nhit(tk) != 1,
"incorrect number of testprobe2 hits."))
warn++;
}
file = find_trace_probe_file(tk, top_trace_array());
if (WARN_ON_ONCE(file == NULL)) {
pr_warn("error on getting probe file.\n");
if (WARN_ONCE(file == NULL, "error on getting probe file.")) {
warn++;
} else
disable_trace_kprobe(
@@ -2117,23 +2155,15 @@ static __init int kprobe_trace_self_tests_init(void)
}
ret = create_or_delete_trace_kprobe("-:testprobe");
if (WARN_ON_ONCE(ret)) {
pr_warn("error on deleting a probe.\n");
if (WARN_ONCE(ret, "error on deleting a probe."))
warn++;
}
ret = create_or_delete_trace_kprobe("-:testprobe2");
if (WARN_ON_ONCE(ret)) {
pr_warn("error on deleting a probe.\n");
if (WARN_ONCE(ret, "error on deleting a probe."))
warn++;
}
end:
ret = dyn_events_release_all(&trace_kprobe_ops);
if (WARN_ON_ONCE(ret)) {
pr_warn("error on cleaning up probes.\n");
warn++;
}
/*
* Wait for the optimizer work to finish. Otherwise it might fiddle
* with probes in already freed __init text.