]> www.infradead.org Git - users/hch/dma-mapping.git/commitdiff
bpf: fix unpopulated name_len field in perf_event link info
authorTyrone Wu <wudevelops@gmail.com>
Tue, 8 Oct 2024 16:43:11 +0000 (16:43 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 10 Oct 2024 01:17:16 +0000 (18:17 -0700)
Previously when retrieving `bpf_link_info.perf_event` for
kprobe/uprobe/tracepoint, the `name_len` field was not populated by the
kernel, leaving it to reflect the value initially set by the user. This
behavior was inconsistent with how other input/output string buffer
fields function (e.g. `raw_tracepoint.tp_name_len`).

This patch fills `name_len` with the actual size of the string name.

Fixes: 1b715e1b0ec5 ("bpf: Support ->fill_link_info for perf_event")
Signed-off-by: Tyrone Wu <wudevelops@gmail.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Yafang Shao <laoar.shao@gmail.com>
Link: https://lore.kernel.org/r/20241008164312.46269-1-wudevelops@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/syscall.c

index a8f1808a1ca54371d5b1fbc85c0290055e62bd4a..8cfa7183d2ef28161aa1ab930e86b740b9b577fd 100644 (file)
@@ -3565,15 +3565,16 @@ static void bpf_perf_link_dealloc(struct bpf_link *link)
 }
 
 static int bpf_perf_link_fill_common(const struct perf_event *event,
-                                    char __user *uname, u32 ulen,
+                                    char __user *uname, u32 *ulenp,
                                     u64 *probe_offset, u64 *probe_addr,
                                     u32 *fd_type, unsigned long *missed)
 {
        const char *buf;
-       u32 prog_id;
+       u32 prog_id, ulen;
        size_t len;
        int err;
 
+       ulen = *ulenp;
        if (!ulen ^ !uname)
                return -EINVAL;
 
@@ -3581,10 +3582,17 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,
                                      probe_offset, probe_addr, missed);
        if (err)
                return err;
+
+       if (buf) {
+               len = strlen(buf);
+               *ulenp = len + 1;
+       } else {
+               *ulenp = 1;
+       }
        if (!uname)
                return 0;
+
        if (buf) {
-               len = strlen(buf);
                err = bpf_copy_to_user(uname, buf, ulen, len);
                if (err)
                        return err;
@@ -3609,7 +3617,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
 
        uname = u64_to_user_ptr(info->perf_event.kprobe.func_name);
        ulen = info->perf_event.kprobe.name_len;
-       err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
+       err = bpf_perf_link_fill_common(event, uname, &ulen, &offset, &addr,
                                        &type, &missed);
        if (err)
                return err;
@@ -3617,7 +3625,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
                info->perf_event.type = BPF_PERF_EVENT_KRETPROBE;
        else
                info->perf_event.type = BPF_PERF_EVENT_KPROBE;
-
+       info->perf_event.kprobe.name_len = ulen;
        info->perf_event.kprobe.offset = offset;
        info->perf_event.kprobe.missed = missed;
        if (!kallsyms_show_value(current_cred()))
@@ -3639,7 +3647,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
 
        uname = u64_to_user_ptr(info->perf_event.uprobe.file_name);
        ulen = info->perf_event.uprobe.name_len;
-       err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
+       err = bpf_perf_link_fill_common(event, uname, &ulen, &offset, &addr,
                                        &type, NULL);
        if (err)
                return err;
@@ -3648,6 +3656,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
                info->perf_event.type = BPF_PERF_EVENT_URETPROBE;
        else
                info->perf_event.type = BPF_PERF_EVENT_UPROBE;
+       info->perf_event.uprobe.name_len = ulen;
        info->perf_event.uprobe.offset = offset;
        info->perf_event.uprobe.cookie = event->bpf_cookie;
        return 0;
@@ -3673,12 +3682,18 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event,
 {
        char __user *uname;
        u32 ulen;
+       int err;
 
        uname = u64_to_user_ptr(info->perf_event.tracepoint.tp_name);
        ulen = info->perf_event.tracepoint.name_len;
+       err = bpf_perf_link_fill_common(event, uname, &ulen, NULL, NULL, NULL, NULL);
+       if (err)
+               return err;
+
        info->perf_event.type = BPF_PERF_EVENT_TRACEPOINT;
+       info->perf_event.tracepoint.name_len = ulen;
        info->perf_event.tracepoint.cookie = event->bpf_cookie;
-       return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL, NULL);
+       return 0;
 }
 
 static int bpf_perf_link_fill_perf_event(const struct perf_event *event,