libbpf: Add support for program extensions
authorAlexei Starovoitov <ast@kernel.org>
Tue, 21 Jan 2020 00:53:47 +0000 (16:53 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 22 Jan 2020 22:04:53 +0000 (23:04 +0100)
Add minimal support for program extensions. bpf_object_open_opts() needs to be
called with attach_prog_fd = target_prog_fd and BPF program extension needs to
have in .c file section definition like SEC("freplace/func_to_be_replaced").
libbpf will search for "func_to_be_replaced" in the target_prog_fd's BTF and
will pass it in attach_btf_id to the kernel. This approach works for tests, but
more compex use case may need to request function name (and attach_btf_id that
kernel sees) to be more dynamic. Such API will be added in future patches.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/bpf/20200121005348.2769920-3-ast@kernel.org
tools/include/uapi/linux/bpf.h
tools/lib/bpf/bpf.c
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map
tools/lib/bpf/libbpf_probes.c

index 033d90a2282dac71ec1c1bf62dfacbe603830411..e81628eb059c8ba8f95b4359d6796020d50d2338 100644 (file)
@@ -180,6 +180,7 @@ enum bpf_prog_type {
        BPF_PROG_TYPE_CGROUP_SOCKOPT,
        BPF_PROG_TYPE_TRACING,
        BPF_PROG_TYPE_STRUCT_OPS,
+       BPF_PROG_TYPE_EXT,
 };
 
 enum bpf_attach_type {
index ed42b006533c455463467414265d8ec19065c54d..c6dafe56317659b8573d5e12bfed9def3e004e6d 100644 (file)
@@ -237,7 +237,8 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        attr.expected_attach_type = load_attr->expected_attach_type;
        if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS) {
                attr.attach_btf_id = load_attr->attach_btf_id;
-       } else if (attr.prog_type == BPF_PROG_TYPE_TRACING) {
+       } else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
+                  attr.prog_type == BPF_PROG_TYPE_EXT) {
                attr.attach_btf_id = load_attr->attach_btf_id;
                attr.attach_prog_fd = load_attr->attach_prog_fd;
        } else {
index faab96a421413bf235e5d1cacd6a3d04a47afb00..ae34b681ae820b53b45b703d3a91eaa0854d9d2b 100644 (file)
@@ -4837,7 +4837,8 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        load_attr.license = license;
        if (prog->type == BPF_PROG_TYPE_STRUCT_OPS) {
                load_attr.attach_btf_id = prog->attach_btf_id;
-       } else if (prog->type == BPF_PROG_TYPE_TRACING) {
+       } else if (prog->type == BPF_PROG_TYPE_TRACING ||
+                  prog->type == BPF_PROG_TYPE_EXT) {
                load_attr.attach_prog_fd = prog->attach_prog_fd;
                load_attr.attach_btf_id = prog->attach_btf_id;
        } else {
@@ -4918,7 +4919,8 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver)
 {
        int err = 0, fd, i, btf_id;
 
-       if (prog->type == BPF_PROG_TYPE_TRACING) {
+       if (prog->type == BPF_PROG_TYPE_TRACING ||
+           prog->type == BPF_PROG_TYPE_EXT) {
                btf_id = libbpf_find_attach_btf_id(prog);
                if (btf_id <= 0)
                        return btf_id;
@@ -5092,7 +5094,8 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
 
                bpf_program__set_type(prog, prog_type);
                bpf_program__set_expected_attach_type(prog, attach_type);
-               if (prog_type == BPF_PROG_TYPE_TRACING)
+               if (prog_type == BPF_PROG_TYPE_TRACING ||
+                   prog_type == BPF_PROG_TYPE_EXT)
                        prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0);
        }
 
@@ -6166,6 +6169,7 @@ BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
 BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
 BPF_PROG_TYPE_FNS(tracing, BPF_PROG_TYPE_TRACING);
 BPF_PROG_TYPE_FNS(struct_ops, BPF_PROG_TYPE_STRUCT_OPS);
+BPF_PROG_TYPE_FNS(extension, BPF_PROG_TYPE_EXT);
 
 enum bpf_attach_type
 bpf_program__get_expected_attach_type(struct bpf_program *prog)
@@ -6265,6 +6269,9 @@ static const struct bpf_sec_def section_defs[] = {
                .expected_attach_type = BPF_TRACE_FEXIT,
                .is_attach_btf = true,
                .attach_fn = attach_trace),
+       SEC_DEF("freplace/", EXT,
+               .is_attach_btf = true,
+               .attach_fn = attach_trace),
        BPF_PROG_SEC("xdp",                     BPF_PROG_TYPE_XDP),
        BPF_PROG_SEC("perf_event",              BPF_PROG_TYPE_PERF_EVENT),
        BPF_PROG_SEC("lwt_in",                  BPF_PROG_TYPE_LWT_IN),
index 01639f9a1062a263bcfaa4f1d36a67143c56e7b6..2a5e3b087002e4b0e83959b9dedda18add97dee7 100644 (file)
@@ -318,6 +318,7 @@ LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_tracing(struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_struct_ops(struct bpf_program *prog);
+LIBBPF_API int bpf_program__set_extension(struct bpf_program *prog);
 
 LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog);
 LIBBPF_API void bpf_program__set_type(struct bpf_program *prog,
@@ -339,6 +340,7 @@ LIBBPF_API bool bpf_program__is_xdp(const struct bpf_program *prog);
 LIBBPF_API bool bpf_program__is_perf_event(const struct bpf_program *prog);
 LIBBPF_API bool bpf_program__is_tracing(const struct bpf_program *prog);
 LIBBPF_API bool bpf_program__is_struct_ops(const struct bpf_program *prog);
+LIBBPF_API bool bpf_program__is_extension(const struct bpf_program *prog);
 
 /*
  * No need for __attribute__((packed)), all members of 'bpf_map_def'
index 64ec71ba41f17205726cccd46e1ef40a08cf3915..b035122142bb9f372eee148856a4f5edde0b2793 100644 (file)
@@ -228,7 +228,9 @@ LIBBPF_0.0.7 {
                bpf_prog_attach_xattr;
                bpf_program__attach;
                bpf_program__name;
+               bpf_program__is_extension;
                bpf_program__is_struct_ops;
+               bpf_program__set_extension;
                bpf_program__set_struct_ops;
                btf__align_of;
                libbpf_find_kernel_btf;
index 8cc992bc532ad5ea547033f5d21bfcdecc60128e..b782ebef6ac9265269ab47db41b3584b1ef326ba 100644 (file)
@@ -107,6 +107,7 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
        case BPF_PROG_TYPE_CGROUP_SOCKOPT:
        case BPF_PROG_TYPE_TRACING:
        case BPF_PROG_TYPE_STRUCT_OPS:
+       case BPF_PROG_TYPE_EXT:
        default:
                break;
        }