forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: Add tests for _opts variants of bpf_*_get_fd_by_id()
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]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
- Loading branch information
1 parent
97c8f9d
commit a9c7c18
Showing
3 changed files
with
124 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
tools/testing/selftests/bpf/prog_tests/libbpf_get_fd_by_id_opts.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
36 changes: 36 additions & 0 deletions
36
tools/testing/selftests/bpf/progs/test_libbpf_get_fd_by_id_opts.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |