Linux Kernel Selftest development
 help / color / mirror / Atom feed
* [PATCH v2 0/9] bpf: Per-operation map permissions
@ 2022-06-02 14:37 Roberto Sassu
  2022-06-02 14:37 ` [PATCH v2 1/9] libbpf: Introduce bpf_map_get_fd_by_id_flags() Roberto Sassu
                   ` (9 more replies)
  0 siblings, 10 replies; 15+ messages in thread
From: Roberto Sassu @ 2022-06-02 14:37 UTC (permalink / raw)
  To: ast, daniel, andrii, kpsingh
  Cc: bpf, netdev, linux-kselftest, linux-kernel, Roberto Sassu

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@huawei.com/

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


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-06-09 12:55 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-06-02 14:37 [PATCH v2 0/9] bpf: Per-operation map permissions Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 1/9] libbpf: Introduce bpf_map_get_fd_by_id_flags() Roberto Sassu
2022-06-03 20:58   ` Andrii Nakryiko
2022-06-02 14:37 ` [PATCH v2 2/9] libbpf: Introduce bpf_obj_get_flags() Roberto Sassu
2022-06-03 20:59   ` Andrii Nakryiko
2022-06-02 14:37 ` [PATCH v2 3/9] bpftool: Add flags parameter to open_obj_pinned_any() and open_obj_pinned() Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 4/9] bpftool: Add flags parameter to *_parse_fd() functions Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 5/9] bpftool: Add flags parameter to map_parse_fds() Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 6/9] bpftool: Add flags parameter to map_parse_fd_and_info() Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 7/9] bpftool: Add flags parameter in struct_ops functions Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 8/9] bpftool: Adjust map permissions Roberto Sassu
2022-06-02 14:37 ` [PATCH v2 9/9] selftests/bpf: Add map access tests Roberto Sassu
2022-06-03 20:59   ` Andrii Nakryiko
2022-06-03 21:00 ` [PATCH v2 0/9] bpf: Per-operation map permissions Andrii Nakryiko
2022-06-09 12:55   ` Roberto Sassu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox