Commit f6ac03eb authored by Andrii Nakryiko's avatar Andrii Nakryiko
Browse files

Merge branch 'Add _opts variant for bpf_*_get_fd_by_id()'



Roberto Sassu says:

====================
From: Roberto Sassu <roberto.sassu@huawei.com>

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
====================

Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
parents 2e309600 a9c7c18b
Loading
Loading
Loading
Loading
+44 −4
Original line number Diff line number Diff line
@@ -935,58 +935,98 @@ 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_map_get_fd_by_id(__u32 id)
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)
{
	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.map_id = id;
	attr.open_flags = OPTS_GET(opts, open_flags, 0);

	fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
	return libbpf_err_errno(fd);
}

int bpf_btf_get_fd_by_id(__u32 id)
int bpf_map_get_fd_by_id(__u32 id)
{
	return bpf_map_get_fd_by_id_opts(id, NULL);
}

int bpf_btf_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.btf_id = id;
	attr.open_flags = OPTS_GET(opts, open_flags, 0);

	fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
	return libbpf_err_errno(fd);
}

int bpf_link_get_fd_by_id(__u32 id)
int bpf_btf_get_fd_by_id(__u32 id)
{
	return bpf_btf_get_fd_by_id_opts(id, NULL);
}

int bpf_link_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.link_id = id;
	attr.open_flags = OPTS_GET(opts, open_flags, 0);

	fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
	return libbpf_err_errno(fd);
}

int bpf_link_get_fd_by_id(__u32 id)
{
	return bpf_link_get_fd_by_id_opts(id, NULL);
}

int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
{
	const size_t attr_sz = offsetofend(union bpf_attr, info);
+16 −0
Original line number Diff line number Diff line
@@ -365,10 +365,26 @@ 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);

struct bpf_get_fd_by_id_opts {
	size_t sz; /* size of this struct for forward/backward compatibility */
	__u32 open_flags; /* permissions requested for the operation on fd */
	size_t :0;
};
#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);
LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_btf_get_fd_by_id_opts(__u32 id,
				const struct bpf_get_fd_by_id_opts *opts);
LIBBPF_API int bpf_link_get_fd_by_id(__u32 id);
LIBBPF_API int bpf_link_get_fd_by_id_opts(__u32 id,
				const struct bpf_get_fd_by_id_opts *opts);
LIBBPF_API int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len);

struct bpf_prog_query_opts {
+5 −1
Original line number Diff line number Diff line
@@ -367,10 +367,14 @@ LIBBPF_1.0.0 {
		libbpf_bpf_map_type_str;
		libbpf_bpf_prog_type_str;
		perf_buffer__buffer;
};
} LIBBPF_0.8.0;

LIBBPF_1.1.0 {
	global:
		bpf_btf_get_fd_by_id_opts;
		bpf_link_get_fd_by_id_opts;
		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;
+1 −0
Original line number Diff line number Diff line
@@ -76,3 +76,4 @@ lookup_key # JIT does not support calling kernel f
verify_pkcs7_sig                         # JIT does not support calling kernel function                                (kfunc)
kfunc_dynptr_param                       # JIT does not support calling kernel function                                (kfunc)
deny_namespace                           # failed to attach: ERROR: strerror_r(-524)=22                                (trampoline)
libbpf_get_fd_by_id_opts                 # failed to attach: ERROR: strerror_r(-524)=22                                (trampoline)
+87 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

/*
 * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
 *
 * Author: Roberto Sassu <roberto.sassu@huawei.com>
 */

#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);
}
Loading