From: Roberto Sassu <[email protected]>
Add the _opts variant for bpf_*_get_fd_by_id() functions, to be able to
pass to the kernel more options, when requesting a fd of an eBPF object.
Pass the options through a newly introduced structure,
bpf_get_fd_by_id_opts, which currently contains open_flags (the other two
members are for compatibility and for padding).
open_flags allows the caller to request specific permissions to access a
map (e.g. read-only). This is useful for example in the situation where a
map is write-protected.
Besides patches 2-6, which introduce the new variants and the data
structure, patch 1 fixes the LIBBPF_1.0.0 declaration in libbpf.map.
Changelog
v1:
- Don't CC stable kernel mailing list for patch 1 (suggested by Andrii)
- Rename bpf_get_fd_opts struct to bpf_get_fd_by_id_opts (suggested by
Andrii)
- Move declaration of _opts variants after non-opts variants (suggested by
Andrii)
- Correctly initialize bpf_map_info, fix style issues, use map from
skeleton, check valid fd in the test (suggested by Andrii)
- Rename libbpf_get_fd_opts test to libbpf_get_fd_by_id_opts
Roberto Sassu (6):
libbpf: Fix LIBBPF_1.0.0 declaration in libbpf.map
libbpf: Introduce bpf_get_fd_by_id_opts and
bpf_map_get_fd_by_id_opts()
libbpf: Introduce bpf_prog_get_fd_by_id_opts()
libbpf: Introduce bpf_btf_get_fd_by_id_opts()
libbpf: Introduce bpf_link_get_fd_by_id_opts()
selftests/bpf: Add tests for _opts variants of bpf_*_get_fd_by_id()
tools/lib/bpf/bpf.c | 48 +++++++++-
tools/lib/bpf/bpf.h | 16 ++++
tools/lib/bpf/libbpf.map | 6 +-
tools/testing/selftests/bpf/DENYLIST.s390x | 1 +
.../bpf/prog_tests/libbpf_get_fd_by_id_opts.c | 87 +++++++++++++++++++
.../bpf/progs/test_libbpf_get_fd_by_id_opts.c | 36 ++++++++
6 files changed, 189 insertions(+), 5 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
create mode 100644 tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
--
2.25.1
From: Roberto Sassu <[email protected]>
Introduce the data_input map, write-protected with a small eBPF program
implementing the lsm/bpf_map hook.
Then, ensure that bpf_map_get_fd_by_id() and bpf_map_get_fd_by_id_opts()
with NULL opts don't succeed due to requesting read-write access to the
write-protected map. Also, ensure that bpf_map_get_fd_by_id_opts() with
open_flags in opts set to BPF_F_RDONLY instead succeeds.
After obtaining a read-only fd, ensure that only map lookup succeeds and
not update. Ensure that update works only with the read-write fd obtained
at program loading time, when the write protection was not yet enabled.
Finally, ensure that the other _opts variants of bpf_*_get_fd_by_id() don't
work if the BPF_F_RDONLY flag is set in opts (due to the kernel not
handling the open_flags member of bpf_attr).
Signed-off-by: Roberto Sassu <[email protected]>
---
tools/testing/selftests/bpf/DENYLIST.s390x | 1 +
.../bpf/prog_tests/libbpf_get_fd_by_id_opts.c | 87 +++++++++++++++++++
.../bpf/progs/test_libbpf_get_fd_by_id_opts.c | 36 ++++++++
3 files changed, 124 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
create mode 100644 tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
diff --git a/tools/testing/selftests/bpf/DENYLIST.s390x b/tools/testing/selftests/bpf/DENYLIST.s390x
index 17e074eb42b8..f3a56dcc4eec 100644
--- a/tools/testing/selftests/bpf/DENYLIST.s390x
+++ b/tools/testing/selftests/bpf/DENYLIST.s390x
@@ -75,3 +75,4 @@ user_ringbuf # failed to find kernel BTF type ID of
lookup_key # JIT does not support calling kernel function (kfunc)
verify_pkcs7_sig # JIT does not support calling kernel function (kfunc)
kfunc_dynptr_param # JIT does not support calling kernel function (kfunc)
+libbpf_get_fd_by_id_opts # failed to attach: ERROR: strerror_r(-524)=22 (trampoline)
diff --git a/tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c b/tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
new file mode 100644
index 000000000000..25e5dfa9c315
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <[email protected]>
+ */
+
+#include <test_progs.h>
+
+#include "test_libbpf_get_fd_by_id_opts.skel.h"
+
+void test_libbpf_get_fd_by_id_opts(void)
+{
+ struct test_libbpf_get_fd_by_id_opts *skel;
+ struct bpf_map_info info_m = {};
+ __u32 len = sizeof(info_m), value;
+ int ret, zero = 0, fd = -1;
+ LIBBPF_OPTS(bpf_get_fd_by_id_opts, fd_opts_rdonly,
+ .open_flags = BPF_F_RDONLY,
+ );
+
+ skel = test_libbpf_get_fd_by_id_opts__open_and_load();
+ if (!ASSERT_OK_PTR(skel,
+ "test_libbpf_get_fd_by_id_opts__open_and_load"))
+ return;
+
+ ret = test_libbpf_get_fd_by_id_opts__attach(skel);
+ if (!ASSERT_OK(ret, "test_libbpf_get_fd_by_id_opts__attach"))
+ goto close_prog;
+
+ ret = bpf_obj_get_info_by_fd(bpf_map__fd(skel->maps.data_input),
+ &info_m, &len);
+ if (!ASSERT_OK(ret, "bpf_obj_get_info_by_fd"))
+ goto close_prog;
+
+ fd = bpf_map_get_fd_by_id(info_m.id);
+ if (!ASSERT_LT(fd, 0, "bpf_map_get_fd_by_id"))
+ goto close_prog;
+
+ fd = bpf_map_get_fd_by_id_opts(info_m.id, NULL);
+ if (!ASSERT_LT(fd, 0, "bpf_map_get_fd_by_id_opts"))
+ goto close_prog;
+
+ fd = bpf_map_get_fd_by_id_opts(info_m.id, &fd_opts_rdonly);
+ if (!ASSERT_GE(fd, 0, "bpf_map_get_fd_by_id_opts"))
+ goto close_prog;
+
+ /* Map lookup should work with read-only fd. */
+ ret = bpf_map_lookup_elem(fd, &zero, &value);
+ if (!ASSERT_OK(ret, "bpf_map_lookup_elem"))
+ goto close_prog;
+
+ if (!ASSERT_EQ(value, 0, "map value mismatch"))
+ goto close_prog;
+
+ /* Map update should not work with read-only fd. */
+ ret = bpf_map_update_elem(fd, &zero, &len, BPF_ANY);
+ if (!ASSERT_LT(ret, 0, "bpf_map_update_elem"))
+ goto close_prog;
+
+ /* Map update should work with read-write fd. */
+ ret = bpf_map_update_elem(bpf_map__fd(skel->maps.data_input), &zero,
+ &len, BPF_ANY);
+ if (!ASSERT_OK(ret, "bpf_map_update_elem"))
+ goto close_prog;
+
+ /* Prog get fd with opts set should not work (no kernel support). */
+ ret = bpf_prog_get_fd_by_id_opts(0, &fd_opts_rdonly);
+ if (!ASSERT_EQ(ret, -EINVAL, "bpf_prog_get_fd_by_id_opts"))
+ goto close_prog;
+
+ /* Link get fd with opts set should not work (no kernel support). */
+ ret = bpf_link_get_fd_by_id_opts(0, &fd_opts_rdonly);
+ if (!ASSERT_EQ(ret, -EINVAL, "bpf_link_get_fd_by_id_opts"))
+ goto close_prog;
+
+ /* BTF get fd with opts set should not work (no kernel support). */
+ ret = bpf_btf_get_fd_by_id_opts(0, &fd_opts_rdonly);
+ ASSERT_EQ(ret, -EINVAL, "bpf_btf_get_fd_by_id_opts");
+
+close_prog:
+ if (fd >= 0)
+ close(fd);
+
+ test_libbpf_get_fd_by_id_opts__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
new file mode 100644
index 000000000000..f5ac5f3e8919
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <[email protected]>
+ */
+
+#include "vmlinux.h"
+#include <errno.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+/* From include/linux/mm.h. */
+#define FMODE_WRITE 0x2
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 1);
+ __type(key, __u32);
+ __type(value, __u32);
+} data_input SEC(".maps");
+
+char _license[] SEC("license") = "GPL";
+
+SEC("lsm/bpf_map")
+int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode)
+{
+ if (map != (struct bpf_map *)&data_input)
+ return 0;
+
+ if (fmode & FMODE_WRITE)
+ return -EACCES;
+
+ return 0;
+}
--
2.25.1
From: Roberto Sassu <[email protected]>
Introduce bpf_prog_get_fd_by_id_opts(), for symmetry with
bpf_map_get_fd_by_id_opts(), to let the caller pass the newly introduced
data structure bpf_get_fd_by_id_opts. Keep the existing
bpf_prog_get_fd_by_id(), and call bpf_prog_get_fd_by_id_opts() with NULL as
opts argument, to prevent setting open_flags.
Currently, the kernel does not support non-zero open_flags for
bpf_prog_get_fd_by_id_opts(), and a call with them will result in an error
returned by the bpf() system call. The caller should always pass zero
open_flags.
Signed-off-by: Roberto Sassu <[email protected]>
---
tools/lib/bpf/bpf.c | 12 +++++++++++-
tools/lib/bpf/bpf.h | 2 ++
tools/lib/bpf/libbpf.map | 1 +
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index c08d7509553d..03be8c96bbac 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -935,19 +935,29 @@ int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
}
-int bpf_prog_get_fd_by_id(__u32 id)
+int bpf_prog_get_fd_by_id_opts(__u32 id,
+ const struct bpf_get_fd_by_id_opts *opts)
{
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
union bpf_attr attr;
int fd;
+ if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
+ return libbpf_err(-EINVAL);
+
memset(&attr, 0, attr_sz);
attr.prog_id = id;
+ attr.open_flags = OPTS_GET(opts, open_flags, 0);
fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
return libbpf_err_errno(fd);
}
+int bpf_prog_get_fd_by_id(__u32 id)
+{
+ return bpf_prog_get_fd_by_id_opts(id, NULL);
+}
+
int bpf_map_get_fd_by_id_opts(__u32 id,
const struct bpf_get_fd_by_id_opts *opts)
{
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 10ce38f0a9ef..4558bafbce14 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -374,6 +374,8 @@ struct bpf_get_fd_by_id_opts {
#define bpf_get_fd_by_id_opts__last_field open_flags
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
+LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
+ const struct bpf_get_fd_by_id_opts *opts);
LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_map_get_fd_by_id_opts(__u32 id,
const struct bpf_get_fd_by_id_opts *opts);
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 2e665b21d84f..c3604eaa220d 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -372,6 +372,7 @@ LIBBPF_1.0.0 {
LIBBPF_1.1.0 {
global:
bpf_map_get_fd_by_id_opts;
+ bpf_prog_get_fd_by_id_opts;
user_ring_buffer__discard;
user_ring_buffer__free;
user_ring_buffer__new;
--
2.25.1
On Thu, Oct 06, 2022 at 01:07:30PM +0200, Roberto Sassu wrote:
> From: Roberto Sassu <[email protected]>
>
> Add the _opts variant for bpf_*_get_fd_by_id() functions, to be able to
> pass to the kernel more options, when requesting a fd of an eBPF object.
>
> Pass the options through a newly introduced structure,
> bpf_get_fd_by_id_opts, which currently contains open_flags (the other two
> members are for compatibility and for padding).
>
> open_flags allows the caller to request specific permissions to access a
> map (e.g. read-only). This is useful for example in the situation where a
> map is write-protected.
>
> Besides patches 2-6, which introduce the new variants and the data
> structure, patch 1 fixes the LIBBPF_1.0.0 declaration in libbpf.map.
>
> Changelog
>
> v1:
> - Don't CC stable kernel mailing list for patch 1 (suggested by Andrii)
> - Rename bpf_get_fd_opts struct to bpf_get_fd_by_id_opts (suggested by
> Andrii)
> - Move declaration of _opts variants after non-opts variants (suggested by
> Andrii)
> - Correctly initialize bpf_map_info, fix style issues, use map from
> skeleton, check valid fd in the test (suggested by Andrii)
> - Rename libbpf_get_fd_opts test to libbpf_get_fd_by_id_opts
>
> Roberto Sassu (6):
> libbpf: Fix LIBBPF_1.0.0 declaration in libbpf.map
> libbpf: Introduce bpf_get_fd_by_id_opts and
> bpf_map_get_fd_by_id_opts()
> libbpf: Introduce bpf_prog_get_fd_by_id_opts()
> libbpf: Introduce bpf_btf_get_fd_by_id_opts()
> libbpf: Introduce bpf_link_get_fd_by_id_opts()
> selftests/bpf: Add tests for _opts variants of bpf_*_get_fd_by_id()
it's not marked, but I'm assuming this goes to bpf-next, right?
anyway, lgtm
Acked-by: Jiri Olsa <[email protected]>
thanks,
jirka
>
> tools/lib/bpf/bpf.c | 48 +++++++++-
> tools/lib/bpf/bpf.h | 16 ++++
> tools/lib/bpf/libbpf.map | 6 +-
> tools/testing/selftests/bpf/DENYLIST.s390x | 1 +
> .../bpf/prog_tests/libbpf_get_fd_by_id_opts.c | 87 +++++++++++++++++++
> .../bpf/progs/test_libbpf_get_fd_by_id_opts.c | 36 ++++++++
> 6 files changed, 189 insertions(+), 5 deletions(-)
> create mode 100644 tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
> create mode 100644 tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
>
> --
> 2.25.1
>
On Fri, 2022-10-07 at 12:59 +0200, Jiri Olsa wrote:
> On Thu, Oct 06, 2022 at 01:07:30PM +0200, Roberto Sassu wrote:
> > From: Roberto Sassu <[email protected]>
> >
> > Add the _opts variant for bpf_*_get_fd_by_id() functions, to be
> > able to
> > pass to the kernel more options, when requesting a fd of an eBPF
> > object.
> >
> > Pass the options through a newly introduced structure,
> > bpf_get_fd_by_id_opts, which currently contains open_flags (the
> > other two
> > members are for compatibility and for padding).
> >
> > open_flags allows the caller to request specific permissions to
> > access a
> > map (e.g. read-only). This is useful for example in the situation
> > where a
> > map is write-protected.
> >
> > Besides patches 2-6, which introduce the new variants and the data
> > structure, patch 1 fixes the LIBBPF_1.0.0 declaration in
> > libbpf.map.
> >
> > Changelog
> >
> > v1:
> > - Don't CC stable kernel mailing list for patch 1 (suggested by
> > Andrii)
> > - Rename bpf_get_fd_opts struct to bpf_get_fd_by_id_opts
> > (suggested by
> > Andrii)
> > - Move declaration of _opts variants after non-opts variants
> > (suggested by
> > Andrii)
> > - Correctly initialize bpf_map_info, fix style issues, use map
> > from
> > skeleton, check valid fd in the test (suggested by Andrii)
> > - Rename libbpf_get_fd_opts test to libbpf_get_fd_by_id_opts
> >
> > Roberto Sassu (6):
> > libbpf: Fix LIBBPF_1.0.0 declaration in libbpf.map
> > libbpf: Introduce bpf_get_fd_by_id_opts and
> > bpf_map_get_fd_by_id_opts()
> > libbpf: Introduce bpf_prog_get_fd_by_id_opts()
> > libbpf: Introduce bpf_btf_get_fd_by_id_opts()
> > libbpf: Introduce bpf_link_get_fd_by_id_opts()
> > selftests/bpf: Add tests for _opts variants of
> > bpf_*_get_fd_by_id()
>
> it's not marked, but I'm assuming this goes to bpf-next, right?
At the next possible chance would be perfect.
> anyway, lgtm
>
> Acked-by: Jiri Olsa <[email protected]>
Thanks
Roberto
> thanks,
> jirka
>
> > tools/lib/bpf/bpf.c | 48 +++++++++-
> > tools/lib/bpf/bpf.h | 16 ++++
> > tools/lib/bpf/libbpf.map | 6 +-
> > tools/testing/selftests/bpf/DENYLIST.s390x | 1 +
> > .../bpf/prog_tests/libbpf_get_fd_by_id_opts.c | 87
> > +++++++++++++++++++
> > .../bpf/progs/test_libbpf_get_fd_by_id_opts.c | 36 ++++++++
> > 6 files changed, 189 insertions(+), 5 deletions(-)
> > create mode 100644
> > tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
> > create mode 100644
> > tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
> >
> > --
> > 2.25.1
> >
Hello:
This series was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <[email protected]>:
On Thu, 6 Oct 2022 13:07:30 +0200 you wrote:
> From: Roberto Sassu <[email protected]>
>
> Add the _opts variant for bpf_*_get_fd_by_id() functions, to be able to
> pass to the kernel more options, when requesting a fd of an eBPF object.
>
> Pass the options through a newly introduced structure,
> bpf_get_fd_by_id_opts, which currently contains open_flags (the other two
> members are for compatibility and for padding).
>
> [...]
Here is the summary with links:
- [v2,1/6] libbpf: Fix LIBBPF_1.0.0 declaration in libbpf.map
https://git.kernel.org/bpf/bpf-next/c/7a366da2d2ba
- [v2,2/6] libbpf: Introduce bpf_get_fd_by_id_opts and bpf_map_get_fd_by_id_opts()
https://git.kernel.org/bpf/bpf-next/c/243e300563b1
- [v2,3/6] libbpf: Introduce bpf_prog_get_fd_by_id_opts()
https://git.kernel.org/bpf/bpf-next/c/8f13f168ea14
- [v2,4/6] libbpf: Introduce bpf_btf_get_fd_by_id_opts()
https://git.kernel.org/bpf/bpf-next/c/2ce7cbf2ba71
- [v2,5/6] libbpf: Introduce bpf_link_get_fd_by_id_opts()
https://git.kernel.org/bpf/bpf-next/c/97c8f9dd5db8
- [v2,6/6] selftests/bpf: Add tests for _opts variants of bpf_*_get_fd_by_id()
https://git.kernel.org/bpf/bpf-next/c/a9c7c18b5759
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html