Re: [PATCH bpf-next v3 1/2] bpftool: Use appropriate permissions for map access

2025-06-16 Thread Quentin Monnet
2025-06-12 08:18 UTC+1000 ~ Slava Imameev 
> Modify several functions in tools/bpf/bpftool/common.c to allow
> specification of requested access for file descriptors, such as
> read-only access.
> 
> Update bpftool to request only read access for maps when write
> access is not required. This fixes errors when reading from maps
> that are protected from modification via security_bpf_map.
> 
> Signed-off-by: Slava Imameev 
> ---
> Changes in v2:
> - fix for a test compilation error: "conflicting types for 'bpf_fentry_test1'"
> Changes in v3:
> - Addressed review feedback
> - Converted the check for flags to an assert in map_parse_fds
> - Modified map_fd_by_name to keep an existing fd where possible
> - Fixed requested access for map delete command in do_delete
> - Changed requested access to RDONLY for inner map fd in do_create
> - Changed requested access to RDONLY for iterator fd in do_pin
> ---
> ---
>  tools/bpf/bpftool/btf.c   |  3 +-
>  tools/bpf/bpftool/common.c| 58 ++-
>  tools/bpf/bpftool/iter.c  |  2 +-
>  tools/bpf/bpftool/link.c  |  2 +-
>  tools/bpf/bpftool/main.h  | 13 ---
>  tools/bpf/bpftool/map.c   | 56 +
>  tools/bpf/bpftool/map_perf_ring.c |  3 +-
>  tools/bpf/bpftool/prog.c  |  4 +--
>  8 files changed, 91 insertions(+), 50 deletions(-)
> 
> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> index 6b14cbfa58aa..1ba27cb03348 100644
> --- a/tools/bpf/bpftool/btf.c
> +++ b/tools/bpf/bpftool/btf.c
> @@ -905,7 +905,8 @@ static int do_dump(int argc, char **argv)
>   return -1;
>   }
>  
> - fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
> + fd = map_parse_fd_and_info(&argc, &argv, &info, &len,
> +BPF_F_RDONLY);
>   if (fd < 0)
>   return -1;
>  
> diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
> index ecfa790adc13..3bdc65112c0d 100644
> --- a/tools/bpf/bpftool/common.c
> +++ b/tools/bpf/bpftool/common.c

[...]

> @@ -1023,8 +1042,13 @@ static int map_fd_by_name(char *name, int **fds)
>   return -1;
>  }
>  
> -int map_parse_fds(int *argc, char ***argv, int **fds)
> +int map_parse_fds(int *argc, char ***argv, int **fds, __u32 open_flags)
>  {
> + LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts);
> +
> + assert((open_flags & ~BPF_F_RDONLY) == 0);


Can you please "#include " at the top of the file? We don't
need it in the kernel repo, because the header is included from
tools/include/linux/kernel.h (from bpftool's main.h) if I remember
correctly. But the GitHub mirror uses a stripped-down version of
kernel.h which doesn't pull assert.h, so we need to include it
explicitly - I just remembered when seeing your v3, sorry.

Looks good to me otherwise, thanks!
Quentin



[PATCH bpf-next v3 1/2] bpftool: Use appropriate permissions for map access

2025-06-11 Thread Slava Imameev
Modify several functions in tools/bpf/bpftool/common.c to allow
specification of requested access for file descriptors, such as
read-only access.

Update bpftool to request only read access for maps when write
access is not required. This fixes errors when reading from maps
that are protected from modification via security_bpf_map.

Signed-off-by: Slava Imameev 
---
Changes in v2:
- fix for a test compilation error: "conflicting types for 'bpf_fentry_test1'"
Changes in v3:
- Addressed review feedback
- Converted the check for flags to an assert in map_parse_fds
- Modified map_fd_by_name to keep an existing fd where possible
- Fixed requested access for map delete command in do_delete
- Changed requested access to RDONLY for inner map fd in do_create
- Changed requested access to RDONLY for iterator fd in do_pin
---
---
 tools/bpf/bpftool/btf.c   |  3 +-
 tools/bpf/bpftool/common.c| 58 ++-
 tools/bpf/bpftool/iter.c  |  2 +-
 tools/bpf/bpftool/link.c  |  2 +-
 tools/bpf/bpftool/main.h  | 13 ---
 tools/bpf/bpftool/map.c   | 56 +
 tools/bpf/bpftool/map_perf_ring.c |  3 +-
 tools/bpf/bpftool/prog.c  |  4 +--
 8 files changed, 91 insertions(+), 50 deletions(-)

diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
index 6b14cbfa58aa..1ba27cb03348 100644
--- a/tools/bpf/bpftool/btf.c
+++ b/tools/bpf/bpftool/btf.c
@@ -905,7 +905,8 @@ static int do_dump(int argc, char **argv)
return -1;
}
 
