[RFC][PATCH v3 03/15] libbpf: Introduce bpf_prog_get_fd_by_id_opts()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Define a new data structure called bpf_get_fd_opts, with the member flags,
to be used by callers of the _opts variants of bpf_*_get_fd_by_id() and
bpf_obj_get() to specify the permissions needed for the operations on the
obtained file descriptor.

Define only one data structure for all variants, as the open_flags field in
bpf_attr for bpf_*_get_fd_by_id_opts() and file_flags for
bpf_obj_get_opts() have the same meaning. Also, it would avoid the
confusion when the same bpftool function calls both
bpf_*_get_fd_by_id_opts() and bpf_obj_get_opts() (e.g. map_parse_fds()).

Then, introduce the new feature FEAT_GET_FD_BY_ID_OPEN_FLAGS to determine
whether or not the kernel supports setting open_flags for
bpf_*_get_fd_by_id() functions (except for bpf_map_get_fd_by_id(), which
already can get it). If the feature is not detected, the _opts variants
ignore flags in the bpf_get_fd_opts structure and leave open_flags to zero.

Finally, introduce bpf_prog_get_fd_by_id_opts(), to let the caller pass the
newly introduced data structure. Keep the existing bpf_prog_get_fd_by_id(),
and call bpf_prog_get_fd_by_id_opts() with NULL as opts argument.

Currently, setting permissions in the data structure has no effect, as the
kernel does not evaluate them. The new variant has been introduced anyway
for symmetry with bpf_map_get_fd_by_id_opts(). Evaluating permissions could
be done in future kernel versions.

Signed-off-by: Roberto Sassu <roberto.sassu@xxxxxxxxxx>
---
 tools/lib/bpf/bpf.c             | 37 ++++++++++++++++++++++++++++++++-
 tools/lib/bpf/bpf.h             | 11 ++++++++++
 tools/lib/bpf/libbpf.c          |  4 ++++
 tools/lib/bpf/libbpf.map        |  1 +
 tools/lib/bpf/libbpf_internal.h |  3 +++
 5 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 5eb0df90eb2b..9014a61bca83 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -910,18 +910,53 @@ 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)
+static int
+bpf_prog_get_fd_by_id_opts_check(__u32 id, const struct bpf_get_fd_opts *opts,
+				 bool check_support)
 {
 	union bpf_attr attr;
 	int fd;
 
+	if (!OPTS_VALID(opts, bpf_get_fd_opts))
+		return libbpf_err(-EINVAL);
+
 	memset(&attr, 0, sizeof(attr));
 	attr.prog_id = id;
+	if (!check_support ||
+	    kernel_supports(NULL, FEAT_GET_FD_BY_ID_OPEN_FLAGS))
+		attr.open_flags = OPTS_GET(opts, flags, 0);
 
 	fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
 	return libbpf_err_errno(fd);
 }
 
+int bpf_prog_get_fd_by_id_opts(__u32 id, const struct bpf_get_fd_opts *opts)
+{
+	return bpf_prog_get_fd_by_id_opts_check(id, opts, true);
+}
+
+int probe_get_fd_by_id_open_flags(void)
+{
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
+	int ret, fd;
+
+	fd = bpf_prog_get_fd_by_id_opts_check(0, &opts, false);
+	ret = (fd >= 0) || (errno == ENOENT);
+
+	if (fd >= 0)
+		close(fd);
+
+	return ret;
+}
+
+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(__u32 id)
 {
 	union bpf_attr attr;
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 88a7cc4bd76f..bc241343a0f9 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -271,6 +271,14 @@ LIBBPF_API int bpf_map_update_batch(int fd, const void *keys, const void *values
 				    const struct bpf_map_batch_opts *opts);
 
 LIBBPF_API int bpf_obj_pin(int fd, const char *pathname);
+
+struct bpf_get_fd_opts {
+	size_t sz; /* size of this struct for forward/backward compatibility */
+	__u32 flags; /* permissions requested for the operation on fd */
+	__u32 :0;
+};
+#define bpf_get_fd_opts__last_field flags
+
 LIBBPF_API int bpf_obj_get(const char *pathname);
 
 struct bpf_prog_attach_opts {
@@ -354,6 +362,9 @@ LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
 LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
 LIBBPF_API int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id);
 LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
+
+LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
+					  const struct bpf_get_fd_opts *opts);
 LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
 LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
 LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b01fe01b0761..12b5e6833726 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4784,6 +4784,10 @@ static struct kern_feature_desc {
 	[FEAT_SYSCALL_WRAPPER] = {
 		"Kernel using syscall wrapper", probe_kern_syscall_wrapper,
 	},
+	[FEAT_GET_FD_BY_ID_OPEN_FLAGS] = {
+		"open_flags accepted for bpf_*_get_fd_by_id() funcs",
+		probe_get_fd_by_id_open_flags,
+	},
 };
 
 bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 0625adb9e888..ab818612a585 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -364,4 +364,5 @@ LIBBPF_1.0.0 {
 		libbpf_bpf_map_type_str;
 		libbpf_bpf_prog_type_str;
 		perf_buffer__buffer;
+		bpf_prog_get_fd_by_id_opts;
 };
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 4135ae0a2bc3..84c589b310e7 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -354,10 +354,13 @@ enum kern_feature_id {
 	FEAT_BTF_ENUM64,
 	/* Kernel uses syscall wrapper (CONFIG_ARCH_HAS_SYSCALL_WRAPPER) */
 	FEAT_SYSCALL_WRAPPER,
+	/* open_flags accepted for bpf_*_get_fd_by_id() funcs */
+	FEAT_GET_FD_BY_ID_OPEN_FLAGS,
 	__FEAT_CNT,
 };
 
 int probe_memcg_account(void);
+int probe_get_fd_by_id_open_flags(void);
 bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
 int bump_rlimit_memlock(void);
 
-- 
2.25.1




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux