get_ips_from_filter() counts matching symbols before allocating its address
and module arrays, then repeats the walk to fill them. A matching module
can be loaded between the two passes. If the vmlinux walk fills the
arrays, filter_match_callback() returns a positive stop value, but the
caller ignores it and starts the module walk with index equal to size.
The first module match then writes beyond both allocations.
KASAN reports:
BUG: KASAN: slab-out-of-bounds in filter_match_callback
Write of size 8
filter_match_callback
module_kallsyms_on_each_symbol
get_ips_from_filter
register_fprobe
Return the completed count when the vmlinux walk reports that the arrays
are full instead of continuing into module symbols.
The reproducer completed all tested module-load timings without a KASAN
report with this change.
Fixes: 4346ba160409 ("fprobe: Rewrite fprobe on function-graph tracer")
Signed-off-by: Yifan Zhang <[email protected]>
---
kernel/trace/fprobe.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c
index da286619c5d89..69d1887790739 100644
--- a/kernel/trace/fprobe.c
+++ b/kernel/trace/fprobe.c
@@ -885,6 +885,8 @@ static int get_ips_from_filter(const char *filter, const
char *notfilter,
ret = kallsyms_on_each_symbol(filter_match_callback, &match);
if (ret < 0)
return ret;
+ if (ret > 0)
+ return match.index;
if (IS_ENABLED(CONFIG_MODULES)) {
ret = module_kallsyms_on_each_symbol(NULL,
filter_match_callback, &match);
if (ret < 0)
--
2.39.5 (Apple Git-154)