Add a test to check the ability of bpf_map_get_fd_by_id() to get a map file descriptor if write permission is denied.
Also ensure that a map update operation fails with the obtained read-only file descriptor.
Signed-off-by: Roberto Sassu roberto.sassu@huawei.com --- .../bpf/prog_tests/test_map_retry_access.c | 54 +++++++++++++++++++ .../selftests/bpf/progs/map_retry_access.c | 36 +++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/test_map_retry_access.c create mode 100644 tools/testing/selftests/bpf/progs/map_retry_access.c
diff --git a/tools/testing/selftests/bpf/prog_tests/test_map_retry_access.c b/tools/testing/selftests/bpf/prog_tests/test_map_retry_access.c new file mode 100644 index 000000000000..beffb2026dcd --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/test_map_retry_access.c @@ -0,0 +1,54 @@ +// 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 "map_retry_access.skel.h" + +void test_test_map_retry_access(void) +{ + struct map_retry_access *skel; + struct bpf_map_info info; + struct bpf_map *map; + __u32 len = sizeof(info); + int ret, zero = 0, fd, duration = 0; + + skel = map_retry_access__open_and_load(); + if (CHECK(!skel, "skel", "open_and_load failed\n")) + goto close_prog; + + ret = map_retry_access__attach(skel); + if (CHECK(ret < 0, "skel", "attach failed\n")) + goto close_prog; + + map = bpf_object__find_map_by_name(skel->obj, "data_input"); + if (CHECK(!map, "bpf_object__find_map_by_name", "not found\n")) + goto close_prog; + + ret = bpf_obj_get_info_by_fd(bpf_map__fd(map), &info, &len); + if (CHECK(ret < 0, "bpf_obj_get_info_by_fd", "error: %d\n", ret)) + goto close_prog; + + fd = bpf_map_get_fd_by_id(info.id); + if (CHECK(fd < 0, "bpf_map_get_fd_by_id", "error: %d\n", fd)) + goto close_prog; + + ret = bpf_map_update_elem(fd, &zero, &len, BPF_ANY); + + close(fd); + + if (CHECK(!ret, "bpf_map_update_elem", + "should fail (read-only permission)\n")) + goto close_prog; + + ret = bpf_map_update_elem(bpf_map__fd(map), &zero, &len, BPF_ANY); + + CHECK(ret < 0, "bpf_map_update_elem", "error: %d\n", ret); +close_prog: + map_retry_access__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/map_retry_access.c b/tools/testing/selftests/bpf/progs/map_retry_access.c new file mode 100644 index 000000000000..1ed7b137a286 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/map_retry_access.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright (C) 2022 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu roberto.sassu@huawei.com + */ + +#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(bpf_map_retry_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; +}