Skip to content

Commit f6ac03e

Browse files
committed
Merge branch 'Add _opts variant for bpf_*_get_fd_by_id()'
Roberto Sassu says: ==================== 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 ==================== Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents 2e30960 + a9c7c18 commit f6ac03e

File tree

6 files changed

+189
-5
lines changed

6 files changed

+189
-5
lines changed

tools/lib/bpf/bpf.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -935,58 +935,98 @@ int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
935935
return bpf_obj_get_next_id(start_id, next_id, BPF_LINK_GET_NEXT_ID);
936936
}
937937

938-
int bpf_prog_get_fd_by_id(__u32 id)
938+
int bpf_prog_get_fd_by_id_opts(__u32 id,
939+
const struct bpf_get_fd_by_id_opts *opts)
939940
{
940941
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
941942
union bpf_attr attr;
942943
int fd;
943944

945+
if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
946+
return libbpf_err(-EINVAL);
947+
944948
memset(&attr, 0, attr_sz);
945949
attr.prog_id = id;
950+
attr.open_flags = OPTS_GET(opts, open_flags, 0);
946951

947952
fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
948953
return libbpf_err_errno(fd);
949954
}
950955

951-
int bpf_map_get_fd_by_id(__u32 id)
956+
int bpf_prog_get_fd_by_id(__u32 id)
957+
{
958+
return bpf_prog_get_fd_by_id_opts(id, NULL);
959+
}
960+
961+
int bpf_map_get_fd_by_id_opts(__u32 id,
962+
const struct bpf_get_fd_by_id_opts *opts)
952963
{
953964
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
954965
union bpf_attr attr;
955966
int fd;
956967

968+
if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
969+
return libbpf_err(-EINVAL);
970+
957971
memset(&attr, 0, attr_sz);
958972
attr.map_id = id;
973+
attr.open_flags = OPTS_GET(opts, open_flags, 0);
959974

960975
fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
961976
return libbpf_err_errno(fd);
962977
}
963978

964-
int bpf_btf_get_fd_by_id(__u32 id)
979+
int bpf_map_get_fd_by_id(__u32 id)
980+
{
981+
return bpf_map_get_fd_by_id_opts(id, NULL);
982+
}
983+
984+
int bpf_btf_get_fd_by_id_opts(__u32 id,
985+
const struct bpf_get_fd_by_id_opts *opts)
965986
{
966987
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
967988
union bpf_attr attr;
968989
int fd;
969990

991+
if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
992+
return libbpf_err(-EINVAL);
993+
970994
memset(&attr, 0, attr_sz);
971995
attr.btf_id = id;
996+
attr.open_flags = OPTS_GET(opts, open_flags, 0);
972997

973998
fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
974999
return libbpf_err_errno(fd);
9751000
}
9761001

977-
int bpf_link_get_fd_by_id(__u32 id)
1002+
int bpf_btf_get_fd_by_id(__u32 id)
1003+
{
1004+
return bpf_btf_get_fd_by_id_opts(id, NULL);
1005+
}
1006+
1007+
int bpf_link_get_fd_by_id_opts(__u32 id,
1008+
const struct bpf_get_fd_by_id_opts *opts)
9781009
{
9791010
const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
9801011
union bpf_attr attr;
9811012
int fd;
9821013

1014+
if (!OPTS_VALID(opts, bpf_get_fd_by_id_opts))
1015+
return libbpf_err(-EINVAL);
1016+
9831017
memset(&attr, 0, attr_sz);
9841018
attr.link_id = id;
1019+
attr.open_flags = OPTS_GET(opts, open_flags, 0);
9851020

9861021
fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
9871022
return libbpf_err_errno(fd);
9881023
}
9891024

