bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments
@ 2022-04-21  3:39 Andrii Nakryiko
  2022-04-21  3:39 ` [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command Andrii Nakryiko
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2022-04-21  3:39 UTC (permalink / raw)
  To: bpf, ast, daniel; +Cc: andrii, kernel-team, Kui-Feng Lee

Wire up ability to attach bpf_link-based fentry/fexit/fmod_ret, tp_btf
(BTF-aware raw tracepoints), and LSM programs through universal LINK_CREATE
command, in addition to current BPF_RAW_TRACEPOINT_OPEN.

Teach libbpf to handle this LINK_CREATE/BPF_RAW_TRACEPOINT_OPEN split on older
kernels transparently in universal low-level bpf_link_create() API for users
convenience.

Patch #3 converts fexit_stress selftest to bpf_link_create().

libbpf CI will be testing this fallback logic on older kernels.

Cc: Kui-Feng Lee <kuifeng@fb.com>

Andrii Nakryiko (3):
  bpf: allow attach TRACING programs through LINK_CREATE command
  libbpf: teach bpf_link_create() to fallback to
    bpf_raw_tracepoint_open()
  selftests/bpf: switch fexit_stress to bpf_link_create() API

 kernel/bpf/syscall.c                          | 110 +++++++++---------
 tools/lib/bpf/bpf.c                           |  34 +++++-
 tools/lib/bpf/libbpf.c                        |   3 +-
 .../selftests/bpf/prog_tests/fexit_stress.c   |   2 +-
 4 files changed, 91 insertions(+), 58 deletions(-)

-- 
2.30.2


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

* [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command
  2022-04-21  3:39 [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments Andrii Nakryiko
@ 2022-04-21  3:39 ` Andrii Nakryiko
  2022-04-22 20:55   ` Kui-Feng Lee
  2022-04-21  3:39 ` [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() Andrii Nakryiko
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Andrii Nakryiko @ 2022-04-21  3:39 UTC (permalink / raw)
  To: bpf, ast, daniel; +Cc: andrii, kernel-team, Kui-Feng Lee

Allow attaching BTF-aware TRACING programs, previously attachable only
through BPF_RAW_TRACEPOINT_OPEN command, through LINK_CREATE command:
  - BTF-aware raw tracepoints (tp_btf in libbpf lingo);
  - fentry/fexit/fmod_ret programs;
  - BPF LSM programs.

This change converges all bpf_link-based attachments under LINK_CREATE
command allowing to further extend the API with features like BPF cookie
under "multiplexed" link_create section of bpf_attr.

Non-BTF-aware raw tracepoints are left under BPF_RAW_TRACEPOINT_OPEN,
but there is nothing preventing opening them up to LINK_CREATE as well.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
---
 kernel/bpf/syscall.c | 110 ++++++++++++++++++++++---------------------
 1 file changed, 56 insertions(+), 54 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e9621cfa09f2..e9e3e49c0eb7 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3030,66 +3030,45 @@ static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *pro
 }
 #endif /* CONFIG_PERF_EVENTS */
 
