Skip to content

Commit

Permalink
libbpf: Support attachment of BPF tracing programs to kernel modules
Browse files Browse the repository at this point in the history
Teach libbpf to search for BTF types in kernel modules for tracing BPF
programs. This allows attachment of raw_tp/fentry/fexit/fmod_ret/etc BPF
program types to tracepoints and functions in kernel modules.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20201203204634.1325171-13-andrii@kernel.org
  • Loading branch information
Andrii Nakryiko authored and Alexei Starovoitov committed Dec 4, 2020
1 parent 6aef10a commit 91abb4a
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 32 deletions.
5 changes: 4 additions & 1 deletion tools/lib/bpf/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,11 @@ int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr)
attr.prog_type = load_attr->prog_type;
attr.expected_attach_type = load_attr->expected_attach_type;

if (load_attr->attach_prog_fd)
attr.attach_prog_fd = load_attr->attach_prog_fd;
else
attr.attach_btf_obj_fd = load_attr->attach_btf_obj_fd;
attr.attach_btf_id = load_attr->attach_btf_id;
attr.attach_prog_fd = load_attr->attach_prog_fd;

attr.prog_ifindex = load_attr->prog_ifindex;
attr.kern_version = load_attr->kern_version;
Expand Down
138 changes: 107 additions & 31 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ struct bpf_program {
enum bpf_prog_type type;
enum bpf_attach_type expected_attach_type;
int prog_ifindex;
__u32 attach_btf_obj_fd;
__u32 attach_btf_id;
__u32 attach_prog_fd;
void *func_info;
Expand Down Expand Up @@ -408,6 +409,7 @@ struct module_btf {
struct btf *btf;
char *name;
__u32 id;
int fd;
};

struct bpf_object {
Expand Down Expand Up @@ -4766,8 +4768,7 @@ static int load_module_btfs(struct bpf_object *obj)
if (err) {
err = -errno;
pr_warn("failed to get BTF object #%d info: %d\n", id, err);
close(fd);
return err;
goto err_out;
}

/* ignore non-module BTFs */
Expand All @@ -4777,25 +4778,33 @@ static int load_module_btfs(struct bpf_object *obj)
}

btf = btf_get_from_fd(fd, obj->btf_vmlinux);
close(fd);
if (IS_ERR(btf)) {
pr_warn("failed to load module [%s]'s BTF object #%d: %ld\n",
name, id, PTR_ERR(btf));
return PTR_ERR(btf);
err = PTR_ERR(btf);
goto err_out;
}

err = btf_ensure_mem((void **)&obj->btf_modules, &obj->btf_module_cap,
sizeof(*obj->btf_modules), obj->btf_module_cnt + 1);
if (err)
return err;
goto err_out;

mod_btf = &obj->btf_modules[obj->btf_module_cnt++];

mod_btf->btf = btf;
mod_btf->id = id;
mod_btf->fd = fd;
mod_btf->name = strdup(name);
if (!mod_btf->name)
return -ENOMEM;
if (!mod_btf->name) {
err = -ENOMEM;
goto err_out;
}
continue;

err_out:
close(fd);
return err;
}

return 0;
Expand Down Expand Up @@ -6841,7 +6850,10 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
load_attr.insn_cnt = insns_cnt;
load_attr.license = license;
load_attr.attach_btf_id = prog->attach_btf_id;
load_attr.attach_prog_fd = prog->attach_prog_fd;
if (prog->attach_prog_fd)
load_attr.attach_prog_fd = prog->attach_prog_fd;
else
load_attr.attach_btf_obj_fd = prog->attach_btf_obj_fd;
load_attr.attach_btf_id = prog->attach_btf_id;
load_attr.kern_version = kern_version;
load_attr.prog_ifindex = prog->prog_ifindex;
Expand Down Expand Up @@ -6937,11 +6949,11 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
return ret;
}

static int libbpf_find_attach_btf_id(struct bpf_program *prog);
static int libbpf_find_attach_btf_id(struct bpf_program *prog, int *btf_obj_fd, int *btf_type_id);

