Skip to content

Commit 5d23328

Browse files
zhuyifei1999Alexei Starovoitov
authored andcommitted
libbpf: Add BPF_PROG_BIND_MAP syscall and use it on .rodata section
The patch adds a simple wrapper bpf_prog_bind_map around the syscall. When the libbpf tries to load a program, it will probe the kernel for the support of this syscall and unconditionally bind .rodata section to the program. Signed-off-by: YiFei Zhu <[email protected]> Signed-off-by: Stanislav Fomichev <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Cc: YiFei Zhu <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent ef15314 commit 5d23328

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

tools/lib/bpf/bpf.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,19 @@ int bpf_enable_stats(enum bpf_stats_type type)
872872

873873
return sys_bpf(BPF_ENABLE_STATS, &attr, sizeof(attr));
874874
}
875+
876+
int bpf_prog_bind_map(int prog_fd, int map_fd,
877+
const struct bpf_prog_bind_opts *opts)
878+
{
879+
union bpf_attr attr;
880+
881+
if (!OPTS_VALID(opts, bpf_prog_bind_opts))
882+
return -EINVAL;
883+
884+
memset(&attr, 0, sizeof(attr));
885+
attr.prog_bind_map.prog_fd = prog_fd;
886+
attr.prog_bind_map.map_fd = map_fd;
887+
attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
888+
889+
return sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr));
890+
}

tools/lib/bpf/bpf.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
243243
enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
244244
LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);
245245

246+
struct bpf_prog_bind_opts {
247+
size_t sz; /* size of this struct for forward/backward compatibility */
248+
__u32 flags;
249+
};
250+
#define bpf_prog_bind_opts__last_field flags
251+
252+
LIBBPF_API int bpf_prog_bind_map(int prog_fd, int map_fd,
253+
const struct bpf_prog_bind_opts *opts);
246254
#ifdef __cplusplus
247255
} /* extern "C" */
248256
#endif

tools/lib/bpf/libbpf.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ enum kern_feature_id {
174174
FEAT_EXP_ATTACH_TYPE,
175175
/* bpf_probe_read_{kernel,user}[_str] helpers */
176176
FEAT_PROBE_READ_KERN,
177+
/* BPF_PROG_BIND_MAP is supported */
178+
FEAT_PROG_BIND_MAP,
177179
__FEAT_CNT,
178180
};
179181

@@ -409,6 +411,7 @@ struct bpf_object {
409411
struct extern_desc *externs;
410412
int nr_extern;
411413
int kconfig_map_idx;
414+
int rodata_map_idx;
412415

413416
bool loaded;
414417
bool has_subcalls;
@@ -1070,6 +1073,7 @@ static struct bpf_object *bpf_object__new(const char *path,
10701073
obj->efile.bss_shndx = -1;
10711074
obj->efile.st_ops_shndx = -1;
10721075
obj->kconfig_map_idx = -1;
1076+
obj->rodata_map_idx = -1;
10731077

10741078
obj->kern_version = get_kernel_version();
10751079
obj->loaded = false;
@@ -1428,6 +1432,8 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
14281432
obj->efile.rodata->d_size);
14291433
if (err)
14301434
return err;
1435+
1436+
obj->rodata_map_idx = obj->nr_maps - 1;
14311437
}
14321438
if (obj->efile.bss_shndx >= 0) {
14331439
err = bpf_object__init_internal_map(obj, LIBBPF_MAP_BSS,
@@ -3894,6 +3900,52 @@ static int probe_kern_probe_read_kernel(void)
38943900
return probe_fd(bpf_load_program_xattr(&attr, NULL, 0));
38953901
}
38963902

3903+
static int probe_prog_bind_map(void)
3904+
{
3905+
struct bpf_load_program_attr prg_attr;
3906+
struct bpf_create_map_attr map_attr;
3907+
char *cp, errmsg[STRERR_BUFSIZE];
3908+
struct bpf_insn insns[] = {
3909+
BPF_MOV64_IMM(BPF_REG_0, 0),
3910+
BPF_EXIT_INSN(),
3911+
};
3912+
int ret, map, prog;
3913+
3914+
memset(&map_attr, 0, sizeof(map_attr));
3915+
map_attr.map_type = BPF_MAP_TYPE_ARRAY;
3916+
map_attr.key_size = sizeof(int);
3917+
map_attr.value_size = 32;
3918+
map_attr.max_entries = 1;
3919+
3920+
map = bpf_create_map_xattr(&map_attr);
3921+
if (map < 0) {
3922+
ret = -errno;
3923+
cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg));
3924+
pr_warn("Error in %s():%s(%d). Couldn't create simple array map.\n",
3925+
__func__, cp, -ret);
3926+
return ret;
3927+
}
3928+
3929+
memset(&prg_attr, 0, sizeof(prg_attr));
3930+
prg_attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
3931+
prg_attr.insns = insns;
3932+
prg_attr.insns_cnt = ARRAY_SIZE(insns);
3933+
prg_attr.license = "GPL";
3934+
3935+
prog = bpf_load_program_xattr(&prg_attr, NULL, 0);
3936+
if (prog < 0) {
3937+
close(map);
3938+
return 0;
3939+
}
3940+
3941+
ret = bpf_prog_bind_map(prog, map, NULL);
3942+
3943+
close(map);
3944+
close(prog);
3945+
3946+
return ret >= 0;
3947+
}
3948+
38973949
enum kern_feature_result {
38983950
FEAT_UNKNOWN = 0,
38993951
FEAT_SUPPORTED = 1,
@@ -3934,6 +3986,9 @@ static struct kern_feature_desc {
39343986
},
39353987
[FEAT_PROBE_READ_KERN] = {
39363988
"bpf_probe_read_kernel() helper", probe_kern_probe_read_kernel,
3989+
},
3990+
[FEAT_PROG_BIND_MAP] = {
3991+
"BPF_PROG_BIND_MAP support", probe_prog_bind_map,
39373992
}
39383993
};
39393994

@@ -6468,6 +6523,20 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
64686523
if (ret >= 0) {
64696524
if (log_buf && load_attr.log_level)
64706525
pr_debug("verifier log:\n%s", log_buf);
6526+
6527+
if (prog->obj->rodata_map_idx >= 0 &&
6528+
kernel_supports(FEAT_PROG_BIND_MAP)) {
6529+
struct bpf_map *rodata_map =
6530+
&prog->obj->maps[prog->obj->rodata_map_idx];
6531+
6532+
if (bpf_prog_bind_map(ret, bpf_map__fd(rodata_map), NULL)) {
6533+
cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
6534+
pr_warn("prog '%s': failed to bind .rodata map: %s\n",
6535+
prog->name, cp);
6536+
/* Don't fail hard if can't bind rodata. */
6537+
}
6538+
}
6539+
64716540
*pfd = ret;
64726541
ret = 0;
64736542
goto out;

tools/lib/bpf/libbpf.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ LIBBPF_0.1.0 {
302302

303303
LIBBPF_0.2.0 {
304304
global:
305+
bpf_prog_bind_map;
305306
bpf_program__section_name;
306307
perf_buffer__buffer_cnt;
307308
perf_buffer__buffer_fd;

0 commit comments

Comments
 (0)