Re: [PATCH v2 bpf-next][RFC] libbpf: introduce legacy kprobe events support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Andrii Nakryiko wrote:
> On Tue, Apr 6, 2021 at 9:49 PM Rafael David Tinoco
> <rafaeldtinoco@xxxxxxxxxx> wrote:
> >
> > Sorry taking so long for replying on this… have been working in:
> > https://github.com/rafaeldtinoco/conntracker/tree/main/ebpf
> > as a consumer for the work being proposed by this patch.
> >
> > Current working version at:
> > https://github.com/rafaeldtinoco/conntracker/blob/main/ebpf/patches/libbpf-introduce-legacy-kprobe-events-support.patch
> > About to be changed with suggestions from this thread.
> >

Just catching up on this thread now.

> > > don't get why you need this function either...
> >
> > Because of /sys/kernel/debug/tracing/events/kprobes/%s/enable. I’m
> > toggling it to OFF before removing the kprobe in kprobe_events, like
> > showed above.
> 
> Alright, see above about enable files, it doesn't seem necessary,
> actually. You use poke_kprobe_events() to add or remove kprobe to the
> kernel. That gives you event_name and its id (from
> /sys/kernel/debug/tracing/events/kprobes/%s/id). You then use that id
> to create perf_event and activate BPF program:
> 
>   struct perf_event_attr attr;
>   struct bpf_link* link;
>   int fd = -1, err, id;
>   FILE* f = NULL;
> 
>   err = poke_kprobe_events(true /*add*/, func_name, is_kretprobe);
>   if (err) {
>     fprintf(stderr, "failed to create kprobe event: %d\n", err);
>     return NULL;
>   }
> 
>   snprintf(
>       fname,
>       sizeof(fname),
>       "/sys/kernel/debug/tracing/events/kprobes/%s/id",
>       func_name);
>   f = fopen(fname, "r");
>   if (!f) {
>     fprintf(stderr, "failed to open kprobe id file '%s': %d\n", fname, -errno);
>     goto err_out;
>   }
> 
>   if (fscanf(f, "%d\n", &id) != 1) {
>     fprintf(stderr, "failed to read kprobe id from '%s': %d\n", fname, -errno);
>     goto err_out;
>   }
> 
>   fclose(f);
>   f = NULL;
> 
>   memset(&attr, 0, sizeof(attr));
>   attr.size = sizeof(attr);
>   attr.config = id;
>   attr.type = PERF_TYPE_TRACEPOINT;
>   attr.sample_period = 1;
>   attr.wakeup_events = 1;
> 
>   fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC);
>   if (fd < 0) {
>     fprintf(
>         stderr,
>         "failed to create perf event for kprobe ID %d: %d\n",
>         id,
>         -errno);
>     goto err_out;
>   }
> 
>   link = bpf_program__attach_perf_event(prog, fd);
> 
> And that should be it. It doesn't seem like either BCC or my example
> (which I'm sure worked last time) does anything with /enable files and
> I'm sure all that works.

FWIW I also have a similar patch on my stack that does this and was
working fine for us. I've got a note here to submit it, but its
been stuck on the todo list.

I'll post it here maybe its helpful,

+static int write_to_kprobe_events(const char *name,
+                                 uint64_t offset, int pid, bool retprobe)
+{
+       const char *kprobe_events = "/sys/kernel/debug/tracing/kprobe_events";
+       int fd = open(kprobe_events, O_WRONLY | O_APPEND, 0);
+       char buf[PATH_MAX];
+       int err;
+
+       if (fd < 0) {
+               err = -errno;
+               pr_warn("Failed open kprobe_events: %s\n", strerror(errno));
+               return err;
+       }
+       snprintf(buf, sizeof(buf), "%c:kprobes/%s %s",
+                retprobe ? 'r' : 'p', name, name);
+       err = write(fd, buf, strlen(buf));
+       close(fd);
+       if (err < 0) {
+               err = -errno;
+               pr_warn("Failed write kprobe_events: %s\n", strerror(errno));
+               return err;
+       }
+       return 0;
+}
+
+/* If we do not have an event_source/../kprobes then we can try to use
+ * kprobe-base event tracing, for details see documentation kprobetrace.rst
+ */
+static int perf_event_open_probe_debugfs(bool uprobe, bool retprobe, const char *name,
+                                        uint64_t offset, int pid)
+{
+       const char *kprobes_dir = "/sys/kernel/debug/tracing/events/kprobes/";
+       struct perf_event_attr attr = {};
+       char errmsg[STRERR_BUFSIZE];
+       char file[PATH_MAX];
+       int pfd, err, id;
+
+       if (uprobe) {
+               return -EOPNOTSUPP;
+       } else {
+               err = write_to_kprobe_events(name, offset, pid, retprobe);
+               if (err < 0)
+                       return err;
+               err = snprintf(file, sizeof(file), "%s/%s/id", kprobes_dir, name);
+               if (err < 0)
+                       return -errno;
+               id = parse_uint_from_file(file, "%d\n");
+               if (id < 0)
+                       return err;
+               attr.size = sizeof(attr);
+               attr.type = PERF_TYPE_TRACEPOINT;
+               attr.config = id;
+       }
+
+       /* pid filter is meaningful only for uprobes */
+       pfd = syscall(__NR_perf_event_open, &attr,
+                     pid < 0 ? -1 : pid /* pid */,
+                     pid == -1 ? 0 : -1 /* cpu */,
+                     -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
+       if (pfd < 0) {
+               err = -errno;
+               pr_warn("%s perf_event_open_probe_debugfs() failed: %s\n",
+                       uprobe ? "uprobe" : "kprobe",
+                       libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
+               return err;
+       }
+       return pfd;
+}

> 
> [...]
> 
> > >>>      return bpf_program__attach_kprobe(prog, retprobe, func_name);



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux