diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
index 2cbc777f1520..4666a59d5fc6 100644
--- a/tools/bpf/bpftool/btf.c
+++ b/tools/bpf/bpftool/btf.c
@@ -566,6 +566,10 @@ static int do_dump(int argc, char **argv)
 	int fd = -1;
 	int err;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (!REQ_ARGS(2)) {
 		usage();
 		return -1;
@@ -580,7 +584,7 @@ static int do_dump(int argc, char **argv)
 			return -1;
 		}
 
-		fd = map_parse_fd_and_info(&argc, &argv, &info, &len, NULL);
+		fd = map_parse_fd_and_info(&argc, &argv, &info, &len, &opts);
 		if (fd < 0)
 			return -1;
 
@@ -753,6 +757,10 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
 	int err;
 	int fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	while (true) {
 		switch (type) {
 		case BPF_OBJ_PROG:
@@ -782,7 +790,7 @@ build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
 			fd = bpf_prog_get_fd_by_id_opts(id, NULL);
 			break;
 		case BPF_OBJ_MAP:
-			fd = bpf_map_get_fd_by_id_opts(id, NULL);
+			fd = bpf_map_get_fd_by_id_opts(id, &opts);
 			break;
 		default:
 			err = -1;
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 8a2412fc4410..dd58054bcce7 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -28,6 +28,7 @@
 #include <bpf/hashmap.h>
 #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
 #include <bpf/btf.h>
+#include <bpf/libbpf_internal.h> /* OPTS_GET */
 
 #include "main.h"
 
@@ -303,7 +304,11 @@ int do_pin_any(int argc, char **argv,
 	int err;
 	int fd;
 
-	fd = get_fd(&argc, &argv, NULL);
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
+	fd = get_fd(&argc, &argv, &opts);
 	if (fd < 0)
 		return fd;
 
@@ -474,10 +479,14 @@ static int do_build_table_cb(const char *fpath, const struct stat *sb,
 	int fd, err = 0;
 	char *path;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (typeflag != FTW_F)
 		goto out_ret;
 
-	fd = open_obj_pinned(fpath, true, NULL);
+	fd = open_obj_pinned(fpath, true, &opts);
 	if (fd < 0)
 		goto out_ret;
 
@@ -886,6 +895,10 @@ static int map_fd_by_name(char *name, int **fds,
 	void *tmp;
 	int err;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, search_opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	while (true) {
 		struct bpf_map_info info = {};
 		__u32 len = sizeof(info);
@@ -899,7 +912,7 @@ static int map_fd_by_name(char *name, int **fds,
 			return nb_fds;
 		}
 
-		fd = bpf_map_get_fd_by_id_opts(id, opts);
+		fd = bpf_map_get_fd_by_id_opts(id, &search_opts);
 		if (fd < 0) {
 			p_err("can't get map by id (%u): %s",
 			      id, strerror(errno));
@@ -918,6 +931,17 @@ static int map_fd_by_name(char *name, int **fds,
 			continue;
 		}
 
+		if (OPTS_GET(opts, flags, 0) != BPF_F_RDONLY) {
+			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) {
diff --git a/tools/bpf/bpftool/iter.c b/tools/bpf/bpftool/iter.c
index 1412be9eb298..40b3f8fddd90 100644
--- a/tools/bpf/bpftool/iter.c
+++ b/tools/bpf/bpftool/iter.c
@@ -18,6 +18,10 @@ static int do_pin(int argc, char **argv)
 	struct bpf_link *link;
 	int err = -1, map_fd = -1;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (!REQ_ARGS(2))
 		usage();
 
@@ -34,7 +38,7 @@ static int do_pin(int argc, char **argv)
 				return -1;
 			}
 
-			map_fd = map_parse_fd(&argc, &argv, NULL);
+			map_fd = map_parse_fd(&argc, &argv, &opts);
 			if (map_fd < 0)
 				return -1;
 
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index 103bd44cd851..e2936b0046ba 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -334,6 +334,10 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
 		      void *key, void *value, __u32 key_size, __u32 value_size,
 		      __u32 *flags, __u32 **value_fd)
 {
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (!*argv) {
 		if (!key && !value)
 			return 0;
@@ -381,7 +385,7 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
 				return -1;
 			}
 
-			fd = map_parse_fd(&argc, &argv, NULL);
+			fd = map_parse_fd(&argc, &argv, &opts);
 			if (fd < 0)
 				return -1;
 
@@ -629,12 +633,16 @@ static int do_show_subset(int argc, char **argv)
 	int nb_fds, i;
 	int err = -1;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	fds = malloc(sizeof(int));
 	if (!fds) {
 		p_err("mem alloc failed");
 		return -1;
 	}
-	nb_fds = map_parse_fds(&argc, &argv, &fds, NULL);
+	nb_fds = map_parse_fds(&argc, &argv, &fds, &opts);
 	if (nb_fds < 1)
 		goto exit_free;
 
@@ -673,6 +681,10 @@ static int do_show(int argc, char **argv)
 	int err;
 	int fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (show_pinned) {
 		map_table = hashmap__new(hash_fn_for_key_as_id,
 					 equal_fn_for_key_as_id, NULL);
@@ -702,7 +714,7 @@ static int do_show(int argc, char **argv)
 			break;
 		}
 
-		fd = bpf_map_get_fd_by_id_opts(id, NULL);
+		fd = bpf_map_get_fd_by_id_opts(id, &opts);
 		if (fd < 0) {
 			if (errno == ENOENT)
 				continue;
@@ -902,6 +914,10 @@ static int do_dump(int argc, char **argv)
 	int *fds = NULL;
 	int err = -1;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (argc != 2)
 		usage();
 
@@ -910,7 +926,7 @@ static int do_dump(int argc, char **argv)
 		p_err("mem alloc failed");
 		return -1;
 	}
-	nb_fds = map_parse_fds(&argc, &argv, &fds, NULL);
+	nb_fds = map_parse_fds(&argc, &argv, &fds, &opts);
 	if (nb_fds < 1)
 		goto exit_free;
 
@@ -995,10 +1011,14 @@ static int do_update(int argc, char **argv)
 	void *key, *value;
 	int fd, err;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_WRONLY,
+	);
+
 	if (argc < 2)
 		usage();
 
-	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, NULL);
+	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, &opts);
 	if (fd < 0)
 		return -1;
 
@@ -1074,10 +1094,14 @@ static int do_lookup(int argc, char **argv)
 	int err;
 	int fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (argc < 2)
 		usage();
 
-	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, NULL);
+	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, &opts);
 	if (fd < 0)
 		return -1;
 
@@ -1125,10 +1149,14 @@ static int do_getnext(int argc, char **argv)
 	int err;
 	int fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (argc < 2)
 		usage();
 
-	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, NULL);
+	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, &opts);
 	if (fd < 0)
 		return -1;
 
