@@ -445,6 +445,7 @@ struct filter_match_data {
445
445
size_t index ;
446
446
size_t size ;
447
447
unsigned long * addrs ;
448
+ struct module * * mods ;
448
449
};
449
450
450
451
static int filter_match_callback (void * data , const char * name , unsigned long addr )
@@ -458,30 +459,47 @@ static int filter_match_callback(void *data, const char *name, unsigned long add
458
459
if (!ftrace_location (addr ))
459
460
return 0 ;
460
461
461
- if (match -> addrs )
462
- match -> addrs [match -> index ] = addr ;
462
+ if (match -> addrs ) {
463
+ struct module * mod = __module_text_address (addr );
464
+
465
+ if (mod && !try_module_get (mod ))
466
+ return 0 ;
463
467
468
+ match -> mods [match -> index ] = mod ;
469
+ match -> addrs [match -> index ] = addr ;
470
+ }
464
471
match -> index ++ ;
465
472
return match -> index == match -> size ;
466
473
}
467
474
468
475
/*
469
476
* Make IP list from the filter/no-filter glob patterns.
470
- * Return the number of matched symbols, or -ENOENT.
477
+ * Return the number of matched symbols, or errno.
478
+ * If @addrs == NULL, this just counts the number of matched symbols. If @addrs
479
+ * is passed with an array, we need to pass the an @mods array of the same size
480
+ * to increment the module refcount for each symbol.
481
+ * This means we also need to call `module_put` for each element of @mods after
482
+ * using the @addrs.
471
483
*/
472
- static int ip_list_from_filter (const char * filter , const char * notfilter ,
473
- unsigned long * addrs , size_t size )
484
+ static int get_ips_from_filter (const char * filter , const char * notfilter ,
485
+ unsigned long * addrs , struct module * * mods ,
486
+ size_t size )
474
487
{
475
488
struct filter_match_data match = { .filter = filter , .notfilter = notfilter ,
476
- .index = 0 , .size = size , .addrs = addrs };
489
+ .index = 0 , .size = size , .addrs = addrs , . mods = mods };
477
490
int ret ;
478
491
492
+ if (addrs && !mods )
493
+ return - EINVAL ;
494
+
479
495
ret = kallsyms_on_each_symbol (filter_match_callback , & match );
480
496
if (ret < 0 )
481
497
return ret ;
482
- ret = module_kallsyms_on_each_symbol (NULL , filter_match_callback , & match );
483
- if (ret < 0 )
484
- return ret ;
498
+ if (IS_ENABLED (CONFIG_MODULES )) {
499
+ ret = module_kallsyms_on_each_symbol (NULL , filter_match_callback , & match );
500
+ if (ret < 0 )
501
+ return ret ;
502
+ }
485
503
486
504
return match .index ?: - ENOENT ;
487
505
}
@@ -543,24 +561,35 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
543
561
*/
544
562
int register_fprobe (struct fprobe * fp , const char * filter , const char * notfilter )
545
563
{
546
- unsigned long * addrs ;
547
- int ret ;
564
+ unsigned long * addrs __free (kfree ) = NULL ;
565
+ struct module * * mods __free (kfree ) = NULL ;
566
+ int ret , num ;
548
567
549
568
if (!fp || !filter )
550
569
return - EINVAL ;
551
570
552
- ret = ip_list_from_filter (filter , notfilter , NULL , FPROBE_IPS_MAX );
553
- if (ret < 0 )
554
- return ret ;
571
+ num = get_ips_from_filter (filter , notfilter , NULL , NULL , FPROBE_IPS_MAX );
572
+ if (num < 0 )
573
+ return num ;
555
574
556
- addrs = kcalloc (ret , sizeof (unsigned long ), GFP_KERNEL );
575
+ addrs = kcalloc (num , sizeof (* addrs ), GFP_KERNEL );
557
576
if (!addrs )
558
577
return - ENOMEM ;
559
- ret = ip_list_from_filter (filter , notfilter , addrs , ret );
560
- if (ret > 0 )
561
- ret = register_fprobe_ips (fp , addrs , ret );
562
578
563
- kfree (addrs );
579
+ mods = kcalloc (num , sizeof (* mods ), GFP_KERNEL );
580
+ if (!mods )
581
+ return - ENOMEM ;
582
+
583
+ ret = get_ips_from_filter (filter , notfilter , addrs , mods , num );
584
+ if (ret < 0 )
585
+ return ret ;
586
+
587
+ ret = register_fprobe_ips (fp , addrs , ret );
588
+
589
+ for (int i = 0 ; i < num ; i ++ ) {
590
+ if (mods [i ])
591
+ module_put (mods [i ]);
592
+ }
564
593
return ret ;
565
594
}
566
595
EXPORT_SYMBOL_GPL (register_fprobe );
0 commit comments