-#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
-
-static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
+static int bpf_raw_tp_link_attach(struct bpf_prog *prog,
+				  const char __user *user_tp_name)
 {
 	struct bpf_link_primer link_primer;
 	struct bpf_raw_tp_link *link;
 	struct bpf_raw_event_map *btp;
-	struct bpf_prog *prog;
 	const char *tp_name;
 	char buf[128];
 	int err;
 
-	if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
-		return -EINVAL;
-
-	prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
-	if (IS_ERR(prog))
-		return PTR_ERR(prog);
-
 	switch (prog->type) {
 	case BPF_PROG_TYPE_TRACING:
 	case BPF_PROG_TYPE_EXT:
 	case BPF_PROG_TYPE_LSM:
-		if (attr->raw_tracepoint.name) {
+		if (user_tp_name)
 			/* The attach point for this category of programs
 			 * should be specified via btf_id during program load.
 			 */
-			err = -EINVAL;
-			goto out_put_prog;
-		}
+			return -EINVAL;
 		if (prog->type == BPF_PROG_TYPE_TRACING &&
 		    prog->expected_attach_type == BPF_TRACE_RAW_TP) {
 			tp_name = prog->aux->attach_func_name;
 			break;
 		}
-		err = bpf_tracing_prog_attach(prog, 0, 0);
-		if (err >= 0)
-			return err;
-		goto out_put_prog;
+		return bpf_tracing_prog_attach(prog, 0, 0);
 	case BPF_PROG_TYPE_RAW_TRACEPOINT:
 	case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
-		if (strncpy_from_user(buf,
-				      u64_to_user_ptr(attr->raw_tracepoint.name),
-				      sizeof(buf) - 1) < 0) {
-			err = -EFAULT;
-			goto out_put_prog;
-		}
+		if (strncpy_from_user(buf, user_tp_name, sizeof(buf) - 1) < 0)
+			return -EFAULT;
 		buf[sizeof(buf) - 1] = 0;
 		tp_name = buf;
 		break;
 	default:
-		err = -EINVAL;
-		goto out_put_prog;
+		return -EINVAL;
 	}
 
 	btp = bpf_get_raw_tracepoint(tp_name);
-	if (!btp) {
-		err = -ENOENT;
-		goto out_put_prog;
-	}
+	if (!btp)
+		return -ENOENT;
 
 	link = kzalloc(sizeof(*link), GFP_USER);
 	if (!link) {
@@ -3116,11 +3095,29 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
 
 out_put_btp:
 	bpf_put_raw_tracepoint(btp);
-out_put_prog:
-	bpf_prog_put(prog);
 	return err;
 }
 
+#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
+
+static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
+{
+	struct bpf_prog *prog;
+	int fd;
+
+	if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
+		return -EINVAL;
+
+	prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
+	if (IS_ERR(prog))
+		return PTR_ERR(prog);
+
+	fd = bpf_raw_tp_link_attach(prog, u64_to_user_ptr(attr->raw_tracepoint.name));
+	if (fd < 0)
+		bpf_prog_put(prog);
+	return fd;
+}
+
 static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
 					     enum bpf_attach_type attach_type)
 {
@@ -3189,7 +3186,13 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
 	case BPF_CGROUP_SETSOCKOPT:
 		return BPF_PROG_TYPE_CGROUP_SOCKOPT;
 	case BPF_TRACE_ITER:
+	case BPF_TRACE_RAW_TP:
+	case BPF_TRACE_FENTRY:
+	case BPF_TRACE_FEXIT:
+	case BPF_MODIFY_RETURN:
 		return BPF_PROG_TYPE_TRACING;
+	case BPF_LSM_MAC:
+		return BPF_PROG_TYPE_LSM;
 	case BPF_SK_LOOKUP:
 		return BPF_PROG_TYPE_SK_LOOKUP;
 	case BPF_XDP:
@@ -4246,21 +4249,6 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
 	return err;
 }
 