@@ -1196,10 +1224,14 @@ static int do_delete(int argc, char **argv)
 	int err;
 	int fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_WRONLY,
+	);
+
 	if (argc < 2)
 		usage();
 
-	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, NULL);
+	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, &opts);
 	if (fd < 0)
 		return -1;
 
diff --git a/tools/bpf/bpftool/map_perf_ring.c b/tools/bpf/bpftool/map_perf_ring.c
index fa062db08c87..8bc513d6eb55 100644
--- a/tools/bpf/bpftool/map_perf_ring.c
+++ b/tools/bpf/bpftool/map_perf_ring.c
@@ -125,6 +125,10 @@ int do_event_pipe(int argc, char **argv)
 	};
 	struct bpf_map_info map_info = {};
 	LIBBPF_OPTS(perf_buffer_raw_opts, opts);
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, map_opts,
+		.flags = BPF_F_WRONLY,
+	);
+
 	struct event_pipe_ctx ctx = {
 		.all_cpus = true,
 		.cpu = -1,
@@ -136,7 +140,7 @@ int do_event_pipe(int argc, char **argv)
 
 	map_info_len = sizeof(map_info);
 	map_fd = map_parse_fd_and_info(&argc, &argv, &map_info, &map_info_len,
-				       NULL);
+				       &map_opts);
 	if (map_fd < 0)
 		return -1;
 
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 648546342988..371a6510b2ed 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -227,6 +227,10 @@ static void *find_metadata(int prog_fd, struct bpf_map_info *map_info)
 	int ret;
 	__u32 i;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	memset(&prog_info, 0, sizeof(prog_info));
 	prog_info_len = sizeof(prog_info);
 	ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len);
