Skip to content

Commit 9d86160

Browse files
committed
tracing/kprobes: Add symbol counting check when module loads
Currently, kprobe event checks whether the target symbol name is unique or not, so that it does not put a probe on an unexpected place. But this skips the check if the target is on a module because the module may not be loaded. To fix this issue, this patch checks the number of probe target symbols in a target module when the module is loaded. If the probe is not on the unique name symbols in the module, it will be rejected at that point. Note that the symbol which has a unique name in the target module, it will be accepted even if there are same-name symbols in the kernel or other modules, Link: https://lore.kernel.org/all/172016348553.99543.2834679315611882137.stgit@devnote2/ Signed-off-by: Masami Hiramatsu (Google) <[email protected]> Reviewed-by: Steven Rostedt (Google) <[email protected]>
1 parent 637c26f commit 9d86160

File tree

1 file changed

+81
-44
lines changed

1 file changed

+81
-44
lines changed

kernel/trace/trace_kprobe.c

Lines changed: 81 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,21 @@ static int register_trace_kprobe(struct trace_kprobe *tk)
678678
}
679679

680680
#ifdef CONFIG_MODULES
681+
static int validate_module_probe_symbol(const char *modname, const char *symbol);
682+
683+
static int register_module_trace_kprobe(struct module *mod, struct trace_kprobe *tk)
684+
{
685+
const char *p;
686+
int ret = 0;
687+
688+
p = strchr(trace_kprobe_symbol(tk), ':');
689+
if (p)
690+
ret = validate_module_probe_symbol(module_name(mod), p + 1);
691+
if (!ret)
692+
ret = __register_trace_kprobe(tk);
693+
return ret;
694+
}
695+
681696
/* Module notifier call back, checking event on the module */
682697
static int trace_kprobe_module_callback(struct notifier_block *nb,
683698
unsigned long val, void *data)
@@ -696,7 +711,7 @@ static int trace_kprobe_module_callback(struct notifier_block *nb,
696711
if (trace_kprobe_within_module(tk, mod)) {
697712
/* Don't need to check busy - this should have gone. */
698713
__unregister_trace_kprobe(tk);
699-
ret = __register_trace_kprobe(tk);
714+
ret = register_module_trace_kprobe(mod, tk);
700715
if (ret)
701716
pr_warn("Failed to re-register probe %s on %s: %d\n",
702717
trace_probe_name(&tk->tp),
@@ -747,17 +762,68 @@ static int count_mod_symbols(void *data, const char *name, unsigned long unused)
747762
return 0;
748763
}
749764

750-
static unsigned int number_of_same_symbols(char *func_name)
765+
static unsigned int number_of_same_symbols(const char *mod, const char *func_name)
751766
{
752767
struct sym_count_ctx ctx = { .count = 0, .name = func_name };
753768

754-
kallsyms_on_each_match_symbol(count_symbols, func_name, &ctx.count);
769+
if (!mod)
770+
kallsyms_on_each_match_symbol(count_symbols, func_name, &ctx.count);
755771

756-
module_kallsyms_on_each_symbol(NULL, count_mod_symbols, &ctx);
772+
module_kallsyms_on_each_symbol(mod, count_mod_symbols, &ctx);
757773

758774
return ctx.count;
759775
}
760776

777+
static int validate_module_probe_symbol(const char *modname, const char *symbol)
778+
{
779+
unsigned int count = number_of_same_symbols(modname, symbol);
780+
781+
if (count > 1) {
782+
/*
783+
* Users should use ADDR to remove the ambiguity of
784+
* using KSYM only.
785+
*/
786+
return -EADDRNOTAVAIL;
787+
} else if (count == 0) {
788+
/*
789+
* We can return ENOENT earlier than when register the
790+
* kprobe.
791+
*/
792+
return -ENOENT;
793+
}
794+
return 0;
795+
}
796+
797+
static int validate_probe_symbol(char *symbol)
798+
{
799+
struct module *mod = NULL;
800+
char *modname = NULL, *p;
801+
int ret = 0;
802+
803+
p = strchr(symbol, ':');
804+
if (p) {
805+
modname = symbol;
806+
symbol = p + 1;
807+
*p = '\0';
808+
/* Return 0 (defer) if the module does not exist yet. */
809+
rcu_read_lock_sched();
810+
mod = find_module(modname);
811+
if (mod && !try_module_get(mod))
812+
mod = NULL;
813+
rcu_read_unlock_sched();
814+
if (!mod)
815+
goto out;
816+
}
817+
818+
ret = validate_module_probe_symbol(modname, symbol);
819+
out:
820+
if (p)
821+
*p = ':';
822+
if (mod)
823+
module_put(mod);
824+
return ret;
825+
}
826+
761827
static int trace_kprobe_entry_handler(struct kretprobe_instance *ri,
762828
struct pt_regs *regs);
763829

@@ -881,6 +947,14 @@ static int __trace_kprobe_create(int argc, const char *argv[])
881947
trace_probe_log_err(0, BAD_PROBE_ADDR);
882948
goto parse_error;
883949
}
950+
ret = validate_probe_symbol(symbol);
951+
if (ret) {
952+
if (ret == -EADDRNOTAVAIL)
953+
trace_probe_log_err(0, NON_UNIQ_SYMBOL);
954+
else
955+
trace_probe_log_err(0, BAD_PROBE_ADDR);
956+
goto parse_error;
957+
}
884958
if (is_return)
885959
ctx.flags |= TPARG_FL_RETURN;
886960
ret = kprobe_on_func_entry(NULL, symbol, offset);
@@ -893,31 +967,6 @@ static int __trace_kprobe_create(int argc, const char *argv[])
893967
}
894968
}
895969

896-
if (symbol && !strchr(symbol, ':')) {
897-
unsigned int count;
898-
899-
count = number_of_same_symbols(symbol);
900-
if (count > 1) {
901-
/*
902-
* Users should use ADDR to remove the ambiguity of
903-
* using KSYM only.
904-
*/
905-
trace_probe_log_err(0, NON_UNIQ_SYMBOL);
906-
ret = -EADDRNOTAVAIL;
907-
908-
goto error;
909-
} else if (count == 0) {
910-
/*
911-
* We can return ENOENT earlier than when register the
912-
* kprobe.
913-
*/
914-
trace_probe_log_err(0, BAD_PROBE_ADDR);
915-
ret = -ENOENT;
916-
917-
goto error;
918-
}
919-
}
920-
921970
trace_probe_log_set_index(0);
922971
if (event) {
923972
ret = traceprobe_parse_event_name(&event, &group, gbuf,
@@ -1835,21 +1884,9 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
18351884
char *event;
18361885

18371886
if (func) {
1838-
unsigned int count;
1839-
1840-
count = number_of_same_symbols(func);
1841-
if (count > 1)
1842-
/*
1843-
* Users should use addr to remove the ambiguity of
1844-
* using func only.
1845-
*/
1846-
return ERR_PTR(-EADDRNOTAVAIL);
1847-
else if (count == 0)
1848-
/*
1849-
* We can return ENOENT earlier than when register the
1850-
* kprobe.
1851-
*/
1852-
return ERR_PTR(-ENOENT);
1887+
ret = validate_probe_symbol(func);
1888+
if (ret)
1889+
return ERR_PTR(ret);
18531890
}
18541891

18551892
/*

0 commit comments

Comments
 (0)