Commit d32179e8 authored by Slava Imameev's avatar Slava Imameev Committed by Alexei Starovoitov
Browse files

bpftool: Use appropriate permissions for map access



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: default avatarSlava Imameev <slava.imameev@crowdstrike.com>
Reviewed-by: default avatarQuentin Monnet <qmo@kernel.org>
Link: https://lore.kernel.org/r/20250620151812.13952-1-slava.imameev@crowdstrike.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent e30329b8
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -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;

@@ -1118,10 +1119,13 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
		[BPF_OBJ_PROG]		= "prog",
		[BPF_OBJ_MAP]		= "map",
	};
	LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts_ro);
	__u32 btf_id, id = 0;
	int err;
	int fd;

	opts_ro.open_flags = BPF_F_RDONLY;

	while (true) {
		switch (type) {
		case BPF_OBJ_PROG:
@@ -1151,7 +1155,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
			fd = bpf_prog_get_fd_by_id(id);
			break;
		case BPF_OBJ_MAP:
			fd = bpf_map_get_fd_by_id(id);
			fd = bpf_map_get_fd_by_id_opts(id, &opts_ro);
			break;
		default:
			err = -1;
+43 −16
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -193,7 +194,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 +207,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 +223,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 +558,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 +931,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 +968,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 +977,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 +990,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 +1011,19 @@ static int map_fd_by_name(char *name, int **fds)
			continue;
		}

		/* Get an fd with the requested options, if they differ
		 * from the read-only options used to get the fd above.
		 */
		if (memcmp(opts, &opts_ro, sizeof(opts_ro))) {
			close(fd);
			fd = bpf_map_get_fd_by_id_opts(id, opts);
			if (fd < 0) {
				p_err("can't get map by id (%u): %s", id,
					strerror(errno));
				goto err_close_fds;
			}
		}

		if (nb_fds > 0) {
			tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
			if (!tmp) {
@@ -1023,8 +1043,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);
	opts.open_flags = open_flags;

	if (is_prefix(**argv, "id")) {
		unsigned int id;
		char *endptr;
@@ -1038,7 +1063,7 @@ int map_parse_fds(int *argc, char ***argv, int **fds)
		}
		NEXT_ARGP();

		(*fds)[0] = bpf_map_get_fd_by_id(id);
		(*fds)[0] = bpf_map_get_fd_by_id_opts(id, &opts);
		if ((*fds)[0] < 0) {
			p_err("get map by id (%u): %s", id, strerror(errno));
			return -1;
@@ -1056,16 +1081,18 @@ int map_parse_fds(int *argc, char ***argv, int **fds)
		}
		NEXT_ARGP();

		return map_fd_by_name(name, fds);
		return map_fd_by_name(name, fds, &opts);
	} else if (is_prefix(**argv, "pinned")) {
		char *path;
		LIBBPF_OPTS(bpf_obj_get_opts, get_opts);
		get_opts.file_flags = open_flags;

		NEXT_ARGP();

		path = **argv;
		NEXT_ARGP();

		(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP);
		(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP, &get_opts);
		if ((*fds)[0] < 0)
			return -1;
		return 1;
@@ -1075,7 +1102,7 @@ int map_parse_fds(int *argc, char ***argv, int **fds)
	return -1;
}

int map_parse_fd(int *argc, char ***argv)
int map_parse_fd(int *argc, char ***argv, __u32 open_flags)
{
	int *fds = NULL;
	int nb_fds, fd;
@@ -1085,7 +1112,7 @@ int map_parse_fd(int *argc, char ***argv)
		p_err("mem alloc failed");
		return -1;
	}
	nb_fds = map_parse_fds(argc, argv, &fds);
	nb_fds = map_parse_fds(argc, argv, &fds, open_flags);
	if (nb_fds != 1) {
		if (nb_fds > 1) {
			p_err("several maps match this handle");
@@ -1103,12 +1130,12 @@ int map_parse_fd(int *argc, char ***argv)
}

int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
			  __u32 *info_len)
			  __u32 *info_len, __u32 open_flags)
{
	int err;
	int fd;

	fd = map_parse_fd(argc, argv);
	fd = map_parse_fd(argc, argv, open_flags);
	if (fd < 0)
		return -1;

+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ static int do_pin(int argc, char **argv)
				return -1;
			}

			map_fd = map_parse_fd(&argc, &argv);
			map_fd = map_parse_fd(&argc, &argv, BPF_F_RDONLY);
			if (map_fd < 0)
				return -1;

+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ static int link_parse_fd(int *argc, char ***argv)
		path = **argv;
		NEXT_ARGP();

		return open_obj_pinned_any(path, BPF_OBJ_LINK);
		return open_obj_pinned_any(path, BPF_OBJ_LINK, NULL);
	}

	p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
+8 −5
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@

#include <bpf/hashmap.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>

#include "json_writer.h"

@@ -140,8 +141,10 @@ void get_prog_full_name(const struct bpf_prog_info *prog_info, int prog_fd,
int get_fd_type(int fd);
const char *get_fd_type_name(enum bpf_obj_type type);
char *get_fdinfo(int fd, const char *key);
int open_obj_pinned(const char *path, bool quiet);
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
int open_obj_pinned(const char *path, bool quiet,
		    const struct bpf_obj_get_opts *opts);
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type,
			const struct bpf_obj_get_opts *opts);
int mount_bpffs_for_file(const char *file_name);
int create_and_mount_bpffs_dir(const char *dir_name);
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(int *, char ***));
@@ -167,10 +170,10 @@ int do_iter(int argc, char **argv) __weak;
int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
int prog_parse_fd(int *argc, char ***argv);
int prog_parse_fds(int *argc, char ***argv, int **fds);
int map_parse_fd(int *argc, char ***argv);
int map_parse_fds(int *argc, char ***argv, int **fds);
int map_parse_fd(int *argc, char ***argv, __u32 open_flags);
int map_parse_fds(int *argc, char ***argv, int **fds, __u32 open_flags);
int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
			  __u32 *info_len);
			  __u32 *info_len, __u32 open_flags);

struct bpf_prog_linfo;
#if defined(HAVE_LLVM_SUPPORT) || defined(HAVE_LIBBFD_SUPPORT)
Loading