@@ -251,7 +255,7 @@ static void *find_metadata(int prog_fd, struct bpf_map_info *map_info)
 		goto free_map_ids;
 
 	for (i = 0; i < prog_info.nr_map_ids; i++) {
-		map_fd = bpf_map_get_fd_by_id_opts(map_ids[i], NULL);
+		map_fd = bpf_map_get_fd_by_id_opts(map_ids[i], &opts);
 		if (map_fd < 0)
 			goto free_map_ids;
 
diff --git a/tools/bpf/bpftool/struct_ops.c b/tools/bpf/bpftool/struct_ops.c
index 51667db3f55f..5a93f14e2b6a 100644
--- a/tools/bpf/bpftool/struct_ops.c
+++ b/tools/bpf/bpftool/struct_ops.c
@@ -10,6 +10,7 @@
 #include <bpf/bpf.h>
 #include <bpf/btf.h>
 #include <bpf/libbpf.h>
+#include <bpf/libbpf_internal.h> /* OPTS_GET */
 
 #include "json_writer.h"
 #include "main.h"
@@ -136,6 +137,10 @@ static int get_next_struct_ops_map(const char *name, int *res_fd,
 	__u32 id = info->id;
 	int err, fd;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, search_opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	while (true) {
 		err = bpf_map_get_next_id(id, &id);
 		if (err) {
@@ -145,7 +150,7 @@ static int get_next_struct_ops_map(const char *name, int *res_fd,
 			return -1;
 		}
 
-		fd = bpf_map_get_fd_by_id_opts(id, opts);
+		fd = bpf_map_get_fd_by_id_opts(id, &search_opts);
 		if (fd < 0) {
 			if (errno == ENOENT)
 				continue;
@@ -163,6 +168,19 @@ static int get_next_struct_ops_map(const char *name, int *res_fd,
 
 		if (info->type == BPF_MAP_TYPE_STRUCT_OPS &&
 		    (!name || !strcmp(name, info->name))) {
+			if (OPTS_GET(opts, flags, 0) != BPF_F_RDONLY) {
+				close(fd);
+
+				fd = bpf_map_get_fd_by_id_opts(id, opts);
+				if (fd < 0) {
+					if (errno == ENOENT)
+						continue;
+					p_err("can't get map by id (%u): %s",
+					      id, strerror(errno));
+					return -1;
+				}
+			}
+
 			*res_fd = fd;
 			return 1;
 		}
@@ -340,6 +358,10 @@ static int do_show(int argc, char **argv)
 	const char *search_type = NULL, *search_term = NULL;
 	struct res res;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (argc && argc != 2)
 		usage();
 
@@ -349,7 +371,7 @@ static int do_show(int argc, char **argv)
 	}
 
 	res = do_work_on_struct_ops(search_type, search_term, __do_show,
-				    NULL, json_wtr, NULL);
+				    NULL, json_wtr, &opts);
 
 	return cmd_retval(&res, !!search_term);
 }
@@ -411,6 +433,10 @@ static int do_dump(int argc, char **argv)
 	struct btf_dumper d = {};
 	struct res res;
 
+	DECLARE_LIBBPF_OPTS(bpf_get_fd_opts, opts,
+		.flags = BPF_F_RDONLY,
+	);
+
 	if (argc && argc != 2)
 		usage();
 
@@ -438,7 +464,7 @@ static int do_dump(int argc, char **argv)
 	d.prog_id_as_func_ptr = true;
 
 	res = do_work_on_struct_ops(search_type, search_term, __do_dump, &d,
-				    wtr, NULL);
+				    wtr, &opts);
 
 	if (!json_output)
 		jsonw_destroy(&wtr);
