Skip to content

Commit 567010a

Browse files
sinkapAlexei Starovoitov
authored andcommitted
libbpf: Support exclusive map creation
Implement setters and getters that allow map to be registered as exclusive to the specified program. The registration should be done before the exclusive program is loaded. Signed-off-by: KP Singh <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent c297fe3 commit 567010a

File tree

5 files changed

+101
-2
lines changed

5 files changed

+101
-2
lines changed

tools/lib/bpf/bpf.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ int bpf_map_create(enum bpf_map_type map_type,
172172
__u32 max_entries,
173173
const struct bpf_map_create_opts *opts)
174174
{
175-
const size_t attr_sz = offsetofend(union bpf_attr, map_token_fd);
175+
const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
176176
union bpf_attr attr;
177177
int fd;
178178

@@ -203,6 +203,8 @@ int bpf_map_create(enum bpf_map_type map_type,
203203
attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0);
204204

205205
attr.map_token_fd = OPTS_GET(opts, token_fd, 0);
206+
attr.excl_prog_hash = ptr_to_u64(OPTS_GET(opts, excl_prog_hash, NULL));
207+
attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0);
206208

207209
fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
208210
return libbpf_err_errno(fd);

tools/lib/bpf/bpf.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ struct bpf_map_create_opts {
5454
__s32 value_type_btf_obj_fd;
5555

5656
__u32 token_fd;
57+
58+
const void *excl_prog_hash;
59+
__u32 excl_prog_hash_size;
5760
size_t :0;
5861
};
59-
#define bpf_map_create_opts__last_field token_fd
62+
#define bpf_map_create_opts__last_field excl_prog_hash_size
6063

6164
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
6265
const char *map_name,

tools/lib/bpf/libbpf.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ struct bpf_program {
499499
__u32 line_info_rec_size;
500500
__u32 line_info_cnt;
501501
__u32 prog_flags;
502+
__u8 hash[SHA256_DIGEST_LENGTH];
502503
};
503504

504505
struct bpf_struct_ops {
@@ -578,6 +579,7 @@ struct bpf_map {
578579
bool autocreate;
579580
bool autoattach;
580581
__u64 map_extra;
582+
struct bpf_program *excl_prog;
581583
};
582584

583585
enum extern_type {
@@ -4488,6 +4490,44 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx)
44884490
}
44894491
}
44904492

4493+
static int bpf_prog_compute_hash(struct bpf_program *prog)
4494+
{
4495+
struct bpf_insn *purged;
4496+
int i, err;
4497+
4498+
purged = calloc(prog->insns_cnt, BPF_INSN_SZ);
4499+
if (!purged)
4500+
return -ENOMEM;
4501+
4502+
/* If relocations have been done, the map_fd needs to be
4503+
* discarded for the digest calculation.
4504+
*/
4505+
for (i = 0; i < prog->insns_cnt; i++) {
4506+
purged[i] = prog->insns[i];
4507+
if (purged[i].code == (BPF_LD | BPF_IMM | BPF_DW) &&
4508+
(purged[i].src_reg == BPF_PSEUDO_MAP_FD ||
4509+
purged[i].src_reg == BPF_PSEUDO_MAP_VALUE)) {
4510+
purged[i].imm = 0;
4511+
i++;
4512+
if (i >= prog->insns_cnt ||
4513+
prog->insns[i].code != 0 ||
4514+
prog->insns[i].dst_reg != 0 ||
4515+
prog->insns[i].src_reg != 0 ||
4516+
prog->insns[i].off != 0) {
4517+
err = -EINVAL;
4518+
goto out;
4519+
}
4520+
purged[i] = prog->insns[i];
4521+
purged[i].imm = 0;
4522+
}
4523+
}
4524+
err = libbpf_sha256(purged, prog->insns_cnt * sizeof(struct bpf_insn),
4525+
prog->hash, SHA256_DIGEST_LENGTH);
4526+
out:
4527+
free(purged);
4528+
return err;
4529+
}
4530+
44914531
static int bpf_program__record_reloc(struct bpf_program *prog,
44924532
struct reloc_desc *reloc_desc,
44934533
__u32 insn_idx, const char *sym_name,
@@ -5237,6 +5277,14 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
52375277
create_attr.token_fd = obj->token_fd;
52385278
if (obj->token_fd)
52395279
create_attr.map_flags |= BPF_F_TOKEN_FD;
5280+
if (map->excl_prog) {
5281+
err = bpf_prog_compute_hash(map->excl_prog);
5282+
if (err)
5283+
return err;
5284+
5285+
create_attr.excl_prog_hash = map->excl_prog->hash;
5286+
create_attr.excl_prog_hash_size = SHA256_DIGEST_LENGTH;
5287+
}
52405288

52415289
if (bpf_map__is_struct_ops(map)) {
52425290
create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
@@ -10527,6 +10575,27 @@ int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd)
1052710575
return 0;
1052810576
}
1052910577

10578+
int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog)
10579+
{
10580+
if (map_is_created(map)) {
10581+
pr_warn("exclusive programs must be set before map creation\n");
10582+
return libbpf_err(-EINVAL);
10583+
}
10584+
10585+
if (map->obj != prog->obj) {
10586+
pr_warn("excl_prog and map must be from the same bpf object\n");
10587+
return libbpf_err(-EINVAL);
10588+
}
10589+
10590+
map->excl_prog = prog;
10591+
return 0;
10592+
}
10593+
10594+
struct bpf_program *bpf_map__exclusive_program(struct bpf_map *map)
10595+
{
10596+
return map->excl_prog;
10597+
}
10598+
1053010599
static struct bpf_map *
1053110600
__bpf_map__iter(const struct bpf_map *m, const struct bpf_object *obj, int i)
1053210601
{

tools/lib/bpf/libbpf.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,28 @@ LIBBPF_API int bpf_map__lookup_and_delete_elem(const struct bpf_map *map,
12911291
*/
12921292
LIBBPF_API int bpf_map__get_next_key(const struct bpf_map *map,
12931293
const void *cur_key, void *next_key, size_t key_sz);
1294+
/**
1295+
* @brief **bpf_map__set_exclusive_program()** sets a map to be exclusive to the
1296+
* specified program. This must be called *before* the map is created.
1297+
*
1298+
* @param map BPF map to make exclusive.
1299+
* @param prog BPF program to be the exclusive user of the map. Must belong
1300+
* to the same bpf_object as the map.
1301+
* @return 0 on success; a negative error code otherwise.
1302+
*
1303+
* This function must be called after the BPF object is opened but before
1304+
* it is loaded. Once the object is loaded, only the specified program
1305+
* will be able to access the map's contents.
1306+
*/
1307+
LIBBPF_API int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog);
1308+
1309+
/**
1310+
* @brief **bpf_map__exclusive_program()** returns the exclusive program
1311+
* that is registered with the map (if any).
1312+
* @param map BPF map to which the exclusive program is registered.
1313+
* @return the registered exclusive program.
1314+
*/
1315+
LIBBPF_API struct bpf_program *bpf_map__exclusive_program(struct bpf_map *map);
12941316

12951317
struct bpf_xdp_set_link_opts {
12961318
size_t sz;

tools/lib/bpf/libbpf.map

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,7 @@ LIBBPF_1.6.0 {
448448
} LIBBPF_1.5.0;
449449

450450
LIBBPF_1.7.0 {
451+
global:
452+
bpf_map__set_exclusive_program;
453+
bpf_map__exclusive_program;
451454
} LIBBPF_1.6.0;

0 commit comments

Comments
 (0)