@@ -333,6 +333,7 @@ struct reloc_desc {
333
333
struct {
334
334
int map_idx ;
335
335
int sym_off ;
336
+ int ext_idx ;
336
337
};
337
338
};
338
339
};
@@ -4042,7 +4043,7 @@ static int bpf_program__record_reloc(struct bpf_program *prog,
4042
4043
else
4043
4044
reloc_desc -> type = RELO_EXTERN_LD64 ;
4044
4045
reloc_desc -> insn_idx = insn_idx ;
4045
- reloc_desc -> sym_off = i ; /* sym_off stores extern index */
4046
+ reloc_desc -> ext_idx = i ;
4046
4047
return 0 ;
4047
4048
}
4048
4049
@@ -5811,8 +5812,8 @@ bpf_object__relocate_core(struct bpf_object *obj, const char *targ_btf_path)
5811
5812
}
5812
5813
5813
5814
/* base map load ldimm64 special constant, used also for log fixup logic */
5814
- #define MAP_LDIMM64_POISON_BASE 2001000000
5815
- #define MAP_LDIMM64_POISON_PFX "200100"
5815
+ #define POISON_LDIMM64_MAP_BASE 2001000000
5816
+ #define POISON_LDIMM64_MAP_PFX "200100"
5816
5817
5817
5818
static void poison_map_ldimm64 (struct bpf_program * prog , int relo_idx ,
5818
5819
int insn_idx , struct bpf_insn * insn ,
@@ -5834,12 +5835,36 @@ static void poison_map_ldimm64(struct bpf_program *prog, int relo_idx,
5834
5835
* invalid func unknown#2001000123
5835
5836
* where lower 123 is map index into obj->maps[] array
5836
5837
*/
5837
- insn -> imm = MAP_LDIMM64_POISON_BASE + map_idx ;
5838
+ insn -> imm = POISON_LDIMM64_MAP_BASE + map_idx ;
5838
5839
5839
5840
insn ++ ;
5840
5841
}
5841
5842
}
5842
5843
5844
+ /* unresolved kfunc call special constant, used also for log fixup logic */
5845
+ #define POISON_CALL_KFUNC_BASE 2002000000
5846
+ #define POISON_CALL_KFUNC_PFX "2002"
5847
+
5848
+ static void poison_kfunc_call (struct bpf_program * prog , int relo_idx ,
5849
+ int insn_idx , struct bpf_insn * insn ,
5850
+ int ext_idx , const struct extern_desc * ext )
5851
+ {
5852
+ pr_debug ("prog '%s': relo #%d: poisoning insn #%d that calls kfunc '%s'\n" ,
5853
+ prog -> name , relo_idx , insn_idx , ext -> name );
5854
+
5855
+ /* we turn kfunc call into invalid helper call with identifiable constant */
5856
+ insn -> code = BPF_JMP | BPF_CALL ;
5857
+ insn -> dst_reg = 0 ;
5858
+ insn -> src_reg = 0 ;
5859
+ insn -> off = 0 ;
5860
+ /* if this instruction is reachable (not a dead code),
5861
+ * verifier will complain with something like:
5862
+ * invalid func unknown#2001000123
5863
+ * where lower 123 is extern index into obj->externs[] array
5864
+ */
5865
+ insn -> imm = POISON_CALL_KFUNC_BASE + ext_idx ;
5866
+ }
5867
+
5843
5868
/* Relocate data references within program code:
5844
5869
* - map references;
5845
5870
* - global variable references;
@@ -5885,7 +5910,7 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
5885
5910
}
5886
5911
break ;
5887
5912
case RELO_EXTERN_LD64 :
5888
- ext = & obj -> externs [relo -> sym_off ];
5913
+ ext = & obj -> externs [relo -> ext_idx ];
5889
5914
if (ext -> type == EXT_KCFG ) {
5890
5915
if (obj -> gen_loader ) {
5891
5916
insn [0 ].src_reg = BPF_PSEUDO_MAP_IDX_VALUE ;
@@ -5907,14 +5932,14 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog)
5907
5932
}
5908
5933
break ;
5909
5934
case RELO_EXTERN_CALL :
5910
- ext = & obj -> externs [relo -> sym_off ];
5935
+ ext = & obj -> externs [relo -> ext_idx ];
5911
5936
insn [0 ].src_reg = BPF_PSEUDO_KFUNC_CALL ;
5912
5937
if (ext -> is_set ) {
5913
5938
insn [0 ].imm = ext -> ksym .kernel_btf_id ;
5914
5939
insn [0 ].off = ext -> ksym .btf_fd_idx ;
5915
- } else { /* unresolved weak kfunc */
5916
- insn [ 0 ]. imm = 0 ;
5917
- insn [ 0 ]. off = 0 ;
5940
+ } else { /* unresolved weak kfunc call */
5941
+ poison_kfunc_call ( prog , i , relo -> insn_idx , insn ,
5942
+ relo -> ext_idx , ext ) ;
5918
5943
}
5919
5944
break ;
5920
5945
case RELO_SUBPROG_ADDR :
@@ -7022,13 +7047,13 @@ static void fixup_log_missing_map_load(struct bpf_program *prog,
7022
7047
char * buf , size_t buf_sz , size_t log_sz ,
7023
7048
char * line1 , char * line2 , char * line3 )
7024
7049
{
7025
- /* Expected log for failed and not properly guarded CO-RE relocation :
7050
+ /* Expected log for failed and not properly guarded map reference :
7026
7051
* line1 -> 123: (85) call unknown#2001000345
7027
7052
* line2 -> invalid func unknown#2001000345
7028
7053
* line3 -> <anything else or end of buffer>
7029
7054
*
7030
7055
* "123" is the index of the instruction that was poisoned.
7031
- * "345" in "2001000345" are map index in obj->maps to fetch map name.
7056
+ * "345" in "2001000345" is a map index in obj->maps to fetch map name.
7032
7057
*/
7033
7058
struct bpf_object * obj = prog -> obj ;
7034
7059
const struct bpf_map * map ;
@@ -7038,7 +7063,7 @@ static void fixup_log_missing_map_load(struct bpf_program *prog,
7038
7063
if (sscanf (line1 , "%d: (%*d) call unknown#%d\n" , & insn_idx , & map_idx ) != 2 )
7039
7064
return ;
7040
7065
7041
- map_idx -= MAP_LDIMM64_POISON_BASE ;
7066
+ map_idx -= POISON_LDIMM64_MAP_BASE ;
7042
7067
if (map_idx < 0 || map_idx >= obj -> nr_maps )
7043
7068
return ;
7044
7069
map = & obj -> maps [map_idx ];
@@ -7051,6 +7076,39 @@ static void fixup_log_missing_map_load(struct bpf_program *prog,
7051
7076
patch_log (buf , buf_sz , log_sz , line1 , line3 - line1 , patch );
7052
7077
}
7053
7078
7079
+ static void fixup_log_missing_kfunc_call (struct bpf_program * prog ,
7080
+ char * buf , size_t buf_sz , size_t log_sz ,
7081
+ char * line1 , char * line2 , char * line3 )
7082
+ {
7083
+ /* Expected log for failed and not properly guarded kfunc call:
7084
+ * line1 -> 123: (85) call unknown#2002000345
7085
+ * line2 -> invalid func unknown#2002000345
7086
+ * line3 -> <anything else or end of buffer>
7087
+ *
7088
+ * "123" is the index of the instruction that was poisoned.
7089
+ * "345" in "2002000345" is an extern index in obj->externs to fetch kfunc name.
7090
+ */
7091
+ struct bpf_object * obj = prog -> obj ;
7092
+ const struct extern_desc * ext ;
7093
+ int insn_idx , ext_idx ;
7094
+ char patch [128 ];
7095
+
7096
+ if (sscanf (line1 , "%d: (%*d) call unknown#%d\n" , & insn_idx , & ext_idx ) != 2 )
7097
+ return ;
7098
+
7099
+ ext_idx -= POISON_CALL_KFUNC_BASE ;
7100
+ if (ext_idx < 0 || ext_idx >= obj -> nr_extern )
7101
+ return ;
7102
+ ext = & obj -> externs [ext_idx ];
7103
+
7104
+ snprintf (patch , sizeof (patch ),
7105
+ "%d: <invalid kfunc call>\n"
7106
+ "kfunc '%s' is referenced but wasn't resolved\n" ,
7107
+ insn_idx , ext -> name );
7108
+
7109
+ patch_log (buf , buf_sz , log_sz , line1 , line3 - line1 , patch );
7110
+ }
7111
+
7054
7112
static void fixup_verifier_log (struct bpf_program * prog , char * buf , size_t buf_sz )
7055
7113
{
7056
7114
/* look for familiar error patterns in last N lines of the log */
@@ -7070,23 +7128,33 @@ static void fixup_verifier_log(struct bpf_program *prog, char *buf, size_t buf_s
7070
7128
if (!cur_line )
7071
7129
return ;
7072
7130
7073
- /* failed CO-RE relocation case */
7074
7131
if (str_has_pfx (cur_line , "invalid func unknown#195896080\n" )) {
7075
7132
prev_line = find_prev_line (buf , cur_line );
7076
7133
if (!prev_line )
7077
7134
continue ;
7078
7135
7136
+ /* failed CO-RE relocation case */
7079
7137
fixup_log_failed_core_relo (prog , buf , buf_sz , log_sz ,
7080
7138
prev_line , cur_line , next_line );
7081
7139
return ;
7082
- } else if (str_has_pfx (cur_line , "invalid func unknown#" MAP_LDIMM64_POISON_PFX )) {
7140
+ } else if (str_has_pfx (cur_line , "invalid func unknown#" POISON_LDIMM64_MAP_PFX )) {
7083
7141
prev_line = find_prev_line (buf , cur_line );
7084
7142
if (!prev_line )
7085
7143
continue ;
7086
7144
7145
+ /* reference to uncreated BPF map */
7087
7146
fixup_log_missing_map_load (prog , buf , buf_sz , log_sz ,
7088
7147
prev_line , cur_line , next_line );
7089
7148
return ;
7149
+ } else if (str_has_pfx (cur_line , "invalid func unknown#" POISON_CALL_KFUNC_PFX )) {
7150
+ prev_line = find_prev_line (buf , cur_line );
7151
+ if (!prev_line )
7152
+ continue ;
7153
+
7154
+ /* reference to unresolved kfunc */
7155
+ fixup_log_missing_kfunc_call (prog , buf , buf_sz , log_sz ,
7156
+ prev_line , cur_line , next_line );
7157
+ return ;
7090
7158
}
7091
7159
}
7092
7160
}
@@ -7098,7 +7166,7 @@ static int bpf_program_record_relos(struct bpf_program *prog)
7098
7166
7099
7167
for (i = 0 ; i < prog -> nr_reloc ; i ++ ) {
7100
7168
struct reloc_desc * relo = & prog -> reloc_desc [i ];
7101
- struct extern_desc * ext = & obj -> externs [relo -> sym_off ];
7169
+ struct extern_desc * ext = & obj -> externs [relo -> ext_idx ];
7102
7170
int kind ;
7103
7171
7104
7172
switch (relo -> type ) {
@@ -7536,8 +7604,9 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
7536
7604
ret = bpf_core_types_are_compat (obj -> btf , local_func_proto_id ,
7537
7605
kern_btf , kfunc_proto_id );
7538
7606
if (ret <= 0 ) {
7539
- pr_warn ("extern (func ksym) '%s': func_proto [%d] incompatible with kernel [%d]\n" ,
7540
- ext -> name , local_func_proto_id , kfunc_proto_id );
7607
+ pr_warn ("extern (func ksym) '%s': func_proto [%d] incompatible with %s [%d]\n" ,
7608
+ ext -> name , local_func_proto_id ,
7609
+ mod_btf ? mod_btf -> name : "vmlinux" , kfunc_proto_id );
7541
7610
return - EINVAL ;
7542
7611
}
7543
7612
@@ -7571,8 +7640,8 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj,
7571
7640
* {kernel_btf_id, kernel_btf_obj_fd} -> fixup ld_imm64.
7572
7641
*/
7573
7642
ext -> ksym .kernel_btf_obj_fd = mod_btf ? mod_btf -> fd : 0 ;
7574
- pr_debug ("extern (func ksym) '%s': resolved to kernel [%d]\n" ,
7575
- ext -> name , kfunc_id );
7643
+ pr_debug ("extern (func ksym) '%s': resolved to %s [%d]\n" ,
7644
+ ext -> name , mod_btf ? mod_btf -> name : "vmlinux" , kfunc_id );
7576
7645
7577
7646
return 0 ;
7578
7647
}
0 commit comments