Skip to content

Commit d695870

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
libbpf: Add bpf_link__disconnect() API to preserve underlying BPF resource
There are cases in which BPF resource (program, map, etc) has to outlive userspace program that "installed" it in the system in the first place. When BPF program is attached, libbpf returns bpf_link object, which is supposed to be destroyed after no longer necessary through bpf_link__destroy() API. Currently, bpf_link destruction causes both automatic detachment and frees up any resources allocated to for bpf_link in-memory representation. This is inconvenient for the case described above because of coupling of detachment and resource freeing. This patch introduces bpf_link__disconnect() API call, which marks bpf_link as disconnected from its underlying BPF resouces. This means that when bpf_link is destroyed later, all its memory resources will be freed, but BPF resource itself won't be detached. This design allows to follow strict and resource-leak-free design by default, while giving easy and straightforward way for user code to opt for keeping BPF resource attached beyond lifetime of a bpf_link. For some BPF programs (i.e., FS-based tracepoints, kprobes, raw tracepoint, etc), user has to make sure to pin BPF program to prevent kernel to automatically detach it on process exit. This should typically be achived by pinning BPF program (or map in some cases) in BPF FS. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 6de6c1f commit d695870

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6245,17 +6245,37 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
62456245
}
62466246

62476247
struct bpf_link {
6248+
int (*detach)(struct bpf_link *link);
62486249
int (*destroy)(struct bpf_link *link);
6250+
bool disconnected;
62496251
};
62506252

6253+
/* Release "ownership" of underlying BPF resource (typically, BPF program
6254+
* attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected
6255+
* link, when destructed through bpf_link__destroy() call won't attempt to
6256+
* detach/unregisted that BPF resource. This is useful in situations where,
6257+
* say, attached BPF program has to outlive userspace program that attached it
6258+
* in the system. Depending on type of BPF program, though, there might be
6259+
* additional steps (like pinning BPF program in BPF FS) necessary to ensure
6260+
* exit of userspace program doesn't trigger automatic detachment and clean up
6261+
* inside the kernel.
6262+
*/
6263+
void bpf_link__disconnect(struct bpf_link *link)
6264+
{
6265+
link->disconnected = true;
6266+
}
6267+
62516268
int bpf_link__destroy(struct bpf_link *link)
62526269
{
6253-
int err;
6270+
int err = 0;
62546271

62556272
if (!link)
62566273
return 0;
62576274

6258-
err = link->destroy(link);
6275+
if (!link->disconnected && link->detach)
6276+
err = link->detach(link);
6277+
if (link->destroy)
6278+
link->destroy(link);
62596279
free(link);
62606280

62616281
return err;
@@ -6266,7 +6286,7 @@ struct bpf_link_fd {
62666286
int fd; /* hook FD */
62676287
};
62686288

6269-
static int bpf_link__destroy_perf_event(struct bpf_link *link)
6289+
static int bpf_link__detach_perf_event(struct bpf_link *link)
62706290
{
62716291
struct bpf_link_fd *l = (void *)link;
62726292
int err;
@@ -6298,10 +6318,10 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
62986318
return ERR_PTR(-EINVAL);
62996319
}
63006320

6301-
link = malloc(sizeof(*link));
6321+
link = calloc(1, sizeof(*link));
63026322
if (!link)
63036323
return ERR_PTR(-ENOMEM);
6304-
link->link.destroy = &bpf_link__destroy_perf_event;
6324+
link->link.detach = &bpf_link__detach_perf_event;
63056325
link->fd = pfd;
63066326

63076327
if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) {
@@ -6608,7 +6628,7 @@ static struct bpf_link *attach_tp(const struct bpf_sec_def *sec,
66086628
return link;
66096629
}
66106630

6611-
static int bpf_link__destroy_fd(struct bpf_link *link)
6631+
static int bpf_link__detach_fd(struct bpf_link *link)
66126632
{
66136633
struct bpf_link_fd *l = (void *)link;
66146634

@@ -6629,10 +6649,10 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
66296649
return ERR_PTR(-EINVAL);
66306650
}
66316651

6632-
link = malloc(sizeof(*link));
6652+
link = calloc(1, sizeof(*link));
66336653
if (!link)
66346654
return ERR_PTR(-ENOMEM);
6635-
link->link.destroy = &bpf_link__destroy_fd;
6655+
link->link.detach = &bpf_link__detach_fd;
66366656

66376657
pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);
66386658
if (pfd < 0) {
@@ -6668,10 +6688,10 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
66686688
return ERR_PTR(-EINVAL);
66696689
}
66706690

6671-
link = malloc(sizeof(*link));
6691+
link = calloc(1, sizeof(*link));
66726692
if (!link)
66736693
return ERR_PTR(-ENOMEM);
6674-
link->link.destroy = &bpf_link__destroy_fd;
6694+
link->link.detach = &bpf_link__detach_fd;
66756695

66766696
pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
66776697
if (pfd < 0) {

tools/lib/bpf/libbpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
215215

216216
struct bpf_link;
217217

218+
LIBBPF_API void bpf_link__disconnect(struct bpf_link *link);
218219
LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
219220

220221
LIBBPF_API struct bpf_link *

tools/lib/bpf/libbpf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ LIBBPF_0.0.6 {
212212
LIBBPF_0.0.7 {
213213
global:
214214
btf_dump__emit_type_decl;
215+
bpf_link__disconnect;
215216
bpf_object__find_program_by_name;
216217
bpf_object__attach_skeleton;
217218
bpf_object__destroy_skeleton;

0 commit comments

Comments
 (0)