[PATCH v2 0/9] bpf: Per-operation map permissions
From: Roberto Sassu
Date: Thu Jun 02 2022 - 10:38:28 EST
With the bpf_map security hook, an eBPF program is able to restrict access
to a map. For example, it might allow only read accesses and deny write
accesses.
Unfortunately, permissions are not accurately specified by libbpf and
bpftool. As a consequence, even if they are requested to perform a
read-like operation, such as a map lookup, that operation fails even if the
caller has the right to do so.
Even worse, the iteration over existing maps stops as soon as a
write-protected one is encountered. Maps after the write-protected one are
not accessible, even if the user has the right to perform operations on
them.
At low level, the problem is that open_flags and file_flags, respectively
in the bpf_map_get_fd_by_id() and bpf_obj_get(), are set to zero. The
kernel interprets this as a request to obtain a file descriptor with full
permissions.
For some operations, like show or dump, a read file descriptor is enough.
Those operations could be still performed even in a write-protected map.
Also for searching a map by name, which requires getting the map info, a
read file descriptor is enough. If an operation requires more permissions,
they could still be requested later, after the search.
First, solve both problems by extending libbpf with two new functions,
bpf_map_get_fd_by_id_flags() and bpf_obj_get_flags(), which unlike their
counterparts bpf_map_get_fd_by_id() and bpf_obj_get(), have the additional
parameter flags to specify the needed permissions for an operation.
Then, propagate the flags in bpftool from the functions implementing the
subcommands down to the functions calling bpf_map_get_fd_by_id() and
bpf_obj_get(), and replace the latter functions with their new variant.
Initially, set the flags to zero, so that the current behavior does not
change.
The only exception is for map search by name, where a read-only permission
is requested, regardless of the operation, to get the map info. In this
case, request a new file descriptor if a write-like operation needs to be
performed after the search.
Finally, identify other read-like operations in bpftool and for those
replace the zero value for flags with BPF_F_RDONLY.
The patch set is organized as follows.
Patches 1-2 introduce the two new variants of bpf_map_get_fd_by_id() and
bpf_obj_get() in libbpf, named respectively bpf_map_get_fd_by_id_flags()
and bpf_obj_get_flags().
Patches 3-7 propagate the flags in bpftool from the functions implementing
the subcommands to the two new libbpf functions, and always set flags to
BPF_F_RDONLY for the map search operation.
Patch 8 adjusts permissions depending on the map operation performed.
Patch 9 ensures that read-only accesses to a write-protected map succeed
and write accesses still fail. Also ensure that map search is always
successful even if there are write-protected maps.
Changelog
v1:
- Define per-operation permissions rather than retrying access with
read-only permission (suggested by Daniel)
https://lore.kernel.org/bpf/20220530084514.10170-1-roberto.sassu@xxxxxxxxxx/
Roberto Sassu (9):
libbpf: Introduce bpf_map_get_fd_by_id_flags()
libbpf: Introduce bpf_obj_get_flags()
bpftool: Add flags parameter to open_obj_pinned_any() and
open_obj_pinned()
bpftool: Add flags parameter to *_parse_fd() functions
bpftool: Add flags parameter to map_parse_fds()
bpftool: Add flags parameter to map_parse_fd_and_info()
bpftool: Add flags parameter in struct_ops functions
bpftool: Adjust map permissions
selftests/bpf: Add map access tests
tools/bpf/bpftool/btf.c | 11 +-
tools/bpf/bpftool/cgroup.c | 4 +-
tools/bpf/bpftool/common.c | 52 ++--
tools/bpf/bpftool/iter.c | 2 +-
tools/bpf/bpftool/link.c | 9 +-
tools/bpf/bpftool/main.h | 17 +-
tools/bpf/bpftool/map.c | 24 +-
tools/bpf/bpftool/map_perf_ring.c | 3 +-
tools/bpf/bpftool/net.c | 2 +-
tools/bpf/bpftool/prog.c | 12 +-
tools/bpf/bpftool/struct_ops.c | 39 ++-
tools/lib/bpf/bpf.c | 16 +-
tools/lib/bpf/bpf.h | 2 +
tools/lib/bpf/libbpf.map | 2 +
.../bpf/prog_tests/test_map_check_access.c | 264 ++++++++++++++++++
.../selftests/bpf/progs/map_check_access.c | 65 +++++
16 files changed, 452 insertions(+), 72 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/test_map_check_access.c
create mode 100644 tools/testing/selftests/bpf/progs/map_check_access.c
--
2.25.1