Add bpf_program__attach_cgroup(), which uses BPF_LINK_CREATE subcommand to create an FD-based kernel bpf_link. Also add low-level bpf_link_create() API. If expected_attach_type is not specified explicitly with bpf_program__set_expected_attach_type(), libbpf will try to determine proper attach type from BPF program's section definition. Also add support for bpf_link's underlying BPF program replacement: - unconditional through high-level bpf_link__update_program() API; - cmpxchg-like with specifying expected current BPF program through low-level bpf_link_update() API.
Unified · Split
| @@ -112,6 +112,7 @@ enum bpf_cmd { · 111 unmodified lines | |||
| 112 | BPF_MAP_UPDATE_BATCH, | 112 | BPF_MAP_UPDATE_BATCH, |
| 113 | BPF_MAP_DELETE_BATCH, | 113 | BPF_MAP_DELETE_BATCH, |
| 114 | BPF_LINK_CREATE, | 114 | BPF_LINK_CREATE, |
| 115 | BPF_LINK_UPDATE, | ||
| 115 | }; | 116 | }; |
| 116 | 117 | ||
| 117 | enum bpf_map_type { | 118 | enum bpf_map_type { |
| @@ -577,6 +578,17 @@ union bpf_attr { · 459 unmodified lines | |||
| 577 | __u32 attach_type; /* attach type */ | 578 | __u32 attach_type; /* attach type */ |
| 578 | __u32 flags; /* extra flags */ | 579 | __u32 flags; /* extra flags */ |
| 579 | } link_create; | 580 | } link_create; |
| 581 | |||
| 582 | struct { /* struct used by BPF_LINK_UPDATE command */ | ||
| 583 | __u32 link_fd; /* link fd */ | ||
| 584 | /* new program fd to update link with */ | ||
| 585 | __u32 new_prog_fd; | ||
| 586 | __u32 flags; /* extra flags */ | ||
| 587 | /* expected link's program fd; is specified only if | ||
| 588 | * BPF_F_REPLACE flag is set in flags */ | ||
| 589 | __u32 old_prog_fd; | ||
| 590 | } link_update; | ||
| 591 | |||
| 580 | } __attribute__((aligned(8))); | 592 | } __attribute__((aligned(8))); |
| 581 | 593 | ||
| 582 | /* The description below is an attempt at providing documentation to eBPF | 594 | /* The description below is an attempt at providing documentation to eBPF |
| @@ -585,6 +585,40 @@ int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type) · 584 unmodified lines | |||
| 585 | return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); | 585 | return sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | int bpf_link_create(int prog_fd, int target_fd, | ||
| 589 | enum bpf_attach_type attach_type, | ||
| 590 | const struct bpf_link_create_opts *opts) | ||
| 591 | { | ||
| 592 | union bpf_attr attr; | ||
| 593 | |||
| 594 | if (!OPTS_VALID(opts, bpf_link_create_opts)) | ||
| 595 | return -EINVAL; | ||
| 596 | |||
| 597 | memset(&attr, 0, sizeof(attr)); | ||
| 598 | attr.link_create.prog_fd = prog_fd; | ||
| 599 | attr.link_create.target_fd = target_fd; | ||
| 600 | attr.link_create.attach_type = attach_type; | ||
| 601 | |||
| 602 | return sys_bpf(BPF_LINK_CREATE, &attr, sizeof(attr)); | ||
| 603 | } | ||
| 604 | |||
| 605 | int bpf_link_update(int link_fd, int new_prog_fd, | ||
| 606 | const struct bpf_link_update_opts *opts) | ||
| 607 | { | ||
| 608 | union bpf_attr attr; | ||
| 609 | |||
| 610 | if (!OPTS_VALID(opts, bpf_link_update_opts)) | ||
| 611 | return -EINVAL; | ||
| 612 | |||
| 613 | memset(&attr, 0, sizeof(attr)); | ||
| 614 | attr.link_update.link_fd = link_fd; | ||
| 615 | attr.link_update.new_prog_fd = new_prog_fd; | ||
| 616 | attr.link_update.flags = OPTS_GET(opts, flags, 0); | ||
| 617 | attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0); | ||
| 618 | |||
| 619 | return sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr)); | ||
| 620 | } | ||
| 621 | |||
| 588 | int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, | 622 | int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags, |
| 589 | __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) | 623 | __u32 *attach_flags, __u32 *prog_ids, __u32 *prog_cnt) |
| 590 | { | 624 | { |
| @@ -168,6 +168,25 @@ LIBBPF_API int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type); · 167 unmodified lines | |||
| 168 | LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd, | 168 | LIBBPF_API int bpf_prog_detach2(int prog_fd, int attachable_fd, |
| 169 | enum bpf_attach_type type); | 169 | enum bpf_attach_type type); |
| 170 | 170 | ||
| 171 | struct bpf_link_create_opts { | ||
| 172 | size_t sz; /* size of this struct for forward/backward compatibility */ | ||
| 173 | }; | ||
| 174 | #define bpf_link_create_opts__last_field sz | ||
| 175 | |||
| 176 | LIBBPF_API int bpf_link_create(int prog_fd, int target_fd, | ||
| 177 | enum bpf_attach_type attach_type, | ||
| 178 | const struct bpf_link_create_opts *opts); | ||
| 179 | |||
| 180 | struct bpf_link_update_opts { | ||
| 181 | size_t sz; /* size of this struct for forward/backward compatibility */ | ||
| 182 | __u32 flags; /* extra flags */ | ||
| 183 | __u32 old_prog_fd; /* expected old program FD */ | ||
| 184 | }; | ||
| 185 | #define bpf_link_update_opts__last_field old_prog_fd | ||
| 186 | |||
| 187 | LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd, | ||
| 188 | const struct bpf_link_update_opts *opts); | ||
| 189 | |||
| 171 | struct bpf_prog_test_run_attr { | 190 | struct bpf_prog_test_run_attr { |
| 172 | int prog_fd; | 191 | int prog_fd; |
| 173 | int repeat; | 192 | int repeat; |
| @@ -6978,6 +6978,12 @@ struct bpf_link { · 6977 unmodified lines | |||
| 6978 | bool disconnected; | 6978 | bool disconnected; |
| 6979 | }; | 6979 | }; |
| 6980 | 6980 | ||
| 6981 | /* Replace link's underlying BPF program with the new one */ | ||
| 6982 | int bpf_link__update_program(struct bpf_link *link, struct bpf_program *prog) | ||
| 6983 | { | ||
| 6984 | return bpf_link_update(bpf_link__fd(link), bpf_program__fd(prog), NULL); | ||
| 6985 | } | ||
| 6986 | |||
| 6981 | /* Release "ownership" of underlying BPF resource (typically, BPF program | 6987 | /* Release "ownership" of underlying BPF resource (typically, BPF program |
| 6982 | * attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected | 6988 | * attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected |
| 6983 | * link, when destructed through bpf_link__destroy() call won't attempt to | 6989 | * link, when destructed through bpf_link__destroy() call won't attempt to |
| @@ -7533,6 +7539,46 @@ static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec, · 549 unmodified lines | |||
| 7533 | return bpf_program__attach_lsm(prog); | 7539 | return bpf_program__attach_lsm(prog); |
| 7534 | } | 7540 | } |
| 7535 | 7541 | ||
| 7542 | struct bpf_link * | ||
| 7543 | bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd) | ||
| 7544 | { | ||
| 7545 | const struct bpf_sec_def *sec_def; | ||
| 7546 | enum bpf_attach_type attach_type; | ||
| 7547 | char errmsg[STRERR_BUFSIZE]; | ||
| 7548 | struct bpf_link *link; | ||
| 7549 | int prog_fd, link_fd; | ||
| 7550 | |||
| 7551 | prog_fd = bpf_program__fd(prog); | ||
| 7552 | if (prog_fd < 0) { | ||
| 7553 | pr_warn("program '%s': can't attach before loaded\n", | ||
| 7554 | bpf_program__title(prog, false)); | ||
| 7555 | return ERR_PTR(-EINVAL); | ||
| 7556 | } | ||
| 7557 | |||
| 7558 | link = calloc(1, sizeof(*link)); | ||
| 7559 | if (!link) | ||
| 7560 | return ERR_PTR(-ENOMEM); | ||
| 7561 | link->detach = &bpf_link__detach_fd; | ||
| 7562 | |||
| 7563 | attach_type = bpf_program__get_expected_attach_type(prog); | ||
| 7564 | if (!attach_type) { | ||
| 7565 | sec_def = find_sec_def(bpf_program__title(prog, false)); | ||
| 7566 | if (sec_def) | ||
| 7567 | attach_type = sec_def->attach_type; | ||
| 7568 | } | ||
| 7569 | link_fd = bpf_link_create(prog_fd, cgroup_fd, attach_type, NULL); | ||
| 7570 | if (link_fd < 0) { | ||
| 7571 | link_fd = -errno; | ||
| 7572 | free(link); | ||
| 7573 | pr_warn("program '%s': failed to attach to cgroup: %s\n", | ||
| 7574 | bpf_program__title(prog, false), | ||
| 7575 | libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg))); | ||
| 7576 | return ERR_PTR(link_fd); | ||
| 7577 | } | ||
| 7578 | link->fd = link_fd; | ||
| 7579 | return link; | ||
| 7580 | } | ||
| 7581 | |||
| 7536 | struct bpf_link *bpf_program__attach(struct bpf_program *prog) | 7582 | struct bpf_link *bpf_program__attach(struct bpf_program *prog) |
| 7537 | { | 7583 | { |
| 7538 | const struct bpf_sec_def *sec_def; | 7584 | const struct bpf_sec_def *sec_def; |
| @@ -224,6 +224,8 @@ LIBBPF_API int bpf_link__fd(const struct bpf_link *link); · 223 unmodified lines | |||
| 224 | LIBBPF_API const char *bpf_link__pin_path(const struct bpf_link *link); | 224 | LIBBPF_API const char *bpf_link__pin_path(const struct bpf_link *link); |
| 225 | LIBBPF_API int bpf_link__pin(struct bpf_link *link, const char *path); | 225 | LIBBPF_API int bpf_link__pin(struct bpf_link *link, const char *path); |
| 226 | LIBBPF_API int bpf_link__unpin(struct bpf_link *link); | 226 | LIBBPF_API int bpf_link__unpin(struct bpf_link *link); |
| 227 | LIBBPF_API int bpf_link__update_program(struct bpf_link *link, | ||
| 228 | struct bpf_program *prog); | ||
| 227 | LIBBPF_API void bpf_link__disconnect(struct bpf_link *link); | 229 | LIBBPF_API void bpf_link__disconnect(struct bpf_link *link); |
| 228 | LIBBPF_API int bpf_link__destroy(struct bpf_link *link); | 230 | LIBBPF_API int bpf_link__destroy(struct bpf_link *link); |
| 229 | 231 | ||
| @@ -245,13 +247,17 @@ bpf_program__attach_tracepoint(struct bpf_program *prog, · 15 unmodified lines | |||
| 245 | LIBBPF_API struct bpf_link * | 247 | LIBBPF_API struct bpf_link * |
| 246 | bpf_program__attach_raw_tracepoint(struct bpf_program *prog, | 248 | bpf_program__attach_raw_tracepoint(struct bpf_program *prog, |
| 247 | const char *tp_name); | 249 | const char *tp_name); |
| 248 | |||
| 249 | LIBBPF_API struct bpf_link * | 250 | LIBBPF_API struct bpf_link * |
| 250 | bpf_program__attach_trace(struct bpf_program *prog); | 251 | bpf_program__attach_trace(struct bpf_program *prog); |
| 251 | LIBBPF_API struct bpf_link * | 252 | LIBBPF_API struct bpf_link * |
| 252 | bpf_program__attach_lsm(struct bpf_program *prog); | 253 | bpf_program__attach_lsm(struct bpf_program *prog); |
| 254 | LIBBPF_API struct bpf_link * | ||
| 255 | bpf_program__attach_cgroup(struct bpf_program *prog, int cgroup_fd); | ||
| 256 | |||
| 253 | struct bpf_map; | 257 | struct bpf_map; |
| 258 | |||
| 254 | LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map); | 259 | LIBBPF_API struct bpf_link *bpf_map__attach_struct_ops(struct bpf_map *map); |
| 260 | |||
| 255 | struct bpf_insn; | 261 | struct bpf_insn; |
| 256 | 262 | ||
| 257 | /* | 263 | /* |
| @@ -243,7 +243,11 @@ LIBBPF_0.0.8 { · 242 unmodified lines | |||
| 243 | bpf_link__pin; | 243 | bpf_link__pin; |
| 244 | bpf_link__pin_path; | 244 | bpf_link__pin_path; |
| 245 | bpf_link__unpin; | 245 | bpf_link__unpin; |
| 246 | bpf_link__update_program; | ||
| 247 | bpf_link_create; | ||
| 248 | bpf_link_update; | ||
| 246 | bpf_map__set_initial_value; | 249 | bpf_map__set_initial_value; |
| 250 | bpf_program__attach_cgroup; | ||
| 247 | bpf_program__attach_lsm; | 251 | bpf_program__attach_lsm; |
| 248 | bpf_program__is_lsm; | 252 | bpf_program__is_lsm; |
| 249 | bpf_program__set_attach_target; | 253 | bpf_program__set_attach_target; |