Skip to content

Commit

Permalink
samples: bpf: fix: error handling regarding kprobe_events
Browse files Browse the repository at this point in the history
Currently, kprobe_events failure won't be handled properly.
Due to calling system() indirectly to write to kprobe_events,
it can't be identified whether an error is derived from kprobe or system.

    // buf = "echo '%c:%s %s' >> /s/k/d/t/kprobe_events"
    err = system(buf);
    if (err < 0) {
        printf("failed to create kprobe ..");
        return -1;
    }

For example, running ./tracex7 sample in ext4 partition,
"echo p:open_ctree open_ctree >> /s/k/d/t/kprobe_events"
gets 256 error code system() failure.
=> The error comes from kprobe, but it's not handled correctly.

According to man of system(3), it's return value
just passes the termination status of the child shell
rather than treating the error as -1. (don't care success)

Which means, currently it's not working as desired.
(According to the upper code snippet)

    ex) running ./tracex7 with ext4 env.
    # Current Output
    sh: echo: I/O error
    failed to open event open_ctree

    # Desired Output
    failed to create kprobe 'open_ctree' error 'No such file or directory'

The problem is, error can't be verified whether from child ps
or system. But using write() directly can verify the command
failure, and it will treat all error as -1. So I suggest using
write() directly to 'kprobe_events' rather than calling system().

Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
Daniel T. Lee authored and Daniel Borkmann committed Nov 23, 2018
1 parent 47ae7e3 commit 5a86381
Showing 1 changed file with 24 additions and 9 deletions.
33 changes: 24 additions & 9 deletions samples/bpf/bpf_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ static int populate_prog_array(const char *event, int prog_fd)
return 0;
}

static int write_kprobe_events(const char *val)
{
int fd, ret, flags;

if ((val != NULL) && (val[0] == '\0'))
flags = O_WRONLY | O_TRUNC;
else
flags = O_WRONLY | O_APPEND;

fd = open("/sys/kernel/debug/tracing/kprobe_events", flags);

ret = write(fd, val, strlen(val));
close(fd);

return ret;
}

static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
{
bool is_socket = strncmp(event, "socket", 6) == 0;
Expand Down Expand Up @@ -165,21 +182,19 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)

#ifdef __x86_64__
if (strncmp(event, "sys_", 4) == 0) {
snprintf(buf, sizeof(buf),
"echo '%c:__x64_%s __x64_%s' >> /sys/kernel/debug/tracing/kprobe_events",
is_kprobe ? 'p' : 'r', event, event);
err = system(buf);
snprintf(buf, sizeof(buf), "%c:__x64_%s __x64_%s",
is_kprobe ? 'p' : 'r', event, event);
err = write_kprobe_events(buf);
if (err >= 0) {
need_normal_check = false;
event_prefix = "__x64_";
}
}
#endif
if (need_normal_check) {
snprintf(buf, sizeof(buf),
"echo '%c:%s %s' >> /sys/kernel/debug/tracing/kprobe_events",
is_kprobe ? 'p' : 'r', event, event);
err = system(buf);
snprintf(buf, sizeof(buf), "%c:%s %s",
is_kprobe ? 'p' : 'r', event, event);
err = write_kprobe_events(buf);
if (err < 0) {
printf("failed to create kprobe '%s' error '%s'\n",
event, strerror(errno));
Expand Down Expand Up @@ -519,7 +534,7 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map)
return 1;

/* clear all kprobes */
i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events");
i = write_kprobe_events("");

/* scan over all elf sections to get license and map info */
for (i = 1; i < ehdr.e_shnum; i++) {
Expand Down

0 comments on commit 5a86381

Please sign in to comment.