Skip to content

Commit d32179e

Browse files
slava-at-csAlexei Starovoitov
authored andcommitted
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: Slava Imameev <[email protected]> Reviewed-by: Quentin Monnet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent e30329b commit d32179e

File tree

8 files changed

+96
-51
lines changed

8 files changed

+96
-51
lines changed

tools/bpf/bpftool/btf.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,8 @@ static int do_dump(int argc, char **argv)
905905
return -1;
906906
}
907907

908-
fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
908+
fd = map_parse_fd_and_info(&argc, &argv, &info, &len,
909+
BPF_F_RDONLY);
909910
if (fd < 0)
910911
return -1;
911912

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

1127+
opts_ro.open_flags = BPF_F_RDONLY;
1128+
11251129
while (true) {
11261130
switch (type) {
11271131
case BPF_OBJ_PROG:
@@ -1151,7 +1155,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
11511155
fd = bpf_prog_get_fd_by_id(id);
11521156
break;
11531157
case BPF_OBJ_MAP:
1154-
fd = bpf_map_get_fd_by_id(id);
1158+
fd = bpf_map_get_fd_by_id_opts(id, &opts_ro);
11551159
break;
11561160
default:
11571161
err = -1;

tools/bpf/bpftool/common.c

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef _GNU_SOURCE
55
#define _GNU_SOURCE
66
#endif
7+
#include <assert.h>
78
#include <ctype.h>
89
#include <errno.h>
910
#include <fcntl.h>
@@ -193,7 +194,8 @@ int mount_tracefs(const char *target)
193194
return err;
194195
}
195196

196-
int open_obj_pinned(const char *path, bool quiet)
197+
int open_obj_pinned(const char *path, bool quiet,
198+
const struct bpf_obj_get_opts *opts)
197199
{
198200
char *pname;
199201
int fd = -1;
@@ -205,7 +207,7 @@ int open_obj_pinned(const char *path, bool quiet)
205207
goto out_ret;
206208
}
207209

208-
fd = bpf_obj_get(pname);
210+
fd = bpf_obj_get_opts(pname, opts);
209211
if (fd < 0) {
210212
if (!quiet)
211213
p_err("bpf obj get (%s): %s", pname,
@@ -221,12 +223,13 @@ int open_obj_pinned(const char *path, bool quiet)
221223
return fd;
222224
}
223225

224-
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
226+
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type,
227+
const struct bpf_obj_get_opts *opts)
225228
{
226229
enum bpf_obj_type type;
227230
int fd;
228231

229-
fd = open_obj_pinned(path, false);
232+
fd = open_obj_pinned(path, false, opts);
230233
if (fd < 0)
231234
return -1;
232235

@@ -555,7 +558,7 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb,
555558
if (typeflag != FTW_F)
556559
goto out_ret;
557560

558-
fd = open_obj_pinned(fpath, true);
561+
fd = open_obj_pinned(fpath, true, NULL);
559562
if (fd < 0)
560563
goto out_ret;
561564

@@ -928,7 +931,7 @@ int prog_parse_fds(int *argc, char ***argv, int **fds)
928931
path = **argv;
929932
NEXT_ARGP();
930933

931-
(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG);
934+
(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG, NULL);
932935
if ((*fds)[0] < 0)
933936
return -1;
934937
return 1;
@@ -965,14 +968,16 @@ int prog_parse_fd(int *argc, char ***argv)
965968
return fd;
966969
}
967970

968-
static int map_fd_by_name(char *name, int **fds)
971+
static int map_fd_by_name(char *name, int **fds,
972+
const struct bpf_get_fd_by_id_opts *opts)
969973
{
970974
unsigned int id = 0;
971975
int fd, nb_fds = 0;
972976
void *tmp;
973977
int err;
974978

975979
while (true) {
980+
LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts_ro);
976981
struct bpf_map_info info = {};
977982
__u32 len = sizeof(info);
978983

@@ -985,7 +990,9 @@ static int map_fd_by_name(char *name, int **fds)
985990
return nb_fds;
986991
}
987992

988-
fd = bpf_map_get_fd_by_id(id);
993+
/* Request a read-only fd to query the map info */
994+
opts_ro.open_flags = BPF_F_RDONLY;
995+
fd = bpf_map_get_fd_by_id_opts(id, &opts_ro);
989996
if (fd < 0) {
990997
p_err("can't get map by id (%u): %s",
991998
id, strerror(errno));
@@ -1004,6 +1011,19 @@ static int map_fd_by_name(char *name, int **fds)
10041011
continue;
10051012
}
10061013

1014+
/* Get an fd with the requested options, if they differ
1015+
* from the read-only options used to get the fd above.
1016+
*/
1017+
if (memcmp(opts, &opts_ro, sizeof(opts_ro))) {
1018+
close(fd);
1019+
fd = bpf_map_get_fd_by_id_opts(id, opts);
1020+
if (fd < 0) {
1021+
p_err("can't get map by id (%u): %s", id,
1022+
strerror(errno));
1023+
goto err_close_fds;
1024+
}
1025+
}
1026+
10071027
if (nb_fds > 0) {
10081028
tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
10091029
if (!tmp) {
@@ -1023,8 +1043,13 @@ static int map_fd_by_name(char *name, int **fds)
10231043
return -1;
10241044
}
10251045

1026-
int map_parse_fds(int *argc, char ***argv, int **fds)
1046+
int map_parse_fds(int *argc, char ***argv, int **fds, __u32 open_flags)
10271047
{
1048+
LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts);
1049+
1050+
assert((open_flags & ~BPF_F_RDONLY) == 0);
1051+
opts.open_flags = open_flags;
1052+
10281053
if (is_prefix(**argv, "id")) {
10291054
unsigned int id;
10301055
char *endptr;
@@ -1038,7 +1063,7 @@ int map_parse_fds(int *argc, char ***argv, int **fds)
10381063
}
10391064
NEXT_ARGP();
10401065

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

1059-
return map_fd_by_name(name, fds);
1084+
return map_fd_by_name(name, fds, &opts);
10601085
} else if (is_prefix(**argv, "pinned")) {
10611086
char *path;
1087+
LIBBPF_OPTS(bpf_obj_get_opts, get_opts);
1088+
get_opts.file_flags = open_flags;
10621089

10631090
NEXT_ARGP();
10641091

10651092
path = **argv;
10661093
NEXT_ARGP();
10671094

1068-
(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP);
1095+
(*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP, &get_opts);
10691096
if ((*fds)[0] < 0)
10701097
return -1;
10711098
return 1;
@@ -1075,7 +1102,7 @@ int map_parse_fds(int *argc, char ***argv, int **fds)
10751102
return -1;
10761103
}
10771104

1078-
int map_parse_fd(int *argc, char ***argv)
1105+
int map_parse_fd(int *argc, char ***argv, __u32 open_flags)
10791106
{
10801107
int *fds = NULL;
10811108
int nb_fds, fd;
@@ -1085,7 +1112,7 @@ int map_parse_fd(int *argc, char ***argv)
10851112
p_err("mem alloc failed");
10861113
return -1;
10871114
}
1088-
nb_fds = map_parse_fds(argc, argv, &fds);
1115+
nb_fds = map_parse_fds(argc, argv, &fds, open_flags);
10891116
if (nb_fds != 1) {
10901117
if (nb_fds > 1) {
10911118
p_err("several maps match this handle");
@@ -1103,12 +1130,12 @@ int map_parse_fd(int *argc, char ***argv)
11031130
}
11041131

11051132
int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
1106-
__u32 *info_len)
1133+
__u32 *info_len, __u32 open_flags)
11071134
{
11081135
int err;
11091136
int fd;
11101137

1111-
fd = map_parse_fd(argc, argv);
1138+
fd = map_parse_fd(argc, argv, open_flags);
11121139
if (fd < 0)
11131140
return -1;
11141141

tools/bpf/bpftool/iter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static int do_pin(int argc, char **argv)
3737
return -1;
3838
}
3939

