public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
From: Jackie Liu <liu.yun@linux.dev>
To: Daniel Borkmann <daniel@iogearbox.net>,
	olsajiri@gmail.com, andrii@kernel.org
Cc: martin.lau@linux.dev, song@kernel.org, yhs@fb.com,
	bpf@vger.kernel.org, liuyun01@kylinos.cn
Subject: Re: [PATCH v6 1/2] libbpf: kprobe.multi: cross filter using available_filter_functions and kallsyms
Date: Wed, 5 Jul 2023 17:04:26 +0800	[thread overview]
Message-ID: <2455212f-3081-af11-e4ba-695c29884930@linux.dev> (raw)
In-Reply-To: <53543ecf-d1dd-3e11-ac6f-59ed134a0711@iogearbox.net>



在 2023/7/5 17:01, Daniel Borkmann 写道:
> On 7/5/23 5:34 AM, Jackie Liu wrote:
>> From: Jackie Liu <liuyun01@kylinos.cn>
>>
>> When using regular expression matching with "kprobe multi", it scans all
>> the functions under "/proc/kallsyms" that can be matched. However, not 
>> all
>> of them can be traced by kprobe.multi. If any one of the functions fails
>> to be traced, it will result in the failure of all functions. The best
>> approach is to filter out the functions that cannot be traced to ensure
>> proper tracking of the functions.
>>
>> Reported-by: kernel test robot <lkp@intel.com>
>> Closes: 
>> https://lore.kernel.org/oe-kbuild-all/202307030355.TdXOHklM-lkp@intel.com/
>> Suggested-by: Jiri Olsa <jolsa@kernel.org>
>> Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
>> Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
>> ---
>>   v5->v6: fix crash by not init "const char *syms"
>>   v4->v5: simplified code
>>
>>   tools/lib/bpf/libbpf.c | 106 +++++++++++++++++++++++++++++++++++++----
>>   1 file changed, 96 insertions(+), 10 deletions(-)
>>
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index 214f828ece6b..3b5a12ca47bf 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -10224,6 +10224,12 @@ static const char *tracefs_uprobe_events(void)
>>       return use_debugfs() ? DEBUGFS"/uprobe_events" : 
>> TRACEFS"/uprobe_events";
>>   }
>> +static const char *tracefs_available_filter_functions(void)
>> +{
>> +    return use_debugfs() ? DEBUGFS"/available_filter_functions" :
>> +                   TRACEFS"/available_filter_functions";
>> +}
>> +
>>   static void gen_kprobe_legacy_event_name(char *buf, size_t buf_sz,
>>                        const char *kfunc_name, size_t offset)
>>   {
>> @@ -10539,14 +10545,26 @@ struct kprobe_multi_resolve {
>>       size_t cnt;
>>   };
>> -static int
>> -resolve_kprobe_multi_cb(unsigned long long sym_addr, char sym_type,
>> -            const char *sym_name, void *ctx)
>> +static int avail_compare_function(const void *a, const void *b)
>> +{
>> +    return strcmp(*(const char **)a, *(const char **)b);
>> +}
>> +
>> +struct avail_kallsyms_data {
>> +    const char **syms;
>> +    size_t cnt;
>> +    struct kprobe_multi_resolve *res;
>> +};
>> +
>> +static int avail_kallsyms_cb(unsigned long long sym_addr, char sym_type,
>> +                 const char *sym_name, void *ctx)
>>   {
>> -    struct kprobe_multi_resolve *res = ctx;
>> +    struct avail_kallsyms_data *data = ctx;
>> +    struct kprobe_multi_resolve *res = data->res;
>>       int err;
>> -    if (!glob_match(sym_name, res->pattern))
>> +    if (!bsearch(&sym_name, data->syms, data->cnt, sizeof(void *),
>> +             avail_compare_function))
>>           return 0;
>>       err = libbpf_ensure_mem((void **) &res->addrs, &res->cap, 
>> sizeof(unsigned long),
>> @@ -10558,6 +10576,78 @@ resolve_kprobe_multi_cb(unsigned long long 
>> sym_addr, char sym_type,
>>       return 0;
>>   }
>> +static int libbpf_available_kallsyms_parse(struct 
>> kprobe_multi_resolve *res)
>> +{
>> +    struct avail_kallsyms_data data;
>> +    char sym_name[500];
>> +    const char *available_functions_file = 
>> tracefs_available_filter_functions();
>> +    FILE *f;
>> +    int err = 0, ret, i;
>> +    const char **syms = NULL;
>> +    size_t cap = 0, cnt = 0;
>> +
>> +    f = fopen(available_functions_file, "r");
>> +    if (!f) {
>> +        err = -errno;
>> +        pr_warn("failed to open %s\n", available_functions_file);
>> +        return err;
>> +    }
>> +
>> +    while (true) {
>> +        char *name;
>> +
>> +        ret = fscanf(f, "%499s%*[^\n]\n", sym_name);
>> +        if (ret == EOF && feof(f))
>> +            break;
>> +
>> +        if (ret != 1) {
>> +            pr_warn("failed to read available function file entry: 
>> %d\n",
>> +                ret);
>> +            err = -EINVAL;
>> +            goto cleanup;
> 

> All your jumps to cleanup here and below leak f.

Yes, thank you. I miss that when simplifying the code.

-- 
Jackie

> 
>> +        }
>> +
>> +        if (!glob_match(sym_name, res->pattern))
>> +            continue;
>> +
>> +        err = libbpf_ensure_mem((void **)&syms, &cap, sizeof(void *),
>> +                    cnt + 1);
>> +        if (err)
>> +            goto cleanup;
>> +
>> +        name = strdup(sym_name);
>> +        if (!name) {
>> +            err = -errno;
>> +            goto cleanup;
>> +        }
>> +
>> +        syms[cnt++] = name;
>> +    }
>> +    fclose(f);
>> +
>> +    /* not found entry, return direct */
>> +    if (!cnt)
>> +        return -ENOENT;
>> +
>> +    /* sort available functions */
>> +    qsort(syms, cnt, sizeof(void *), avail_compare_function);
>> +
>> +    data.syms = syms;
>> +    data.res = res;
>> +    data.cnt = cnt;
>> +    libbpf_kallsyms_parse(avail_kallsyms_cb, &data);
>> +
>> +    if (!res->cnt)
>> +        err = -ENOENT;
>> +
>> +cleanup:
>> +    for (i = 0; i < cnt; i++)
>> +        free((char *)syms[i]);
>> +    free(syms);
>> +
>> +    return err;
>> +}
>> +
>>   struct bpf_link *
>>   bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
>>                         const char *pattern,
>> @@ -10594,13 +10684,9 @@ bpf_program__attach_kprobe_multi_opts(const 
>> struct bpf_program *prog,
>>           return libbpf_err_ptr(-EINVAL);
>>       if (pattern) {
>> -        err = libbpf_kallsyms_parse(resolve_kprobe_multi_cb, &res);
>> +        err = libbpf_available_kallsyms_parse(&res);
>>           if (err)
>>               goto error;
>> -        if (!res.cnt) {
>> -            err = -ENOENT;
>> -            goto error;
>> -        }
>>           addrs = res.addrs;
>>           cnt = res.cnt;
>>       }
>>
> 

      reply	other threads:[~2023-07-05  9:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-05  3:34 [PATCH v6 1/2] libbpf: kprobe.multi: cross filter using available_filter_functions and kallsyms Jackie Liu
2023-07-05  3:34 ` [PATCH v6 2/2] libbpf: kprobe.multi: Filter with available_filter_functions_addrs Jackie Liu
2023-07-05  9:01 ` [PATCH v6 1/2] libbpf: kprobe.multi: cross filter using available_filter_functions and kallsyms Daniel Borkmann
2023-07-05  9:04   ` Jackie Liu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2455212f-3081-af11-e4ba-695c29884930@linux.dev \
    --to=liu.yun@linux.dev \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=liuyun01@kylinos.cn \
    --cc=martin.lau@linux.dev \
    --cc=olsajiri@gmail.com \
    --cc=song@kernel.org \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox