Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf...
[sfrench/cifs-2.6.git] / kernel / trace / bpf_trace.c
index 5f2dcabad202c976b1005599a37b87fd0231ce12..c92eb8c6ff08dbfad32c1c60bcca452de8c9ac31 100644 (file)
@@ -2369,9 +2369,13 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
        if (is_tracepoint || is_syscall_tp) {
                *buf = is_tracepoint ? event->tp_event->tp->name
                                     : event->tp_event->name;
-               *fd_type = BPF_FD_TYPE_TRACEPOINT;
-               *probe_offset = 0x0;
-               *probe_addr = 0x0;
+               /* We allow NULL pointer for tracepoint */
+               if (fd_type)
+                       *fd_type = BPF_FD_TYPE_TRACEPOINT;
+               if (probe_offset)
+                       *probe_offset = 0x0;
+               if (probe_addr)
+                       *probe_addr = 0x0;
        } else {
                /* kprobe/uprobe */
                err = -EOPNOTSUPP;
@@ -2384,7 +2388,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
 #ifdef CONFIG_UPROBE_EVENTS
                if (flags & TRACE_EVENT_FL_UPROBE)
                        err = bpf_get_uprobe_info(event, fd_type, buf,
-                                                 probe_offset,
+                                                 probe_offset, probe_addr,
                                                  event->attr.type == PERF_TYPE_TRACEPOINT);
 #endif
        }
@@ -2469,6 +2473,7 @@ struct bpf_kprobe_multi_link {
        u32 cnt;
        u32 mods_cnt;
        struct module **mods;
+       u32 flags;
 };
 
 struct bpf_kprobe_multi_run_ctx {
@@ -2558,9 +2563,44 @@ static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
        kfree(kmulti_link);
 }
 
+static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
+                                               struct bpf_link_info *info)
+{
+       u64 __user *uaddrs = u64_to_user_ptr(info->kprobe_multi.addrs);
+       struct bpf_kprobe_multi_link *kmulti_link;
+       u32 ucount = info->kprobe_multi.count;
+       int err = 0, i;
+
+       if (!uaddrs ^ !ucount)
+               return -EINVAL;
+
+       kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
+       info->kprobe_multi.count = kmulti_link->cnt;
+       info->kprobe_multi.flags = kmulti_link->flags;
+
+       if (!uaddrs)
+               return 0;
+       if (ucount < kmulti_link->cnt)
+               err = -ENOSPC;
+       else
+               ucount = kmulti_link->cnt;
+
+       if (kallsyms_show_value(current_cred())) {
+               if (copy_to_user(uaddrs, kmulti_link->addrs, ucount * sizeof(u64)))
+                       return -EFAULT;
+       } else {
+               for (i = 0; i < ucount; i++) {
+                       if (put_user(0, uaddrs + i))
+                               return -EFAULT;
+               }
+       }
+       return err;
+}
+
 static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
        .release = bpf_kprobe_multi_link_release,
        .dealloc = bpf_kprobe_multi_link_dealloc,
+       .fill_link_info = bpf_kprobe_multi_link_fill_link_info,
 };
 
 static void bpf_kprobe_multi_cookie_swap(void *a, void *b, int size, const void *priv)
@@ -2874,6 +2914,7 @@ int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
        link->addrs = addrs;
        link->cookies = cookies;
        link->cnt = cnt;
+       link->flags = flags;
 
        if (cookies) {
                /*