@@ -2651,8 +2651,8 @@ static s32 btf_func_check_meta(struct btf_verifier_env *env,
2651
2651
return - EINVAL ;
2652
2652
}
2653
2653
2654
- if (btf_type_vlen (t )) {
2655
- btf_verifier_log_type (env , t , "vlen != 0 " );
2654
+ if (btf_type_vlen (t ) > BTF_FUNC_GLOBAL ) {
2655
+ btf_verifier_log_type (env , t , "Invalid func linkage " );
2656
2656
return - EINVAL ;
2657
2657
}
2658
2658
@@ -3506,7 +3506,8 @@ static u8 bpf_ctx_convert_map[] = {
3506
3506
3507
3507
static const struct btf_member *
3508
3508
btf_get_prog_ctx_type (struct bpf_verifier_log * log , struct btf * btf ,
3509
- const struct btf_type * t , enum bpf_prog_type prog_type )
3509
+ const struct btf_type * t , enum bpf_prog_type prog_type ,
3510
+ int arg )
3510
3511
{
3511
3512
const struct btf_type * conv_struct ;
3512
3513
const struct btf_type * ctx_struct ;
@@ -3527,12 +3528,13 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
3527
3528
* is not supported yet.
3528
3529
* BPF_PROG_TYPE_RAW_TRACEPOINT is fine.
3529
3530
*/
3530
- bpf_log (log , "BPF program ctx type is not a struct\n" );
3531
+ if (log -> level & BPF_LOG_LEVEL )
3532
+ bpf_log (log , "arg#%d type is not a struct\n" , arg );
3531
3533
return NULL ;
3532
3534
}
3533
3535
tname = btf_name_by_offset (btf , t -> name_off );
3534
3536
if (!tname ) {
3535
- bpf_log (log , "BPF program ctx struct doesn't have a name\n" );
3537
+ bpf_log (log , "arg#%d struct doesn't have a name\n" , arg );
3536
3538
return NULL ;
3537
3539
}
3538
3540
/* prog_type is valid bpf program type. No need for bounds check. */
@@ -3565,11 +3567,12 @@ btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
3565
3567
static int btf_translate_to_vmlinux (struct bpf_verifier_log * log ,
3566
3568
struct btf * btf ,
3567
3569
const struct btf_type * t ,
3568
- enum bpf_prog_type prog_type )
3570
+ enum bpf_prog_type prog_type ,
3571
+ int arg )
3569
3572
{
3570
3573
const struct btf_member * prog_ctx_type , * kern_ctx_type ;
3571
3574
3572
- prog_ctx_type = btf_get_prog_ctx_type (log , btf , t , prog_type );
3575
+ prog_ctx_type = btf_get_prog_ctx_type (log , btf , t , prog_type , arg );
3573
3576
if (!prog_ctx_type )
3574
3577
return - ENOENT ;
3575
3578
kern_ctx_type = prog_ctx_type + 1 ;
@@ -3731,7 +3734,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
3731
3734
info -> reg_type = PTR_TO_BTF_ID ;
3732
3735
3733
3736
if (tgt_prog ) {
3734
- ret = btf_translate_to_vmlinux (log , btf , t , tgt_prog -> type );
3737
+ ret = btf_translate_to_vmlinux (log , btf , t , tgt_prog -> type , arg );
3735
3738
if (ret > 0 ) {
3736
3739
info -> btf_id = ret ;
3737
3740
return true;
@@ -4112,11 +4115,16 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
4112
4115
return 0 ;
4113
4116
}
4114
4117
4115
- int btf_check_func_arg_match (struct bpf_verifier_env * env , int subprog )
4118
+ /* Compare BTF of a function with given bpf_reg_state.
4119
+ * Returns:
4120
+ * EFAULT - there is a verifier bug. Abort verification.
4121
+ * EINVAL - there is a type mismatch or BTF is not available.
4122
+ * 0 - BTF matches with what bpf_reg_state expects.
4123
+ * Only PTR_TO_CTX and SCALAR_VALUE states are recognized.
4124
+ */
4125
+ int btf_check_func_arg_match (struct bpf_verifier_env * env , int subprog ,
4126
+ struct bpf_reg_state * reg )
4116
4127
{
4117
- struct bpf_verifier_state * st = env -> cur_state ;
4118
- struct bpf_func_state * func = st -> frame [st -> curframe ];
4119
- struct bpf_reg_state * reg = func -> regs ;
4120
4128
struct bpf_verifier_log * log = & env -> log ;
4121
4129
struct bpf_prog * prog = env -> prog ;
4122
4130
struct btf * btf = prog -> aux -> btf ;
@@ -4126,27 +4134,30 @@ int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog)
4126
4134
const char * tname ;
4127
4135
4128
4136
if (!prog -> aux -> func_info )
4129
- return 0 ;
4137
+ return - EINVAL ;
4130
4138
4131
4139
btf_id = prog -> aux -> func_info [subprog ].type_id ;
4132
4140
if (!btf_id )
4133
- return 0 ;
4141
+ return - EFAULT ;
4134
4142
4135
4143
if (prog -> aux -> func_info_aux [subprog ].unreliable )
4136
- return 0 ;
4144
+ return - EINVAL ;
4137
4145
4138
4146
t = btf_type_by_id (btf , btf_id );
4139
4147
if (!t || !btf_type_is_func (t )) {
4140
- bpf_log (log , "BTF of subprog %d doesn't point to KIND_FUNC\n" ,
4148
+ /* These checks were already done by the verifier while loading
4149
+ * struct bpf_func_info
4150
+ */
4151
+ bpf_log (log , "BTF of func#%d doesn't point to KIND_FUNC\n" ,
4141
4152
subprog );
4142
- return - EINVAL ;
4153
+ return - EFAULT ;
4143
4154
}
4144
4155
tname = btf_name_by_offset (btf , t -> name_off );
4145
4156
4146
4157
t = btf_type_by_id (btf , t -> type );
4147
4158
if (!t || !btf_type_is_func_proto (t )) {
4148
- bpf_log (log , "Invalid type of func %s\n" , tname );
4149
- return - EINVAL ;
4159
+ bpf_log (log , "Invalid BTF of func %s\n" , tname );
4160
+ return - EFAULT ;
4150
4161
}
4151
4162
args = (const struct btf_param * )(t + 1 );
4152
4163
nargs = btf_type_vlen (t );
@@ -4172,25 +4183,127 @@ int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog)
4172
4183
bpf_log (log , "R%d is not a pointer\n" , i + 1 );
4173
4184
goto out ;
4174
4185
}
4175
- /* If program is passing PTR_TO_CTX into subprogram
4176
- * check that BTF type matches .
4186
+ /* If function expects ctx type in BTF check that caller
4187
+ * is passing PTR_TO_CTX .
4177
4188
*/
4178
- if (reg [i + 1 ].type == PTR_TO_CTX &&
4179
- !btf_get_prog_ctx_type (log , btf , t , prog -> type ))
4180
- goto out ;
4181
- /* All other pointers are ok */
4182
- continue ;
4189
+ if (btf_get_prog_ctx_type (log , btf , t , prog -> type , i )) {
4190
+ if (reg [i + 1 ].type != PTR_TO_CTX ) {
4191
+ bpf_log (log ,
4192
+ "arg#%d expected pointer to ctx, but got %s\n" ,
4193
+ i , btf_kind_str [BTF_INFO_KIND (t -> info )]);
4194
+ goto out ;
4195
+ }
4196
+ if (check_ctx_reg (env , & reg [i + 1 ], i + 1 ))
4197
+ goto out ;
4198
+ continue ;
4199
+ }
4183
4200
}
4184
- bpf_log (log , "Unrecognized argument type %s\n" ,
4185
- btf_kind_str [BTF_INFO_KIND (t -> info )]);
4201
+ bpf_log (log , "Unrecognized arg#%d type %s\n" ,
4202
+ i , btf_kind_str [BTF_INFO_KIND (t -> info )]);
4186
4203
goto out ;
4187
4204
}
4188
4205
return 0 ;
4189
4206
out :
4190
- /* LLVM optimizations can remove arguments from static functions. */
4191
- bpf_log (log ,
4192
- "Type info disagrees with actual arguments due to compiler optimizations\n" );
4207
+ /* Compiler optimizations can remove arguments from static functions
4208
+ * or mismatched type can be passed into a global function.
4209
+ * In such cases mark the function as unreliable from BTF point of view.
4210
+ */
4193
4211
prog -> aux -> func_info_aux [subprog ].unreliable = true;
4212
+ return - EINVAL ;
4213
+ }
4214
+
4215
+ /* Convert BTF of a function into bpf_reg_state if possible
4216
+ * Returns:
4217
+ * EFAULT - there is a verifier bug. Abort verification.
4218
+ * EINVAL - cannot convert BTF.
4219
+ * 0 - Successfully converted BTF into bpf_reg_state
4220
+ * (either PTR_TO_CTX or SCALAR_VALUE).
4221
+ */
4222
+ int btf_prepare_func_args (struct bpf_verifier_env * env , int subprog ,
4223
+ struct bpf_reg_state * reg )
4224
+ {
4225
+ struct bpf_verifier_log * log = & env -> log ;
4226
+ struct bpf_prog * prog = env -> prog ;
4227
+ struct btf * btf = prog -> aux -> btf ;
4228
+ const struct btf_param * args ;
4229
+ const struct btf_type * t ;
4230
+ u32 i , nargs , btf_id ;
4231
+ const char * tname ;
4232
+
4233
+ if (!prog -> aux -> func_info ||
4234
+ prog -> aux -> func_info_aux [subprog ].linkage != BTF_FUNC_GLOBAL ) {
4235
+ bpf_log (log , "Verifier bug\n" );
4236
+ return - EFAULT ;
4237
+ }
4238
+
4239
+ btf_id = prog -> aux -> func_info [subprog ].type_id ;
4240
+ if (!btf_id ) {
4241
+ bpf_log (log , "Global functions need valid BTF\n" );
4242
+ return - EFAULT ;
4243
+ }
4244
+
4245
+ t = btf_type_by_id (btf , btf_id );
4246
+ if (!t || !btf_type_is_func (t )) {
4247
+ /* These checks were already done by the verifier while loading
4248
+ * struct bpf_func_info
4249
+ */
4250
+ bpf_log (log , "BTF of func#%d doesn't point to KIND_FUNC\n" ,
4251
+ subprog );
4252
+ return - EFAULT ;
4253
+ }
4254
+ tname = btf_name_by_offset (btf , t -> name_off );
4255
+
4256
+ if (log -> level & BPF_LOG_LEVEL )
4257
+ bpf_log (log , "Validating %s() func#%d...\n" ,
4258
+ tname , subprog );
4259
+
4260
+ if (prog -> aux -> func_info_aux [subprog ].unreliable ) {
4261
+ bpf_log (log , "Verifier bug in function %s()\n" , tname );
4262
+ return - EFAULT ;
4263
+ }
4264
+
4265
+ t = btf_type_by_id (btf , t -> type );
4266
+ if (!t || !btf_type_is_func_proto (t )) {
4267
+ bpf_log (log , "Invalid type of function %s()\n" , tname );
4268
+ return - EFAULT ;
4269
+ }
4270
+ args = (const struct btf_param * )(t + 1 );
4271
+ nargs = btf_type_vlen (t );
4272
+ if (nargs > 5 ) {
4273
+ bpf_log (log , "Global function %s() with %d > 5 args. Buggy compiler.\n" ,
4274
+ tname , nargs );
4275
+ return - EINVAL ;
4276
+ }
4277
+ /* check that function returns int */
4278
+ t = btf_type_by_id (btf , t -> type );
4279
+ while (btf_type_is_modifier (t ))
4280
+ t = btf_type_by_id (btf , t -> type );
4281
+ if (!btf_type_is_int (t ) && !btf_type_is_enum (t )) {
4282
+ bpf_log (log ,
4283
+ "Global function %s() doesn't return scalar. Only those are supported.\n" ,
4284
+ tname );
4285
+ return - EINVAL ;
4286
+ }
4287
+ /* Convert BTF function arguments into verifier types.
4288
+ * Only PTR_TO_CTX and SCALAR are supported atm.
4289
+ */
4290
+ for (i = 0 ; i < nargs ; i ++ ) {
4291
+ t = btf_type_by_id (btf , args [i ].type );
4292
+ while (btf_type_is_modifier (t ))
4293
+ t = btf_type_by_id (btf , t -> type );
4294
+ if (btf_type_is_int (t ) || btf_type_is_enum (t )) {
4295
+ reg [i + 1 ].type = SCALAR_VALUE ;
4296
+ continue ;
4297
+ }
4298
+ if (btf_type_is_ptr (t ) &&
4299
+ btf_get_prog_ctx_type (log , btf , t , prog -> type , i )) {
4300
+ reg [i + 1 ].type = PTR_TO_CTX ;
4301
+ continue ;
4302
+ }
4303
+ bpf_log (log , "Arg#%d type %s in %s() is not supported yet.\n" ,
4304
+ i , btf_kind_str [BTF_INFO_KIND (t -> info )], tname );
4305
+ return - EINVAL ;
4306
+ }
4194
4307
return 0 ;
4195
4308
}
4196
4309
0 commit comments