-static int tracing_bpf_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
-				   struct bpf_prog *prog)
-{
-	if (attr->link_create.attach_type != prog->expected_attach_type)
-		return -EINVAL;
-
-	if (prog->expected_attach_type == BPF_TRACE_ITER)
-		return bpf_iter_link_attach(attr, uattr, prog);
-	else if (prog->type == BPF_PROG_TYPE_EXT)
-		return bpf_tracing_prog_attach(prog,
-					       attr->link_create.target_fd,
-					       attr->link_create.target_btf_id);
-	return -EINVAL;
-}
-
 #define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
 static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 {
@@ -4282,15 +4270,13 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 
 	switch (prog->type) {
 	case BPF_PROG_TYPE_EXT:
-		ret = tracing_bpf_link_attach(attr, uattr, prog);
-		goto out;
+		break;
 	case BPF_PROG_TYPE_PERF_EVENT:
 	case BPF_PROG_TYPE_TRACEPOINT:
 		if (attr->link_create.attach_type != BPF_PERF_EVENT) {
 			ret = -EINVAL;
 			goto out;
 		}
-		ptype = prog->type;
 		break;
 	case BPF_PROG_TYPE_KPROBE:
 		if (attr->link_create.attach_type != BPF_PERF_EVENT &&
@@ -4298,7 +4284,6 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 			ret = -EINVAL;
 			goto out;
 		}
-		ptype = prog->type;
 		break;
 	default:
 		ptype = attach_type_to_prog_type(attr->link_create.attach_type);
@@ -4309,7 +4294,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 		break;
 	}
 
-	switch (ptype) {
+	switch (prog->type) {
 	case BPF_PROG_TYPE_CGROUP_SKB:
 	case BPF_PROG_TYPE_CGROUP_SOCK:
 	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
@@ -4319,8 +4304,25 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 	case BPF_PROG_TYPE_CGROUP_SOCKOPT:
 		ret = cgroup_bpf_link_attach(attr, prog);
 		break;
+	case BPF_PROG_TYPE_EXT:
+		ret = bpf_tracing_prog_attach(prog,
+					      attr->link_create.target_fd,
+					      attr->link_create.target_btf_id);
+		break;
+	case BPF_PROG_TYPE_LSM:
 	case BPF_PROG_TYPE_TRACING:
-		ret = tracing_bpf_link_attach(attr, uattr, prog);
+		if (attr->link_create.attach_type != prog->expected_attach_type) {
+			ret = -EINVAL;
+			goto out;
+		}
+		if (prog->expected_attach_type == BPF_TRACE_RAW_TP)
+			ret = bpf_raw_tp_link_attach(prog, NULL);
+		else if (prog->expected_attach_type == BPF_TRACE_ITER)
+			ret = bpf_iter_link_attach(attr, uattr, prog);
+		else
+			ret = bpf_tracing_prog_attach(prog,
+						      attr->link_create.target_fd,
+						      attr->link_create.target_btf_id);
 		break;
 	case BPF_PROG_TYPE_FLOW_DISSECTOR:
 	case BPF_PROG_TYPE_SK_LOOKUP:
-- 
2.30.2


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

* [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open()
  2022-04-21  3:39 [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments Andrii Nakryiko
  2022-04-21  3:39 ` [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command Andrii Nakryiko
@ 2022-04-21  3:39 ` Andrii Nakryiko
  2022-04-22 20:57   ` Kui-Feng Lee
  2022-04-21  3:39 ` [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API Andrii Nakryiko
  2022-04-22 22:40 ` [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments patchwork-bot+netdevbpf
  3 siblings, 1 reply; 8+ messages in thread
From: Andrii Nakryiko @ 2022-04-21  3:39 UTC (permalink / raw)
  To: bpf, ast, daniel; +Cc: andrii, kernel-team, Kui-Feng Lee

Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() on
older kernels for programs that are attachable through
BPF_RAW_TRACEPOINT_OPEN. This makes bpf_link_create() more unified and
convenient interface for creating bpf_link-based attachments.

With this approach end users can just use bpf_link_create() for
tp_btf/fentry/fexit/fmod_ret/lsm program attachments without needing to
care about kernel support, as libbpf will handle this transparently. On
the other hand, as newer features (like BPF cookie) are added to
LINK_CREATE interface, they will be readily usable though the same
bpf_link_create() API without any major refactoring from user's
standpoint.

bpf_program__attach_btf_id() is now using bpf_link_create() internally
as well and will take advantaged of this unified interface when BPF
cookie is added for fentry/fexit.

Doing proactive feature detection of LINK_CREATE support for
fentry/tp_btf/etc is quite involved. It requires parsing vmlinux BTF,
determining some stable and guaranteed to be in all kernels versions
target BTF type (either raw tracepoint or fentry target function),
actually attaching this program and thus potentially affecting the
performance of the host kernel briefly, etc. So instead we are taking
much simpler "lazy" approach of falling back to
bpf_raw_tracepoint_open() call only if initial LINK_CREATE command
fails. For modern kernels this will mean zero added overhead, while
older kernels will incur minimal overhead with a single fast-failing
LINK_CREATE call.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
---
 tools/lib/bpf/bpf.c    | 34 ++++++++++++++++++++++++++++++++--
 tools/lib/bpf/libbpf.c |  3 ++-
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index cf27251adb92..a9d292c106c2 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -817,7 +817,7 @@ int bpf_link_create(int prog_fd, int target_fd,
 {
 	__u32 target_btf_id, iter_info_len;
 	union bpf_attr attr;
-	int fd;
+	int fd, err;
 
 	if (!OPTS_VALID(opts, bpf_link_create_opts))
 		return libbpf_err(-EINVAL);
@@ -870,7 +870,37 @@ int bpf_link_create(int prog_fd, int target_fd,
 	}
 proceed:
 	fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, sizeof(attr));
-	return libbpf_err_errno(fd);
+	if (fd >= 0)
+		return fd;
+	/* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
+	 * and other similar programs
+	 */
+	err = -errno;
+	if (err != -EINVAL)
+		return libbpf_err(err);
+
+	/* if user used features not supported by
+	 * BPF_RAW_TRACEPOINT_OPEN command, then just give up immediately
+	 */
+	if (attr.link_create.target_fd || attr.link_create.target_btf_id)
+		return libbpf_err(err);
+	if (!OPTS_ZEROED(opts, sz))
+		return libbpf_err(err);
+
+	/* otherwise, for few select kinds of programs that can be
+	 * attached using BPF_RAW_TRACEPOINT_OPEN command, try that as
+	 * a fallback for older kernels
+	 */
+	switch (attach_type) {
+	case BPF_TRACE_RAW_TP:
+	case BPF_LSM_MAC:
+	case BPF_TRACE_FENTRY:
+	case BPF_TRACE_FEXIT:
+	case BPF_MODIFY_RETURN:
+		return bpf_raw_tracepoint_open(NULL, prog_fd);
+	default:
+		return libbpf_err(err);
+	}
 }
 
 int bpf_link_detach(int link_fd)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 94940497354b..ae317df1fc57 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -11262,7 +11262,8 @@ static struct bpf_link *bpf_program__attach_btf_id(const struct bpf_program *pro
 		return libbpf_err_ptr(-ENOMEM);
 	link->detach = &bpf_link__detach_fd;
 
-	pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
+	/* libbpf is smart enough to redirect to BPF_RAW_TRACEPOINT_OPEN on old kernels */
+	pfd = bpf_link_create(prog_fd, 0, bpf_program__expected_attach_type(prog), NULL);
 	if (pfd < 0) {
 		pfd = -errno;
 		free(link);
-- 
2.30.2


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

* [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API
  2022-04-21  3:39 [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments Andrii Nakryiko
  2022-04-21  3:39 ` [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command Andrii Nakryiko
  2022-04-21  3:39 ` [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() Andrii Nakryiko
@ 2022-04-21  3:39 ` Andrii Nakryiko
  2022-04-22 21:02   ` Kui-Feng Lee
  2022-04-22 22:40 ` [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments patchwork-bot+netdevbpf
  3 siblings, 1 reply; 8+ messages in thread
From: Andrii Nakryiko @ 2022-04-21  3:39 UTC (permalink / raw)
  To: bpf, ast, daniel; +Cc: andrii, kernel-team, Kui-Feng Lee

Use bpf_link_create() API in fexit_stress test to attach FEXIT programs.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
---
 tools/testing/selftests/bpf/prog_tests/fexit_stress.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_stress.c b/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
index 3ee2107bbf7a..fe1f0f26ea14 100644
--- a/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
+++ b/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
@@ -53,7 +53,7 @@ void test_fexit_stress(void)
 					    &trace_opts);
 		if (!ASSERT_GE(fexit_fd[i], 0, "fexit load"))
 			goto out;
-		link_fd[i] = bpf_raw_tracepoint_open(NULL, fexit_fd[i]);
+		link_fd[i] = bpf_link_create(fexit_fd[i], 0, BPF_TRACE_FEXIT, NULL);
 		if (!ASSERT_GE(link_fd[i], 0, "fexit attach"))
 			goto out;
 	}
-- 
2.30.2


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

* Re: [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command
  2022-04-21  3:39 ` [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command Andrii Nakryiko
@ 2022-04-22 20:55   ` Kui-Feng Lee
  0 siblings, 0 replies; 8+ messages in thread
From: Kui-Feng Lee @ 2022-04-22 20:55 UTC (permalink / raw)
  To: daniel, ast, andrii, bpf; +Cc: Kernel Team

On Wed, 2022-04-20 at 20:39 -0700, Andrii Nakryiko wrote:
> Allow attaching BTF-aware TRACING programs, previously attachable only
> through BPF_RAW_TRACEPOINT_OPEN command, through LINK_CREATE command:
>   - BTF-aware raw tracepoints (tp_btf in libbpf lingo);
>   - fentry/fexit/fmod_ret programs;
>   - BPF LSM programs.
> 
> This change converges all bpf_link-based attachments under LINK_CREATE
> command allowing to further extend the API with features like BPF
> cookie
> under "multiplexed" link_create section of bpf_attr.
> 
> Non-BTF-aware raw tracepoints are left under BPF_RAW_TRACEPOINT_OPEN,
> but there is nothing preventing opening them up to LINK_CREATE as well.
> 
> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

Reviewed-by: Kuifeng Lee <kuifeng@fb.com>

LGTM

> ---
>  kernel/bpf/syscall.c | 110 ++++++++++++++++++++++---------------------
>  1 file changed, 56 insertions(+), 54 deletions(-)
> 
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index e9621cfa09f2..e9e3e49c0eb7 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -3030,66 +3030,45 @@ static int bpf_perf_link_attach(const union
> bpf_attr *attr, struct bpf_prog *pro
>  }
>  #endif /* CONFIG_PERF_EVENTS */
>  
> -#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
> -
> -static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
> +static int bpf_raw_tp_link_attach(struct bpf_prog *prog,
> +                                 const char __user *user_tp_name)
>  {
>         struct bpf_link_primer link_primer;
>         struct bpf_raw_tp_link *link;
>         struct bpf_raw_event_map *btp;
> -       struct bpf_prog *prog;
>         const char *tp_name;
>         char buf[128];
>         int err;
>  
> -       if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
> -               return -EINVAL;
> -
> -       prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
> -       if (IS_ERR(prog))
> -               return PTR_ERR(prog);
> -
>         switch (prog->type) {
>         case BPF_PROG_TYPE_TRACING:
>         case BPF_PROG_TYPE_EXT:
>         case BPF_PROG_TYPE_LSM:
> -               if (attr->raw_tracepoint.name) {
> +               if (user_tp_name)
>                         /* The attach point for this category of
> programs
>                          * should be specified via btf_id during
> program load.
>                          */
> -                       err = -EINVAL;
> -                       goto out_put_prog;
> -               }
> +                       return -EINVAL;
>                 if (prog->type == BPF_PROG_TYPE_TRACING &&
>                     prog->expected_attach_type == BPF_TRACE_RAW_TP) {
>                         tp_name = prog->aux->attach_func_name;
>                         break;
>                 }
> -               err = bpf_tracing_prog_attach(prog, 0, 0);
> -               if (err >= 0)
> -                       return err;
> -               goto out_put_prog;
> +               return bpf_tracing_prog_attach(prog, 0, 0);
>         case BPF_PROG_TYPE_RAW_TRACEPOINT:
>         case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
> -               if (strncpy_from_user(buf,
> -                                     u64_to_user_ptr(attr-
> >raw_tracepoint.name),
> -                                     sizeof(buf) - 1) < 0) {
> -                       err = -EFAULT;
> -                       goto out_put_prog;
> -               }
> +               if (strncpy_from_user(buf, user_tp_name, sizeof(buf) -
> 1) < 0)
> +                       return -EFAULT;
>                 buf[sizeof(buf) - 1] = 0;
>                 tp_name = buf;
>                 break;
>         default:
> -               err = -EINVAL;
> -               goto out_put_prog;
> +               return -EINVAL;
>         }
>  
>         btp = bpf_get_raw_tracepoint(tp_name);
> -       if (!btp) {
> -               err = -ENOENT;
> -               goto out_put_prog;
> -       }
> +       if (!btp)
> +               return -ENOENT;
>  
>         link = kzalloc(sizeof(*link), GFP_USER);
>         if (!link) {
> @@ -3116,11 +3095,29 @@ static int bpf_raw_tracepoint_open(const union
> bpf_attr *attr)
>  
>  out_put_btp:
>         bpf_put_raw_tracepoint(btp);
> -out_put_prog:
> -       bpf_prog_put(prog);
>         return err;
>  }
>  
> +#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
> +
> +static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
> +{
> +       struct bpf_prog *prog;
> +       int fd;
> +
> +       if (CHECK_ATTR(BPF_RAW_TRACEPOINT_OPEN))
> +               return -EINVAL;
> +
> +       prog = bpf_prog_get(attr->raw_tracepoint.prog_fd);
> +       if (IS_ERR(prog))
> +               return PTR_ERR(prog);
> +
> +       fd = bpf_raw_tp_link_attach(prog, u64_to_user_ptr(attr-
> >raw_tracepoint.name));
> +       if (fd < 0)
> +               bpf_prog_put(prog);
> +       return fd;
> +}
> +
>  static int bpf_prog_attach_check_attach_type(const struct bpf_prog
> *prog,
>                                              enum bpf_attach_type
> attach_type)
>  {
> @@ -3189,7 +3186,13 @@ attach_type_to_prog_type(enum bpf_attach_type
> attach_type)
>         case BPF_CGROUP_SETSOCKOPT:
>                 return BPF_PROG_TYPE_CGROUP_SOCKOPT;
>         case BPF_TRACE_ITER:
> +       case BPF_TRACE_RAW_TP:
> +       case BPF_TRACE_FENTRY:
> +       case BPF_TRACE_FEXIT:
> +       case BPF_MODIFY_RETURN:
>                 return BPF_PROG_TYPE_TRACING;
> +       case BPF_LSM_MAC:
> +               return BPF_PROG_TYPE_LSM;
>         case BPF_SK_LOOKUP:
>                 return BPF_PROG_TYPE_SK_LOOKUP;
>         case BPF_XDP:
> @@ -4246,21 +4249,6 @@ static int bpf_map_do_batch(const union bpf_attr
> *attr,
>         return err;
>  }
>  
> -static int tracing_bpf_link_attach(const union bpf_attr *attr,
> bpfptr_t uattr,
> -                                  struct bpf_prog *prog)
> -{
> -       if (attr->link_create.attach_type != prog-
> >expected_attach_type)
> -               return -EINVAL;
> -
> -       if (prog->expected_attach_type == BPF_TRACE_ITER)
> -               return bpf_iter_link_attach(attr, uattr, prog);
> -       else if (prog->type == BPF_PROG_TYPE_EXT)
> -               return bpf_tracing_prog_attach(prog,
> -                                              attr-
> >link_create.target_fd,
> -                                              attr-
> >link_create.target_btf_id);
> -       return -EINVAL;
> -}
> -
>  #define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
>  static int link_create(union bpf_attr *attr, bpfptr_t uattr)
>  {
> @@ -4282,15 +4270,13 @@ static int link_create(union bpf_attr *attr,
> bpfptr_t uattr)
>  
>         switch (prog->type) {
>         case BPF_PROG_TYPE_EXT:
> -               ret = tracing_bpf_link_attach(attr, uattr, prog);
> -               goto out;
> +               break;
>         case BPF_PROG_TYPE_PERF_EVENT:
>         case BPF_PROG_TYPE_TRACEPOINT:
>                 if (attr->link_create.attach_type != BPF_PERF_EVENT) {
>                         ret = -EINVAL;
>                         goto out;
>                 }
> -               ptype = prog->type;
>                 break;
>         case BPF_PROG_TYPE_KPROBE:
>                 if (attr->link_create.attach_type != BPF_PERF_EVENT &&
> @@ -4298,7 +4284,6 @@ static int link_create(union bpf_attr *attr,
> bpfptr_t uattr)
>                         ret = -EINVAL;
>                         goto out;
>                 }
> -               ptype = prog->type;
>                 break;
>         default:
>                 ptype = attach_type_to_prog_type(attr-
> >link_create.attach_type);
> @@ -4309,7 +4294,7 @@ static int link_create(union bpf_attr *attr,
> bpfptr_t uattr)
>                 break;
>         }
>  
> -       switch (ptype) {
> +       switch (prog->type) {
>         case BPF_PROG_TYPE_CGROUP_SKB:
>         case BPF_PROG_TYPE_CGROUP_SOCK:
>         case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
> @@ -4319,8 +4304,25 @@ static int link_create(union bpf_attr *attr,
> bpfptr_t uattr)
>         case BPF_PROG_TYPE_CGROUP_SOCKOPT:
>                 ret = cgroup_bpf_link_attach(attr, prog);
>                 break;
> +       case BPF_PROG_TYPE_EXT:
> +               ret = bpf_tracing_prog_attach(prog,
> +                                             attr-
> >link_create.target_fd,
> +                                             attr-
> >link_create.target_btf_id);
> +               break;
> +       case BPF_PROG_TYPE_LSM:
>         case BPF_PROG_TYPE_TRACING:
> -               ret = tracing_bpf_link_attach(attr, uattr, prog);
> +               if (attr->link_create.attach_type != prog-
> >expected_attach_type) {
> +                       ret = -EINVAL;
> +                       goto out;
> +               }
> +               if (prog->expected_attach_type == BPF_TRACE_RAW_TP)
> +                       ret = bpf_raw_tp_link_attach(prog, NULL);
> +               else if (prog->expected_attach_type == BPF_TRACE_ITER)
> +                       ret = bpf_iter_link_attach(attr, uattr, prog);
> +               else
> +                       ret = bpf_tracing_prog_attach(prog,
> +                                                     attr-
> >link_create.target_fd,
> +                                                     attr-
> >link_create.target_btf_id);
>                 break;
>         case BPF_PROG_TYPE_FLOW_DISSECTOR:
>         case BPF_PROG_TYPE_SK_LOOKUP:


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

* Re: [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open()
  2022-04-21  3:39 ` [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() Andrii Nakryiko
@ 2022-04-22 20:57   ` Kui-Feng Lee
  0 siblings, 0 replies; 8+ messages in thread
From: Kui-Feng Lee @ 2022-04-22 20:57 UTC (permalink / raw)
  To: daniel, ast, andrii, bpf; +Cc: Kernel Team

On Wed, 2022-04-20 at 20:39 -0700, Andrii Nakryiko wrote:
> Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() on
> older kernels for programs that are attachable through
> BPF_RAW_TRACEPOINT_OPEN. This makes bpf_link_create() more unified
> and
> convenient interface for creating bpf_link-based attachments.
> 
> With this approach end users can just use bpf_link_create() for
> tp_btf/fentry/fexit/fmod_ret/lsm program attachments without needing
> to
> care about kernel support, as libbpf will handle this transparently.
> On
> the other hand, as newer features (like BPF cookie) are added to
> LINK_CREATE interface, they will be readily usable though the same
> bpf_link_create() API without any major refactoring from user's
> standpoint.
> 
> bpf_program__attach_btf_id() is now using bpf_link_create()
> internally
> as well and will take advantaged of this unified interface when BPF
> cookie is added for fentry/fexit.
> 
> Doing proactive feature detection of LINK_CREATE support for
> fentry/tp_btf/etc is quite involved. It requires parsing vmlinux BTF,
> determining some stable and guaranteed to be in all kernels versions
> target BTF type (either raw tracepoint or fentry target function),
> actually attaching this program and thus potentially affecting the
> performance of the host kernel briefly, etc. So instead we are taking
> much simpler "lazy" approach of falling back to
> bpf_raw_tracepoint_open() call only if initial LINK_CREATE command
> fails. For modern kernels this will mean zero added overhead, while
> older kernels will incur minimal overhead with a single fast-failing
> LINK_CREATE call.
> 
> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

Reviewed-by: Kui-Feng Lee <kuifeng@fb.com>

This is very straight forward.

> ---
>  tools/lib/bpf/bpf.c    | 34 ++++++++++++++++++++++++++++++++--
>  tools/lib/bpf/libbpf.c |  3 ++-
>  2 files changed, 34 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
> index cf27251adb92..a9d292c106c2 100644
> --- a/tools/lib/bpf/bpf.c
> +++ b/tools/lib/bpf/bpf.c
> @@ -817,7 +817,7 @@ int bpf_link_create(int prog_fd, int target_fd,
>  {
>         __u32 target_btf_id, iter_info_len;
>         union bpf_attr attr;
> -       int fd;
> +       int fd, err;
>  
>         if (!OPTS_VALID(opts, bpf_link_create_opts))
>                 return libbpf_err(-EINVAL);
> @@ -870,7 +870,37 @@ int bpf_link_create(int prog_fd, int target_fd,
>         }
>  proceed:
>         fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, sizeof(attr));
> -       return libbpf_err_errno(fd);
> +       if (fd >= 0)
> +               return fd;
> +       /* we'll get EINVAL if LINK_CREATE doesn't support attaching
> fentry
> +        * and other similar programs
> +        */
> +       err = -errno;
> +       if (err != -EINVAL)
> +               return libbpf_err(err);
> +
> +       /* if user used features not supported by
> +        * BPF_RAW_TRACEPOINT_OPEN command, then just give up
> immediately
> +        */
> +       if (attr.link_create.target_fd ||
> attr.link_create.target_btf_id)
> +               return libbpf_err(err);
> +       if (!OPTS_ZEROED(opts, sz))
> +               return libbpf_err(err);
> +
> +       /* otherwise, for few select kinds of programs that can be
> +        * attached using BPF_RAW_TRACEPOINT_OPEN command, try that
> as
> +        * a fallback for older kernels
> +        */
> +       switch (attach_type) {
> +       case BPF_TRACE_RAW_TP:
> +       case BPF_LSM_MAC:
> +       case BPF_TRACE_FENTRY:
> +       case BPF_TRACE_FEXIT:
> +       case BPF_MODIFY_RETURN:
> +               return bpf_raw_tracepoint_open(NULL, prog_fd);
> +       default:
> +               return libbpf_err(err);
> +       }
>  }
>  
>  int bpf_link_detach(int link_fd)
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 94940497354b..ae317df1fc57 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -11262,7 +11262,8 @@ static struct bpf_link
> *bpf_program__attach_btf_id(const struct bpf_program *pro
>                 return libbpf_err_ptr(-ENOMEM);
>         link->detach = &bpf_link__detach_fd;
>  
> -       pfd = bpf_raw_tracepoint_open(NULL, prog_fd);
> +       /* libbpf is smart enough to redirect to
> BPF_RAW_TRACEPOINT_OPEN on old kernels */
> +       pfd = bpf_link_create(prog_fd, 0,
> bpf_program__expected_attach_type(prog), NULL);
>         if (pfd < 0) {
>                 pfd = -errno;
>                 free(link);


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

* Re: [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API
  2022-04-21  3:39 ` [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API Andrii Nakryiko
@ 2022-04-22 21:02   ` Kui-Feng Lee
  0 siblings, 0 replies; 8+ messages in thread
From: Kui-Feng Lee @ 2022-04-22 21:02 UTC (permalink / raw)
  To: daniel, ast, andrii, bpf; +Cc: Kernel Team

On Wed, 2022-04-20 at 20:39 -0700, Andrii Nakryiko wrote:
> Use bpf_link_create() API in fexit_stress test to attach FEXIT
> programs.
> 
> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

Reviewed-by: Kui-Feng Lee <kuifeng@fb.com>


> ---
>  tools/testing/selftests/bpf/prog_tests/fexit_stress.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
> b/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
> index 3ee2107bbf7a..fe1f0f26ea14 100644
> --- a/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
> +++ b/tools/testing/selftests/bpf/prog_tests/fexit_stress.c
> @@ -53,7 +53,7 @@ void test_fexit_stress(void)
>                                             &trace_opts);
>                 if (!ASSERT_GE(fexit_fd[i], 0, "fexit load"))
>                         goto out;
> -               link_fd[i] = bpf_raw_tracepoint_open(NULL,
> fexit_fd[i]);
> +               link_fd[i] = bpf_link_create(fexit_fd[i], 0,
> BPF_TRACE_FEXIT, NULL);
>                 if (!ASSERT_GE(link_fd[i], 0, "fexit attach"))
>                         goto out;
>         }


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

* Re: [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments
  2022-04-21  3:39 [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments Andrii Nakryiko
                   ` (2 preceding siblings ...)
  2022-04-21  3:39 ` [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API Andrii Nakryiko
@ 2022-04-22 22:40 ` patchwork-bot+netdevbpf
  3 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-04-22 22:40 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: bpf, ast, daniel, kernel-team, kuifeng

Hello:

This series was applied to bpf/bpf-next.git (master)
by Daniel Borkmann <daniel@iogearbox.net>:

On Wed, 20 Apr 2022 20:39:42 -0700 you wrote:
> Wire up ability to attach bpf_link-based fentry/fexit/fmod_ret, tp_btf
> (BTF-aware raw tracepoints), and LSM programs through universal LINK_CREATE
> command, in addition to current BPF_RAW_TRACEPOINT_OPEN.
> 
> Teach libbpf to handle this LINK_CREATE/BPF_RAW_TRACEPOINT_OPEN split on older
> kernels transparently in universal low-level bpf_link_create() API for users
> convenience.
> 
> [...]

Here is the summary with links:
  - [bpf-next,1/3] bpf: allow attach TRACING programs through LINK_CREATE command
    https://git.kernel.org/bpf/bpf-next/c/df86ca0d2f0f
  - [bpf-next,2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open()
    https://git.kernel.org/bpf/bpf-next/c/8462e0b46fe2
  - [bpf-next,3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API
    https://git.kernel.org/bpf/bpf-next/c/fd0493a1e49e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2022-04-22 23:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-21  3:39 [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments Andrii Nakryiko
2022-04-21  3:39 ` [PATCH bpf-next 1/3] bpf: allow attach TRACING programs through LINK_CREATE command Andrii Nakryiko
2022-04-22 20:55   ` Kui-Feng Lee
2022-04-21  3:39 ` [PATCH bpf-next 2/3] libbpf: teach bpf_link_create() to fallback to bpf_raw_tracepoint_open() Andrii Nakryiko
2022-04-22 20:57   ` Kui-Feng Lee
2022-04-21  3:39 ` [PATCH bpf-next 3/3] selftests/bpf: switch fexit_stress to bpf_link_create() API Andrii Nakryiko
2022-04-22 21:02   ` Kui-Feng Lee
2022-04-22 22:40 ` [PATCH bpf-next 0/3] LINK_CREATE support for fentry/tp_btf/lsm attachments patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).