@@ -4377,7 +4377,7 @@ static u8 bpf_ctx_convert_map[] = {
4377
4377
#undef BPF_LINK_TYPE
4378
4378
4379
4379
static const struct btf_member *
4380
- btf_get_prog_ctx_type (struct bpf_verifier_log * log , struct btf * btf ,
4380
+ btf_get_prog_ctx_type (struct bpf_verifier_log * log , const struct btf * btf ,
4381
4381
const struct btf_type * t , enum bpf_prog_type prog_type ,
4382
4382
int arg )
4383
4383
{
@@ -5362,122 +5362,135 @@ int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *pr
5362
5362
return btf_check_func_type_match (log , btf1 , t1 , btf2 , t2 );
5363
5363
}
5364
5364
5365
- /* Compare BTF of a function with given bpf_reg_state.
5366
- * Returns:
5367
- * EFAULT - there is a verifier bug. Abort verification.
5368
- * EINVAL - there is a type mismatch or BTF is not available.
5369
- * 0 - BTF matches with what bpf_reg_state expects.
5370
- * Only PTR_TO_CTX and SCALAR_VALUE states are recognized.
5371
- */
5372
- int btf_check_func_arg_match (struct bpf_verifier_env * env , int subprog ,
5373
- struct bpf_reg_state * regs )
5365
+ static int btf_check_func_arg_match (struct bpf_verifier_env * env ,
5366
+ const struct btf * btf , u32 func_id ,
5367
+ struct bpf_reg_state * regs ,
5368
+ bool ptr_to_mem_ok )
5374
5369
{
5375
5370
struct bpf_verifier_log * log = & env -> log ;
5376
- struct bpf_prog * prog = env -> prog ;
5377
- struct btf * btf = prog -> aux -> btf ;
5378
- const struct btf_param * args ;
5371
+ const char * func_name , * ref_tname ;
5379
5372
const struct btf_type * t , * ref_t ;
5380
- u32 i , nargs , btf_id , type_size ;
5381
- const char * tname ;
5382
- bool is_global ;
5383
-
5384
- if (!prog -> aux -> func_info )
5385
- return - EINVAL ;
5386
-
5387
- btf_id = prog -> aux -> func_info [subprog ].type_id ;
5388
- if (!btf_id )
5389
- return - EFAULT ;
5390
-
5391
- if (prog -> aux -> func_info_aux [subprog ].unreliable )
5392
- return - EINVAL ;
5373
+ const struct btf_param * args ;
5374
+ u32 i , nargs ;
5393
5375
5394
- t = btf_type_by_id (btf , btf_id );
5376
+ t = btf_type_by_id (btf , func_id );
5395
5377
if (!t || !btf_type_is_func (t )) {
5396
5378
/* These checks were already done by the verifier while loading
5397
5379
* struct bpf_func_info
5398
5380
*/
5399
- bpf_log (log , "BTF of func#%d doesn't point to KIND_FUNC\n" ,
5400
- subprog );
5381
+ bpf_log (log , "BTF of func_id %u doesn't point to KIND_FUNC\n" ,
5382
+ func_id );
5401
5383
return - EFAULT ;
5402
5384
}
5403
- tname = btf_name_by_offset (btf , t -> name_off );
5385
+ func_name = btf_name_by_offset (btf , t -> name_off );
5404
5386
5405
5387
t = btf_type_by_id (btf , t -> type );
5406
5388
if (!t || !btf_type_is_func_proto (t )) {
5407
- bpf_log (log , "Invalid BTF of func %s\n" , tname );
5389
+ bpf_log (log , "Invalid BTF of func %s\n" , func_name );
5408
5390
return - EFAULT ;
5409
5391
}
5410
5392
args = (const struct btf_param * )(t + 1 );
5411
5393
nargs = btf_type_vlen (t );
5412
5394
if (nargs > MAX_BPF_FUNC_REG_ARGS ) {
5413
- bpf_log (log , "Function %s has %d > %d args\n" , tname , nargs ,
5395
+ bpf_log (log , "Function %s has %d > %d args\n" , func_name , nargs ,
5414
5396
MAX_BPF_FUNC_REG_ARGS );
5415
- goto out ;
5397
+ return - EINVAL ;
5416
5398
}
5417
5399
5418
- is_global = prog -> aux -> func_info_aux [subprog ].linkage == BTF_FUNC_GLOBAL ;
5419
5400
/* check that BTF function arguments match actual types that the
5420
5401
* verifier sees.
5421
5402
*/
5422
5403
for (i = 0 ; i < nargs ; i ++ ) {
5423
- struct bpf_reg_state * reg = & regs [i + 1 ];
5404
+ u32 regno = i + 1 ;
5405
+ struct bpf_reg_state * reg = & regs [regno ];
5424
5406
5425
- t = btf_type_by_id (btf , args [i ].type );
5426
- while (btf_type_is_modifier (t ))
5427
- t = btf_type_by_id (btf , t -> type );
5428
- if (btf_type_is_int (t ) || btf_type_is_enum (t )) {
5407
+ t = btf_type_skip_modifiers (btf , args [i ].type , NULL );
5408
+ if (btf_type_is_scalar (t )) {
5429
5409
if (reg -> type == SCALAR_VALUE )
5430
5410
continue ;
5431
- bpf_log (log , "R%d is not a scalar\n" , i + 1 );
5432
- goto out ;
5411
+ bpf_log (log , "R%d is not a scalar\n" , regno );
5412
+ return - EINVAL ;
5433
5413
}
5434
- if (btf_type_is_ptr (t )) {
5414
+
5415
+ if (!btf_type_is_ptr (t )) {
5416
+ bpf_log (log , "Unrecognized arg#%d type %s\n" ,
5417
+ i , btf_type_str (t ));
5418
+ return - EINVAL ;
5419
+ }
5420
+
5421
+ ref_t = btf_type_skip_modifiers (btf , t -> type , NULL );
5422
+ ref_tname = btf_name_by_offset (btf , ref_t -> name_off );
5423
+ if (btf_get_prog_ctx_type (log , btf , t , env -> prog -> type , i )) {
5435
5424
/* If function expects ctx type in BTF check that caller
5436
5425
* is passing PTR_TO_CTX.
5437
5426
*/
5438
- if (btf_get_prog_ctx_type (log , btf , t , prog -> type , i )) {
5439
- if (reg -> type != PTR_TO_CTX ) {
5440
- bpf_log (log ,
5441
- "arg#%d expected pointer to ctx, but got %s\n" ,
5442
- i , btf_kind_str [BTF_INFO_KIND (t -> info )]);
5443
- goto out ;
5444
- }
5445
- if (check_ctx_reg (env , reg , i + 1 ))
5446
- goto out ;
5447
- continue ;
5427
+ if (reg -> type != PTR_TO_CTX ) {
5428
+ bpf_log (log ,
5429
+ "arg#%d expected pointer to ctx, but got %s\n" ,
5430
+ i , btf_type_str (t ));
5431
+ return - EINVAL ;
5448
5432
}
5433
+ if (check_ctx_reg (env , reg , regno ))
5434
+ return - EINVAL ;
5435
+ } else if (ptr_to_mem_ok ) {
5436
+ const struct btf_type * resolve_ret ;
5437
+ u32 type_size ;
5449
5438
5450
- if (!is_global )
5451
- goto out ;
5452
-
5453
- t = btf_type_skip_modifiers (btf , t -> type , NULL );
5454
-
5455
- ref_t = btf_resolve_size (btf , t , & type_size );
5456
- if (IS_ERR (ref_t )) {
5439
+ resolve_ret = btf_resolve_size (btf , ref_t , & type_size );
5440
+ if (IS_ERR (resolve_ret )) {
5457
5441
bpf_log (log ,
5458
- "arg#%d reference type('%s %s') size cannot be determined: %ld\n" ,
5459
- i , btf_type_str (t ), btf_name_by_offset ( btf , t -> name_off ) ,
5460
- PTR_ERR (ref_t ));
5461
- goto out ;
5442
+ "arg#%d reference type('%s %s') size cannot be determined: %ld\n" ,
5443
+ i , btf_type_str (ref_t ), ref_tname ,
5444
+ PTR_ERR (resolve_ret ));
5445
+ return - EINVAL ;
5462
5446
}
5463
5447
5464
- if (check_mem_reg (env , reg , i + 1 , type_size ))
5465
- goto out ;
5466
-
5467
- continue ;
5448
+ if (check_mem_reg (env , reg , regno , type_size ))
5449
+ return - EINVAL ;
5450
+ } else {
5451
+ return - EINVAL ;
5468
5452
}
5469
- bpf_log (log , "Unrecognized arg#%d type %s\n" ,
5470
- i , btf_kind_str [BTF_INFO_KIND (t -> info )]);
5471
- goto out ;
5472
5453
}
5454
+
5473
5455
return 0 ;
5474
- out :
5456
+ }
5457
+
5458
+ /* Compare BTF of a function with given bpf_reg_state.
5459
+ * Returns:
5460
+ * EFAULT - there is a verifier bug. Abort verification.
5461
+ * EINVAL - there is a type mismatch or BTF is not available.
5462
+ * 0 - BTF matches with what bpf_reg_state expects.
5463
+ * Only PTR_TO_CTX and SCALAR_VALUE states are recognized.
5464
+ */
5465
+ int btf_check_subprog_arg_match (struct bpf_verifier_env * env , int subprog ,
5466
+ struct bpf_reg_state * regs )
5467
+ {
5468
+ struct bpf_prog * prog = env -> prog ;
5469
+ struct btf * btf = prog -> aux -> btf ;
5470
+ bool is_global ;
5471
+ u32 btf_id ;
5472
+ int err ;
5473
+
5474
+ if (!prog -> aux -> func_info )
5475
+ return - EINVAL ;
5476
+
5477
+ btf_id = prog -> aux -> func_info [subprog ].type_id ;
5478
+ if (!btf_id )
5479
+ return - EFAULT ;
5480
+
5481
+ if (prog -> aux -> func_info_aux [subprog ].unreliable )
5482
+ return - EINVAL ;
5483
+
5484
+ is_global = prog -> aux -> func_info_aux [subprog ].linkage == BTF_FUNC_GLOBAL ;
5485
+ err = btf_check_func_arg_match (env , btf , btf_id , regs , is_global );
5486
+
5475
5487
/* Compiler optimizations can remove arguments from static functions
5476
5488
* or mismatched type can be passed into a global function.
5477
5489
* In such cases mark the function as unreliable from BTF point of view.
5478
5490
*/
5479
- prog -> aux -> func_info_aux [subprog ].unreliable = true;
5480
- return - EINVAL ;
5491
+ if (err )
5492
+ prog -> aux -> func_info_aux [subprog ].unreliable = true;
5493
+ return err ;
5481
5494
}
5482
5495
5483
5496
/* Convert BTF of a function into bpf_reg_state if possible
0 commit comments