40-
map_fd = map_parse_fd(&argc, &argv);
40+
map_fd = map_parse_fd(&argc, &argv, BPF_F_RDONLY);
4141
if (map_fd < 0)
4242
return -1;
4343

tools/bpf/bpftool/link.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static int link_parse_fd(int *argc, char ***argv)
117117
path = **argv;
118118
NEXT_ARGP();
119119

120-
return open_obj_pinned_any(path, BPF_OBJ_LINK);
120+
return open_obj_pinned_any(path, BPF_OBJ_LINK, NULL);
121121
}
122122

123123
p_err("expected 'id' or 'pinned', got: '%s'?", **argv);

tools/bpf/bpftool/main.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <bpf/hashmap.h>
1717
#include <bpf/libbpf.h>
18+
#include <bpf/bpf.h>
1819

1920
#include "json_writer.h"
2021

@@ -140,8 +141,10 @@ void get_prog_full_name(const struct bpf_prog_info *prog_info, int prog_fd,
140141
int get_fd_type(int fd);
141142
const char *get_fd_type_name(enum bpf_obj_type type);
142143
char *get_fdinfo(int fd, const char *key);
143-
int open_obj_pinned(const char *path, bool quiet);
144-
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
144+
int open_obj_pinned(const char *path, bool quiet,
145+
const struct bpf_obj_get_opts *opts);
146+
int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type,
147+
const struct bpf_obj_get_opts *opts);
145148
int mount_bpffs_for_file(const char *file_name);
146149
int create_and_mount_bpffs_dir(const char *dir_name);
147150
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;
167170
int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what);
168171
int prog_parse_fd(int *argc, char ***argv);
169172
int prog_parse_fds(int *argc, char ***argv, int **fds);
170-
int map_parse_fd(int *argc, char ***argv);
171-
int map_parse_fds(int *argc, char ***argv, int **fds);
173+
int map_parse_fd(int *argc, char ***argv, __u32 open_flags);
174+
int map_parse_fds(int *argc, char ***argv, int **fds, __u32 open_flags);
172175
int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
173-
__u32 *info_len);
176+
__u32 *info_len, __u32 open_flags);
174177

175178
struct bpf_prog_linfo;
176179
#if defined(HAVE_LLVM_SUPPORT) || defined(HAVE_LIBBFD_SUPPORT)

0 commit comments

Comments
 (0)