All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next] libbpf: add bpf_link__disconnect() API to preserve underlying BPF resource
@ 2019-12-18 22:50 Andrii Nakryiko
  2019-12-18 23:12 ` [Potential Spoof] " Martin Lau
  0 siblings, 1 reply; 3+ messages in thread
From: Andrii Nakryiko @ 2019-12-18 22:50 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, kafai
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

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 <andriin@fb.com>
---
 tools/lib/bpf/libbpf.c   | 40 ++++++++++++++++++++++++++++++----------
 tools/lib/bpf/libbpf.h   |  1 +
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 906bbbf7b2e4..2a341a5b9f63 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -6245,17 +6245,37 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr,
 }
 
 struct bpf_link {
+	int (*detach)(struct bpf_link *link);
 	int (*destroy)(struct bpf_link *link);
+	bool disconnected;
 };
 
+/* Release "ownership" of underlying BPF resource (typically, BPF program
+ * attached to some BPF hook, e.g., tracepoint, kprobe, etc). Disconnected
+ * link, when destructed through bpf_link__destroy() call won't attempt to
+ * detach/unregisted that BPF resource. This is useful in situations where,
+ * say, attached BPF program has to outlive userspace program that attached it
+ * in the system. Depending on type of BPF program, though, there might be
+ * additional steps (like pinning BPF program in BPF FS) necessary to ensure
+ * exit of userspace program doesn't trigger automatic detachment and clean up
+ * inside the kernel.
+ */
+void bpf_link__disconnect(struct bpf_link *link)
+{
+	link->disconnected = true;
+}
+
 int bpf_link__destroy(struct bpf_link *link)
 {
-	int err;
+	int err = 0;
 
 	if (!link)
 		return 0;
 
-	err = link->destroy(link);
+	if (!link->disconnected && link->detach)
+		err = link->detach(link);
+	if (link->destroy)
+		link->destroy(link);
 	free(link);
 
 	return err;
@@ -6266,7 +6286,7 @@ struct bpf_link_fd {
 	int fd; /* hook FD */
 };
 
-static int bpf_link__destroy_perf_event(struct bpf_link *link)
+static int bpf_link__detach_perf_event(struct bpf_link *link)
 {
 	struct bpf_link_fd *l = (void *)link;
 	int err;
@@ -6298,10 +6318,10 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog,
 		return ERR_PTR(-EINVAL);
 	}
 
-	link = malloc(sizeof(*link));
+	link = calloc(1, sizeof(*link));
 	if (!link)
 		return ERR_PTR(-ENOMEM);
-	link->link.destroy = &bpf_link__destroy_perf_event;
+	link->link.detach = &bpf_link__detach_perf_event;
 	link->fd = pfd;
 
 	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,
 	return link;
 }
 
-static int bpf_link__destroy_fd(struct bpf_link *link)
+static int bpf_link__detach_fd(struct bpf_link *link)
 {
 	struct bpf_link_fd *l = (void *)link;
 
@@ -6629,10 +6649,10 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(struct bpf_program *prog,
 		return ERR_PTR(-EINVAL);
 	}
 
-	link = malloc(sizeof(*link));
+	link = calloc(1, sizeof(*link));
 	if (!link)
 		return ERR_PTR(-ENOMEM);
-	link->link.destroy = &bpf_link__destroy_fd;
+	link->link.detach = &bpf_link__detach_fd;
 
 	pfd = bpf_raw_tracepoint_open(tp_name, prog_fd);
 	if (pfd < 0) {
@@ -6668,10 +6688,10 @@ struct bpf_link *bpf_program__attach_trace(struct bpf_program *prog)
 		return ERR_PTR(-EINVAL);
 	}
 
-	link = malloc(sizeof(*link));
+	link = calloc(1, sizeof(*link));
 	if (!link)
 		return ERR_PTR(-ENOMEM);
-	link->link.destroy = &bpf_link__destroy_fd;
+	link->link.detach = &bpf_link__detach_fd;
 
 	pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
 	if (pfd < 0) {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index f7084235bae9..ad8c1c127933 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -215,6 +215,7 @@ LIBBPF_API void bpf_program__unload(struct bpf_program *prog);
 
 struct bpf_link;
 
+LIBBPF_API void bpf_link__disconnect(struct bpf_link *link);
 LIBBPF_API int bpf_link__destroy(struct bpf_link *link);
 
 LIBBPF_API struct bpf_link *
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 1376d992a703..e3a471f38a71 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -212,6 +212,7 @@ LIBBPF_0.0.6 {
 LIBBPF_0.0.7 {
 	global:
 		btf_dump__emit_type_decl;
+		bpf_link__disconnect;
 		bpf_object__find_program_by_name;
 		bpf_object__attach_skeleton;
 		bpf_object__destroy_skeleton;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Potential Spoof] [PATCH bpf-next] libbpf: add bpf_link__disconnect() API to preserve underlying BPF resource
  2019-12-18 22:50 [PATCH bpf-next] libbpf: add bpf_link__disconnect() API to preserve underlying BPF resource Andrii Nakryiko
@ 2019-12-18 23:12 ` Martin Lau
  2019-12-19  1:19   ` Alexei Starovoitov
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Lau @ 2019-12-18 23:12 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: bpf, netdev, Alexei Starovoitov, daniel, andrii.nakryiko, Kernel Team

On Wed, Dec 18, 2019 at 02:50:39PM -0800, Andrii Nakryiko wrote:
> 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.
Thanks for the patch.

Acked-by: Martin KaFai Lau <kafai@fb.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Potential Spoof] [PATCH bpf-next] libbpf: add bpf_link__disconnect() API to preserve underlying BPF resource
  2019-12-18 23:12 ` [Potential Spoof] " Martin Lau
@ 2019-12-19  1:19   ` Alexei Starovoitov
  0 siblings, 0 replies; 3+ messages in thread
From: Alexei Starovoitov @ 2019-12-19  1:19 UTC (permalink / raw)
  To: Martin Lau
  Cc: Andrii Nakryiko, bpf, netdev, Alexei Starovoitov, daniel,
	andrii.nakryiko, Kernel Team

On Wed, Dec 18, 2019 at 3:13 PM Martin Lau <kafai@fb.com> wrote:
>
> On Wed, Dec 18, 2019 at 02:50:39PM -0800, Andrii Nakryiko wrote:
> > 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.
> Thanks for the patch.
>
> Acked-by: Martin KaFai Lau <kafai@fb.com>

Applied. Thanks

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-12-19  1:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18 22:50 [PATCH bpf-next] libbpf: add bpf_link__disconnect() API to preserve underlying BPF resource Andrii Nakryiko
2019-12-18 23:12 ` [Potential Spoof] " Martin Lau
2019-12-19  1:19   ` Alexei Starovoitov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.