@@ -174,6 +174,8 @@ enum kern_feature_id {
174
174
FEAT_EXP_ATTACH_TYPE ,
175
175
/* bpf_probe_read_{kernel,user}[_str] helpers */
176
176
FEAT_PROBE_READ_KERN ,
177
+ /* BPF_PROG_BIND_MAP is supported */
178
+ FEAT_PROG_BIND_MAP ,
177
179
__FEAT_CNT ,
178
180
};
179
181
@@ -409,6 +411,7 @@ struct bpf_object {
409
411
struct extern_desc * externs ;
410
412
int nr_extern ;
411
413
int kconfig_map_idx ;
414
+ int rodata_map_idx ;
412
415
413
416
bool loaded ;
414
417
bool has_subcalls ;
@@ -1070,6 +1073,7 @@ static struct bpf_object *bpf_object__new(const char *path,
1070
1073
obj -> efile .bss_shndx = -1 ;
1071
1074
obj -> efile .st_ops_shndx = -1 ;
1072
1075
obj -> kconfig_map_idx = -1 ;
1076
+ obj -> rodata_map_idx = -1 ;
1073
1077
1074
1078
obj -> kern_version = get_kernel_version ();
1075
1079
obj -> loaded = false;
@@ -1428,6 +1432,8 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
1428
1432
obj -> efile .rodata -> d_size );
1429
1433
if (err )
1430
1434
return err ;
1435
+
1436
+ obj -> rodata_map_idx = obj -> nr_maps - 1 ;
1431
1437
}
1432
1438
if (obj -> efile .bss_shndx >= 0 ) {
1433
1439
err = bpf_object__init_internal_map (obj , LIBBPF_MAP_BSS ,
@@ -3894,6 +3900,52 @@ static int probe_kern_probe_read_kernel(void)
3894
3900
return probe_fd (bpf_load_program_xattr (& attr , NULL , 0 ));
3895
3901
}
3896
3902
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
+
3897
3949
enum kern_feature_result {
3898
3950
FEAT_UNKNOWN = 0 ,
3899
3951
FEAT_SUPPORTED = 1 ,
@@ -3934,6 +3986,9 @@ static struct kern_feature_desc {
3934
3986
},
3935
3987
[FEAT_PROBE_READ_KERN ] = {
3936
3988
"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 ,
3937
3992
}
3938
3993
};
3939
3994
@@ -6468,6 +6523,20 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
6468
6523
if (ret >= 0 ) {
6469
6524
if (log_buf && load_attr .log_level )
6470
6525
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
+
6471
6540
* pfd = ret ;
6472
6541
ret = 0 ;
6473
6542
goto out ;
0 commit comments