[PATCH v2] samples: bpf: fix: seg fault with NULL pointer arg

2018-12-03 Thread Daniel T. Lee
When NULL pointer accidentally passed to write_kprobe_events,
due to strlen(NULL), segmentation fault happens.
Changed code returns -1 to deal with this situation.

Bug issued with Smatch, static analysis.

Signed-off-by: Daniel T. Lee 
---
 samples/bpf/bpf_load.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 434ea34a5954..eae7b635343d 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -58,7 +58,9 @@ static int write_kprobe_events(const char *val)
 {
int fd, ret, flags;
 
-   if ((val != NULL) && (val[0] == '\0'))
+   if (val == NULL)
+   return -1;
+   else if (val[0] == '\0')
flags = O_WRONLY | O_TRUNC;
else
flags = O_WRONLY | O_APPEND;
-- 
2.17.1



[PATCH] samples: bpf: fix: seg fault with NULL pointer arg

2018-12-01 Thread Daniel T. Lee
When NULL pointer accidentally passed to write_kprobe_events,
due to strlen(NULL), segmentation fault happens.
Changed code returns -1 to deal with this situation.

Bug issued with Smatch, static analysis.

Signed-off-by: Daniel T. Lee 
---
 samples/bpf/bpf_load.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 434ea34a5954..c670bd2200d2 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -58,7 +58,9 @@ static int write_kprobe_events(const char *val)
 {
int fd, ret, flags;
 
-   if ((val != NULL) && (val[0] == '\0'))
+   if (val == NULL)
+   return -1;
+   else if ((val != NULL) && (val[0] == '\0'))
flags = O_WRONLY | O_TRUNC;
else
flags = O_WRONLY | O_APPEND;
-- 
2.17.1



[PATCH v2] samples: bpf: fix: error handling regarding kprobe_events

2018-11-22 Thread Daniel T. Lee
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 
---
Changes in v2:
  - Fix code style at variable declaration.

 samples/bpf/bpf_load.c | 33 -
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index e6d7e0fe155b..96783207de4a 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -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;
@@ -165,10 +182,9 @@ 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_";
@@ -176,10 +192,9 @@ static int load_and_attach(const char *event, struct 
bpf_insn *prog, int size)
}
 #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));
@@ -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++) {
-- 
2.17.1



[PATCH] samples: bpf: fix: error handling regarding kprobe_events

2018-11-21 Thread Daniel T. Lee
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 
---
 samples/bpf/bpf_load.c | 33 -
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index e6d7e0fe155b..3e34d733f5f8 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -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 ret, flags;
+
+   if ((val != NULL) && (val[0] == '\0'))
+   flags = O_WRONLY | O_TRUNC;
+   else
+   flags = O_WRONLY | O_APPEND;
+
+   int 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;
@@ -165,10 +182,9 @@ 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_";
@@ -176,10 +192,9 @@ static int load_and_attach(const char *event, struct 
bpf_insn *prog, int size)
}
 #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));
@@ -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++) {
-- 
2.17.1