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)

Reply via email to