Skip to content

Commit d38fab4

Browse files
committed
libbpf: Support exclusive map creation
Implement setters and getters that allow map to be registers as exclusive to the specified program. The registration should be done before the exclusive program is loaded.
1 parent 94be364 commit d38fab4

File tree

5 files changed

+92
-2
lines changed

5 files changed

+92
-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);
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: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ struct bpf_map_create_opts {
5454
__s32 value_type_btf_obj_fd;
5555

5656
__u32 token_fd;
57+
__u32 excl_prog_hash_size;
58+
const void *excl_prog_hash;
5759
size_t :0;
5860
};
59-
#define bpf_map_create_opts__last_field token_fd
61+
#define bpf_map_create_opts__last_field excl_prog_hash
6062

6163
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
6264
const char *map_name,

tools/lib/bpf/libbpf.c

Lines changed: 66 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,43 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx)
44884490
}
44894491
}
44904492

4493+
static int bpf_program__compute_hash(struct bpf_program *prog)
4494+
{
4495+
struct bpf_insn *purged;
4496+
int i, err;
4497+
4498+
purged = calloc(1, BPF_INSN_SZ * prog->insns_cnt);
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), prog->hash, SHA256_DIGEST_LENGTH);
4525+
out:
4526+
free(purged);
4527+
return err;
4528+
}
4529+
44914530
static int bpf_program__record_reloc(struct bpf_program *prog,
44924531
struct reloc_desc *reloc_desc,
44934532
__u32 insn_idx, const char *sym_name,
@@ -5227,6 +5266,18 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
52275266
create_attr.token_fd = obj->token_fd;
52285267
if (obj->token_fd)
52295268
create_attr.map_flags |= BPF_F_TOKEN_FD;
5269+
if (map->excl_prog) {
5270+
if (map->excl_prog->obj->state == OBJ_LOADED) {
5271+
pr_warn("exclusive program already loaded\n");
5272+
return libbpf_err(-EINVAL);
5273+
}
5274+
err = bpf_program__compute_hash(map->excl_prog);
5275+
if (err)
5276+
return err;
5277+
5278+
create_attr.excl_prog_hash = map->excl_prog->hash;
5279+
create_attr.excl_prog_hash_size = SHA256_DIGEST_LENGTH;
5280+
}
52305281

52315282
if (bpf_map__is_struct_ops(map)) {
52325283
create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
@@ -10517,6 +10568,21 @@ int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd)
1051710568
return 0;
1051810569
}
1051910570

10571+
int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog)
10572+
{
10573+
if (map_is_created(map)) {
10574+
pr_warn("exclusive programs must be set before map creation\n");
10575+
return libbpf_err(-EINVAL);
10576+
}
10577+
map->excl_prog = prog;
10578+
return 0;
10579+
}
10580+
10581+
struct bpf_program *bpf_map__get_exclusive_program(struct bpf_map *map)
10582+
{
10583+
return map->excl_prog;
10584+
}
10585+
1052010586
static struct bpf_map *
1052110587
__bpf_map__iter(const struct bpf_map *m, const struct bpf_object *obj, int i)
1052210588
{

tools/lib/bpf/libbpf.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,25 @@ LIBBPF_API int bpf_map__lookup_and_delete_elem(const struct bpf_map *map,
12641264
*/
12651265
LIBBPF_API int bpf_map__get_next_key(const struct bpf_map *map,
12661266
const void *cur_key, void *next_key, size_t key_sz);
1267+
/**
1268+
* @brief **bpf_map__set_exclusive_program()** sets map to be exclusive to the
1269+
* to the specified program. The program must not be loaded yet.
1270+
* @param map BPF map to make exclusive.
1271+
* @param prog BPF program to be the exclusive user of the map.
1272+
* @return 0 on success; a negative error code otherwise.
1273+
*
1274+
* Once a map is made exclusive, only the specified program can access its
1275+
* contents.
1276+
*/
1277+
LIBBPF_API int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog);
12671278

1279+
/**
1280+
* @brief **bpf_map__get_exclusive_program()** returns the exclusive program
1281+
* that is registered with the map (if any).
1282+
* @param map BPF map to which the exclusive program is registered.
1283+
* @return the registered exclusive program.
1284+
*/
1285+
LIBBPF_API struct bpf_program *bpf_map__get_exclusive_program(struct bpf_map *map);
12681286
struct bpf_xdp_set_link_opts {
12691287
size_t sz;
12701288
int old_fd;

tools/lib/bpf/libbpf.map

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ LIBBPF_1.6.0 {
436436
bpf_linker__add_buf;
437437
bpf_linker__add_fd;
438438
bpf_linker__new_fd;
439+
bpf_map__set_exclusive_program;
440+
bpf_map__get_exclusive_program;
439441
bpf_object__prepare;
440442
bpf_prog_stream_read;
441443
bpf_program__attach_cgroup_opts;

0 commit comments

Comments
 (0)