diff options
author | Andrii Nakryiko <andrii@kernel.org> | 2022-04-07 21:42:51 +0300 |
---|---|---|
committer | Andrii Nakryiko <andrii@kernel.org> | 2022-04-07 21:42:51 +0300 |
commit | 502b0e3dcb326cf38334dad35957b12d9cdcf633 (patch) | |
tree | 19b8fcc5a57a399ac1b4510a1453a8e8ad29d7cd /tools/lib | |
parent | 9fc4476a08b6dc61e406c2c0c4e0690512f60e82 (diff) | |
parent | 1717e248014c33a81d7a1cdc048c6b3bed7bb3f8 (diff) | |
download | linux-502b0e3dcb326cf38334dad35957b12d9cdcf633.tar.xz |
Merge branch 'libbpf: uprobe name-based attach followups'
Alan Maguire says:
====================
Follow-up series to [1] to address some suggestions from Andrii to
improve parsing and make it more robust (patches 1, 2) and to improve
validation of u[ret]probe firing by validating expected argument
and return values (patch 3).
[1] https://lore.kernel.org/bpf/164903521182.13106.12656654142629368774.git-patchwork-notify@kernel.org/
Changes since v1:
- split library name, auto-attach parsing into separate patches (Andrii, patches 1, 2)
- made str_has_sfx() static inline, avoided repeated strlen()s by storing lengths,
used strlen() instead of strnlen() (Andrii, patch 1)
- fixed sscanf() arg to use %li, switched logging to use "prog '%s'" format,
used direct strcmp() on probe_type instead of prefix check (Andrii, patch 2)
- switched auto-attach tests to log parameter/return values to be checked by
user-space side of tests. Needed to add pid filtering to avoid capturing
stray malloc()s (Andrii, patch 3)
====================
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 83 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf_internal.h | 11 |
2 files changed, 45 insertions, 49 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1111e9d16e01..016ecdd1c3e1 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -10766,7 +10766,7 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz) const char *search_paths[3] = {}; int i; - if (strstr(file, ".so")) { + if (str_has_sfx(file, ".so") || strstr(file, ".so.")) { search_paths[0] = getenv("LD_LIBRARY_PATH"); search_paths[1] = "/usr/lib64:/usr/lib"; search_paths[2] = arch_specific_lib_paths(); @@ -10913,60 +10913,45 @@ err_out: static int attach_uprobe(const struct bpf_program *prog, long cookie, struct bpf_link **link) { DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts); - char *func, *probe_name, *func_end; - char *func_name, binary_path[512]; - unsigned long long raw_offset; - size_t offset = 0; - int n; + char *probe_type = NULL, *binary_path = NULL, *func_name = NULL; + int n, ret = -EINVAL; + long offset = 0; *link = NULL; - opts.retprobe = str_has_pfx(prog->sec_name, "uretprobe"); - if (opts.retprobe) - probe_name = prog->sec_name + sizeof("uretprobe") - 1; - else - probe_name = prog->sec_name + sizeof("uprobe") - 1; - if (probe_name[0] == '/') - probe_name++; - - /* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */ - if (strlen(probe_name) == 0) - return 0; - - snprintf(binary_path, sizeof(binary_path), "%s", probe_name); - /* ':' should be prior to function+offset */ - func_name = strrchr(binary_path, ':'); - if (!func_name) { - pr_warn("section '%s' missing ':function[+offset]' specification\n", + n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%m[a-zA-Z0-9_.]+%li", + &probe_type, &binary_path, &func_name, &offset); + switch (n) { + case 1: + /* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */ + ret = 0; + break; + case 2: + pr_warn("prog '%s': section '%s' missing ':function[+offset]' specification\n", + prog->name, prog->sec_name); + break; + case 3: + case 4: + opts.retprobe = strcmp(probe_type, "uretprobe") == 0; + if (opts.retprobe && offset != 0) { + pr_warn("prog '%s': uretprobes do not support offset specification\n", + prog->name); + break; + } + opts.func_name = func_name; + *link = bpf_program__attach_uprobe_opts(prog, -1, binary_path, offset, &opts); + ret = libbpf_get_error(*link); + break; + default: + pr_warn("prog '%s': invalid format of section definition '%s'\n", prog->name, prog->sec_name); - return -EINVAL; - } - func_name[0] = '\0'; - func_name++; - n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%li", &func, &offset); - if (n < 1) { - pr_warn("uprobe name '%s' is invalid\n", func_name); - return -EINVAL; - } - if (opts.retprobe && offset != 0) { - free(func); - pr_warn("uretprobes do not support offset specification\n"); - return -EINVAL; - } - - /* Is func a raw address? */ - errno = 0; - raw_offset = strtoull(func, &func_end, 0); - if (!errno && !*func_end) { - free(func); - func = NULL; - offset = (size_t)raw_offset; + break; } - opts.func_name = func; + free(probe_type); + free(binary_path); + free(func_name); - *link = bpf_program__attach_uprobe_opts(prog, -1, binary_path, offset, &opts); - free(func); - return libbpf_get_error(*link); + return ret; } struct bpf_link *bpf_program__attach_uprobe(const struct bpf_program *prog, diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index dd0d4ccfa649..080272421f6c 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -103,6 +103,17 @@ #define str_has_pfx(str, pfx) \ (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0) +/* suffix check */ +static inline bool str_has_sfx(const char *str, const char *sfx) +{ + size_t str_len = strlen(str); + size_t sfx_len = strlen(sfx); + + if (sfx_len <= str_len) + return strcmp(str + str_len - sfx_len, sfx); + return false; +} + /* Symbol versioning is different between static and shared library. * Properly versioned symbols are needed for shared library, but * only the symbol of the new version is needed for static library. |