int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
{
int err = 0, fd, i, btf_id;
int err = 0, fd, i;

if (prog->obj->loaded) {
pr_warn("prog '%s': can't load after object was loaded\n", prog->name);
Expand All @@ -6951,10 +6963,14 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
if ((prog->type == BPF_PROG_TYPE_TRACING ||
prog->type == BPF_PROG_TYPE_LSM ||
prog->type == BPF_PROG_TYPE_EXT) && !prog->attach_btf_id) {
btf_id = libbpf_find_attach_btf_id(prog);
if (btf_id <= 0)
return btf_id;
prog->attach_btf_id = btf_id;
int btf_obj_fd = 0, btf_type_id = 0;

err = libbpf_find_attach_btf_id(prog, &btf_obj_fd, &btf_type_id);
if (err)
return err;

prog->attach_btf_obj_fd = btf_obj_fd;
prog->attach_btf_id = btf_type_id;
}

if (prog->instances.nr < 0 || !prog->instances.fds) {
Expand Down Expand Up @@ -7467,6 +7483,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr)

/* clean up module BTFs */
for (i = 0; i < obj->btf_module_cnt; i++) {
close(obj->btf_modules[i].fd);
btf__free(obj->btf_modules[i].btf);
free(obj->btf_modules[i].name);
}
Expand Down Expand Up @@ -8821,8 +8838,8 @@ static int find_btf_by_prefix_kind(const struct btf *btf, const char *prefix,
return btf__find_by_name_kind(btf, btf_type_name, kind);
}

static inline int __find_vmlinux_btf_id(struct btf *btf, const char *name,
enum bpf_attach_type attach_type)
static inline int find_attach_btf_id(struct btf *btf, const char *name,
enum bpf_attach_type attach_type)
{
int err;

Expand All @@ -8838,9 +8855,6 @@ static inline int __find_vmlinux_btf_id(struct btf *btf, const char *name,
else
err = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC);

if (err <= 0)
pr_warn("%s is not found in vmlinux BTF\n", name);

return err;
}

Expand All @@ -8856,7 +8870,10 @@ int libbpf_find_vmlinux_btf_id(const char *name,
return -EINVAL;
}

err = __find_vmlinux_btf_id(btf, name, attach_type);
err = find_attach_btf_id(btf, name, attach_type);
if (err <= 0)
pr_warn("%s is not found in vmlinux BTF\n", name);

btf__free(btf);
return err;
}
Expand Down Expand Up @@ -8894,11 +8911,49 @@ static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd)
return err;
}

static int libbpf_find_attach_btf_id(struct bpf_program *prog)
static int find_kernel_btf_id(struct bpf_object *obj, const char *attach_name,
enum bpf_attach_type attach_type,
int *btf_obj_fd, int *btf_type_id)
{
int ret, i;

ret = find_attach_btf_id(obj->btf_vmlinux, attach_name, attach_type);
if (ret > 0) {
*btf_obj_fd = 0; /* vmlinux BTF */
*btf_type_id = ret;
return 0;
}
if (ret != -ENOENT)
return ret;

ret = load_module_btfs(obj);
if (ret)
return ret;

for (i = 0; i < obj->btf_module_cnt; i++) {
const struct module_btf *mod = &obj->btf_modules[i];

ret = find_attach_btf_id(mod->btf, attach_name, attach_type);
if (ret > 0) {
*btf_obj_fd = mod->fd;
*btf_type_id = ret;
return 0;
}
if (ret == -ENOENT)
continue;

return ret;
}

return -ESRCH;
}

static int libbpf_find_attach_btf_id(struct bpf_program *prog, int *btf_obj_fd, int *btf_type_id)
{
enum bpf_attach_type attach_type = prog->expected_attach_type;
__u32 attach_prog_fd = prog->attach_prog_fd;
const char *name = prog->sec_name;
const char *name = prog->sec_name, *attach_name;
const struct bpf_sec_def *sec = NULL;
int i, err;

if (!name)
Expand All @@ -8909,17 +8964,37 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog)
continue;
if (strncmp(name, section_defs[i].sec, section_defs[i].len))
continue;
if (attach_prog_fd)
err = libbpf_find_prog_btf_id(name + section_defs[i].len,
attach_prog_fd);
else
err = __find_vmlinux_btf_id(prog->obj->btf_vmlinux,
name + section_defs[i].len,
attach_type);

sec = &section_defs[i];
break;
}

if (!sec) {
pr_warn("failed to identify BTF ID based on ELF section name '%s'\n", name);
return -ESRCH;
}
attach_name = name + sec->len;

/* BPF program's BTF ID */
if (attach_prog_fd) {
err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd);
if (err < 0) {
pr_warn("failed to find BPF program (FD %d) BTF ID for '%s': %d\n",
attach_prog_fd, attach_name, err);
return err;
}
*btf_obj_fd = 0;
*btf_type_id = err;
return 0;
}

/* kernel/module BTF ID */
err = find_kernel_btf_id(prog->obj, attach_name, attach_type, btf_obj_fd, btf_type_id);
if (err) {
pr_warn("failed to find kernel BTF type ID of '%s': %d\n", attach_name, err);
return err;
}
pr_warn("failed to identify btf_id based on ELF section name '%s'\n", name);
return -ESRCH;
return 0;
}

int libbpf_attach_type_by_name(const char *name,
Expand Down Expand Up @@ -10808,6 +10883,7 @@ int bpf_program__set_attach_target(struct bpf_program *prog,
return btf_id;

prog->attach_btf_id = btf_id;
prog->attach_btf_obj_fd = 0;
prog->attach_prog_fd = attach_prog_fd;
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions tools/lib/bpf/libbpf_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ struct bpf_prog_load_params {
const char *license;
__u32 kern_version;
__u32 attach_prog_fd;
__u32 attach_btf_obj_fd;
__u32 attach_btf_id;
__u32 prog_ifindex;
__u32 prog_btf_fd;
Expand Down

0 comments on commit 91abb4a

Please sign in to comment.