1025+
int bpf_link_get_fd_by_id(__u32 id)
1026+
{
1027+
return bpf_link_get_fd_by_id_opts(id, NULL);
1028+
}
1029+
9901030
int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
9911031
{
9921032
const size_t attr_sz = offsetofend(union bpf_attr, info);

tools/lib/bpf/bpf.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,26 @@ LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
365365
LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
366366
LIBBPF_API int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id);
367367
LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
368+
369+
struct bpf_get_fd_by_id_opts {
370+
size_t sz; /* size of this struct for forward/backward compatibility */
371+
__u32 open_flags; /* permissions requested for the operation on fd */
372+
size_t :0;
373+
};
374+
#define bpf_get_fd_by_id_opts__last_field open_flags
375+
368376
LIBBPF_API int bpf_prog_get_fd_by_id(__u32 id);
377+
LIBBPF_API int bpf_prog_get_fd_by_id_opts(__u32 id,
378+
const struct bpf_get_fd_by_id_opts *opts);
369379
LIBBPF_API int bpf_map_get_fd_by_id(__u32 id);
380+
LIBBPF_API int bpf_map_get_fd_by_id_opts(__u32 id,
381+
const struct bpf_get_fd_by_id_opts *opts);
370382
LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
383+
LIBBPF_API int bpf_btf_get_fd_by_id_opts(__u32 id,
384+
const struct bpf_get_fd_by_id_opts *opts);
371385
LIBBPF_API int bpf_link_get_fd_by_id(__u32 id);
386+
LIBBPF_API int bpf_link_get_fd_by_id_opts(__u32 id,
387+
const struct bpf_get_fd_by_id_opts *opts);
372388
LIBBPF_API int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len);
373389

374390
struct bpf_prog_query_opts {

tools/lib/bpf/libbpf.map

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,14 @@ LIBBPF_1.0.0 {
367367
libbpf_bpf_map_type_str;
368368
libbpf_bpf_prog_type_str;
369369
perf_buffer__buffer;
370-
};
370+
} LIBBPF_0.8.0;
371371