-   fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
+   fd = map_parse_fd_and_info(&argc, &argv, &info, &len,
+  BPF_F_RDONLY);
if (fd < 0)
return -1;
 
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index ecfa790adc13..3bdc65112c0d 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -193,7 +193,8 @@ int mount_tracefs(const char *target)
return err;
 }
 
-int open_obj_pinned(const char *path, bool quiet)
+int open_obj_pinned(const char *path, bool quiet,
+   const struct bpf_obj_get_opts *opts)
 {
char *pname;
int fd = -1;
@@ -205,7 +206,7 @@ int open_obj_pinned(const char *path, bool quiet)
goto out_ret;
}
 
-   fd = bpf_obj_get(pname);
+   fd = bpf_obj_get_opts(pname, opts);
if (fd < 0) {
if (!quiet)
p_err("bpf obj get (%s): %s", pname,
@@ -221,12 +222,13 @@ int open_obj_pinned(const char *path, bool quiet)
return fd;
 }
 
-int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
+int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type,
+   const struct bpf_obj_get_opts *opts)
 {
enum bpf_obj_type type;
int fd;
 
-   fd = open_obj_pinned(path, false);
+   fd = open_obj_pinned(path, false, opts);
if (fd < 0)
return -1;
 
@@ -555,7 +557,7 @@ static int do_build_table_cb(const char *fpath, const 
struct stat *sb,
if (typeflag != FTW_F)
goto out_ret;
 
-   fd = open_obj_pinned(fpath, true);
+   fd = open_obj_pinned(fpath, true, NULL);
if (fd < 0)
goto out_ret;
 
@@ -928,7 +930,7 @@ int prog_parse_fds(int *argc, char ***argv, int **fds)
path = **argv;
NEXT_ARGP();
 
-   (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG);
+   (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG, NULL);
if ((*fds)[0] < 0)
return -1;
return 1;
@@ -965,7 +967,8 @@ int prog_parse_fd(int *argc, char ***argv)
return fd;
 }
 
-static int map_fd_by_name(char *name, int **fds)
+static int map_fd_by_name(char *name, int **fds,
+ const struct bpf_get_fd_by_id_opts *opts)
 {
unsigned int id = 0;
int fd, nb_fds = 0;
@@ -973,6 +976,7 @@ static int map_fd_by_name(char *name, int **fds)
int err;
 
while (true) {
+   LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts_ro);
struct bpf_map_info info = {};
__u32 len = sizeof(info);
 
@@ -985,7 +989,9 @@ static int map_fd_by_name(char *name, int **fds)
return nb_fds;
}
 
-   fd = bpf_map_get_fd_by_id(id);
+   /* Request a read-only fd to query the map info */
+   opts_ro.open_flags = BPF_F_RDONLY;
+   fd = bpf_map_get_fd_by_id_opts(id, &opts_ro);
if (fd < 0) {
p_err("can't get map by id (%u): %s",
  id, strerror(errno));
@@ -1004,6 +1010,19 @@ static int map_fd_by_name(char *name, int **fds)
continue;
}
 
+   /* Get an fd wi