372372
LIBBPF_1.1.0 {
373373
global:
374+
bpf_btf_get_fd_by_id_opts;
375+
bpf_link_get_fd_by_id_opts;
376+
bpf_map_get_fd_by_id_opts;
377+
bpf_prog_get_fd_by_id_opts;
374378
user_ring_buffer__discard;
375379
user_ring_buffer__free;
376380
user_ring_buffer__new;

tools/testing/selftests/bpf/DENYLIST.s390x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,4 @@ lookup_key # JIT does not support calling kernel f
7676
verify_pkcs7_sig # JIT does not support calling kernel function (kfunc)
7777
kfunc_dynptr_param # JIT does not support calling kernel function (kfunc)
7878
deny_namespace # failed to attach: ERROR: strerror_r(-524)=22 (trampoline)
79+
libbpf_get_fd_by_id_opts # failed to attach: ERROR: strerror_r(-524)=22 (trampoline)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
5+
*
6+
* Author: Roberto Sassu <[email protected]>
7+
*/
8+
9+
#include <test_progs.h>
10+
11+
#include "test_libbpf_get_fd_by_id_opts.skel.h"
12+
13+
void test_libbpf_get_fd_by_id_opts(void)
14+
{
15+
struct test_libbpf_get_fd_by_id_opts *skel;
16+
struct bpf_map_info info_m = {};
17+
__u32 len = sizeof(info_m), value;
18+
int ret, zero = 0, fd = -1;
19+
LIBBPF_OPTS(bpf_get_fd_by_id_opts, fd_opts_rdonly,
20+
.open_flags = BPF_F_RDONLY,
21+
);
22+
23+
skel = test_libbpf_get_fd_by_id_opts__open_and_load();
24+
if (!ASSERT_OK_PTR(skel,
25+
"test_libbpf_get_fd_by_id_opts__open_and_load"))
26+
return;
27+
28+
ret = test_libbpf_get_fd_by_id_opts__attach(skel);
29+
if (!ASSERT_OK(ret, "test_libbpf_get_fd_by_id_opts__attach"))
30+
goto close_prog;
31+
32+
ret = bpf_obj_get_info_by_fd(bpf_map__fd(skel->maps.data_input),
33+
&info_m, &len);
34+
if (!ASSERT_OK(ret, "bpf_obj_get_info_by_fd"))
35+
goto close_prog;
36+
37+
fd = bpf_map_get_fd_by_id(info_m.id);
38+
if (!ASSERT_LT(fd, 0, "bpf_map_get_fd_by_id"))
39+
goto close_prog;
40+
41+
fd = bpf_map_get_fd_by_id_opts(info_m.id, NULL);
42+
if (!ASSERT_LT(fd, 0, "bpf_map_get_fd_by_id_opts"))
43+
goto close_prog;
44+
45+
fd = bpf_map_get_fd_by_id_opts(info_m.id, &fd_opts_rdonly);
46+
if (!ASSERT_GE(fd, 0, "bpf_map_get_fd_by_id_opts"))
47+
goto close_prog;
48+
49+
/* Map lookup should work with read-only fd. */
50+
ret = bpf_map_lookup_elem(fd, &zero, &value);
51+
if (!ASSERT_OK(ret, "bpf_map_lookup_elem"))
52+
goto close_prog;
53+
54+
if (!ASSERT_EQ(value, 0, "map value mismatch"))
55+
goto close_prog;
56+
57+
/* Map update should not work with read-only fd. */
58+
ret = bpf_map_update_elem(fd, &zero, &len, BPF_ANY);
59+
if (!ASSERT_LT(ret, 0, "bpf_map_update_elem"))
60+
goto close_prog;
61+
62+
/* Map update should work with read-write fd. */
63+
ret = bpf_map_update_elem(bpf_map__fd(skel->maps.data_input), &zero,
64+
&len, BPF_ANY);
65+
if (!ASSERT_OK(ret, "bpf_map_update_elem"))
66+
goto close_prog;
67+
68+
/* Prog get fd with opts set should not work (no kernel support). */
69+
ret = bpf_prog_get_fd_by_id_opts(0, &fd_opts_rdonly);
70+
if (!ASSERT_EQ(ret, -EINVAL, "bpf_prog_get_fd_by_id_opts"))
71+
goto close_prog;
72+
73+
/* Link get fd with opts set should not work (no kernel support). */
74+
ret = bpf_link_get_fd_by_id_opts(0, &fd_opts_rdonly);
75+
if (!ASSERT_EQ(ret, -EINVAL, "bpf_link_get_fd_by_id_opts"))
76+
goto close_prog;
77+
78+
/* BTF get fd with opts set should not work (no kernel support). */
79+
ret = bpf_btf_get_fd_by_id_opts(0, &fd_opts_rdonly);
80+
ASSERT_EQ(ret, -EINVAL, "bpf_btf_get_fd_by_id_opts");
81+
82+
close_prog:
83+
if (fd >= 0)
84+
close(fd);
85+
86+
test_libbpf_get_fd_by_id_opts__destroy(skel);
87+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH
5+
*
6+
* Author: Roberto Sassu <[email protected]>
7+
*/
8+
9+
#include "vmlinux.h"
10+
#include <errno.h>
11+
#include <bpf/bpf_helpers.h>
12+
#include <bpf/bpf_tracing.h>
13+
14+
/* From include/linux/mm.h. */
15+
#define FMODE_WRITE 0x2
16+
17+
struct {
18+
__uint(type, BPF_MAP_TYPE_ARRAY);
19+
__uint(max_entries, 1);
20+
__type(key, __u32);
21+
__type(value, __u32);
22+
} data_input SEC(".maps");
23+
24+
char _license[] SEC("license") = "GPL";
25+
26+
SEC("lsm/bpf_map")
27+
int BPF_PROG(check_access, struct bpf_map *map, fmode_t fmode)
28+
{
29+
if (map != (struct bpf_map *)&data_input)
30+
return 0;
31+
32+
if (fmode & FMODE_WRITE)
33+
return -EACCES;
34+
35+
return 0;
36+
}

0 commit comments

Comments
 (0)