@@ -459,6 +459,11 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
459
459
base_type (type ) == PTR_TO_MEM ;
460
460
}
461
461
462
+ static bool type_is_rdonly_mem (u32 type )
463
+ {
464
+ return type & MEM_RDONLY ;
465
+ }
466
+
462
467
static bool arg_type_may_be_refcounted (enum bpf_arg_type type )
463
468
{
464
469
return type == ARG_PTR_TO_SOCK_COMMON ;
@@ -534,7 +539,7 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
534
539
static const char * reg_type_str (struct bpf_verifier_env * env ,
535
540
enum bpf_reg_type type )
536
541
{
537
- char postfix [16 ] = {0 };
542
+ char postfix [16 ] = {0 }, prefix [ 16 ] = { 0 } ;
538
543
static const char * const str [] = {
539
544
[NOT_INIT ] = "?" ,
540
545
[SCALAR_VALUE ] = "inv" ,
@@ -554,8 +559,7 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
554
559
[PTR_TO_BTF_ID ] = "ptr_" ,
555
560
[PTR_TO_PERCPU_BTF_ID ] = "percpu_ptr_" ,
556
561
[PTR_TO_MEM ] = "mem" ,
557
- [PTR_TO_RDONLY_BUF ] = "rdonly_buf" ,
558
- [PTR_TO_RDWR_BUF ] = "rdwr_buf" ,
562
+ [PTR_TO_BUF ] = "buf" ,
559
563
[PTR_TO_FUNC ] = "func" ,
560
564
[PTR_TO_MAP_KEY ] = "map_key" ,
561
565
};
@@ -568,8 +572,11 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
568
572
strncpy (postfix , "_or_null" , 16 );
569
573
}
570
574
571
- snprintf (env -> type_str_buf , TYPE_STR_BUF_LEN , "%s%s" ,
572
- str [base_type (type )], postfix );
575
+ if (type & MEM_RDONLY )
576
+ strncpy (prefix , "rdonly_" , 16 );
577
+
578
+ snprintf (env -> type_str_buf , TYPE_STR_BUF_LEN , "%s%s%s" ,
579
+ prefix , str [base_type (type )], postfix );
573
580
return env -> type_str_buf ;
574
581
}
575
582
@@ -2493,8 +2500,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
2493
2500
case PTR_TO_TCP_SOCK :
2494
2501
case PTR_TO_XDP_SOCK :
2495
2502
case PTR_TO_BTF_ID :
2496
- case PTR_TO_RDONLY_BUF :
2497
- case PTR_TO_RDWR_BUF :
2503
+ case PTR_TO_BUF :
2498
2504
case PTR_TO_PERCPU_BTF_ID :
2499
2505
case PTR_TO_MEM :
2500
2506
case PTR_TO_FUNC :
@@ -4187,22 +4193,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
4187
4193
} else if (reg -> type == CONST_PTR_TO_MAP ) {
4188
4194
err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
4189
4195
value_regno );
4190
- } else if (reg -> type == PTR_TO_RDONLY_BUF ) {
4191
- if (t == BPF_WRITE ) {
4192
- verbose (env , "R%d cannot write into %s\n" ,
4193
- regno , reg_type_str (env , reg -> type ));
4194
- return - EACCES ;
4196
+ } else if (base_type (reg -> type ) == PTR_TO_BUF ) {
4197
+ bool rdonly_mem = type_is_rdonly_mem (reg -> type );
4198
+ const char * buf_info ;
4199
+ u32 * max_access ;
4200
+
4201
+ if (rdonly_mem ) {
4202
+ if (t == BPF_WRITE ) {
4203
+ verbose (env , "R%d cannot write into %s\n" ,
4204
+ regno , reg_type_str (env , reg -> type ));
4205
+ return - EACCES ;
4206
+ }
4207
+ buf_info = "rdonly" ;
4208
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4209
+ } else {
4210
+ buf_info = "rdwr" ;
4211
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4195
4212
}
4213
+
4196
4214
err = check_buffer_access (env , reg , regno , off , size , false,
4197
- "rdonly" ,
4198
- & env -> prog -> aux -> max_rdonly_access );
4199
- if (!err && value_regno >= 0 )
4200
- mark_reg_unknown (env , regs , value_regno );
4201
- } else if (reg -> type == PTR_TO_RDWR_BUF ) {
4202
- err = check_buffer_access (env , reg , regno , off , size , false,
4203
- "rdwr" ,
4204
- & env -> prog -> aux -> max_rdwr_access );
4205
- if (!err && t == BPF_READ && value_regno >= 0 )
4215
+ buf_info , max_access );
4216
+
4217
+ if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ ))
4206
4218
mark_reg_unknown (env , regs , value_regno );
4207
4219
} else {
4208
4220
verbose (env , "R%d invalid mem access '%s'\n" , regno ,
@@ -4450,8 +4462,10 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4450
4462
struct bpf_call_arg_meta * meta )
4451
4463
{
4452
4464
struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4465
+ const char * buf_info ;
4466
+ u32 * max_access ;
4453
4467
4454
- switch (reg -> type ) {
4468
+ switch (base_type ( reg -> type ) ) {
4455
4469
case PTR_TO_PACKET :
4456
4470
case PTR_TO_PACKET_META :
4457
4471
return check_packet_access (env , regno , reg -> off , access_size ,
@@ -4470,18 +4484,20 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4470
4484
return check_mem_region_access (env , regno , reg -> off ,
4471
4485
access_size , reg -> mem_size ,
4472
4486
zero_size_allowed );
4473
- case PTR_TO_RDONLY_BUF :
4474
- if (meta && meta -> raw_mode )
4475
- return - EACCES ;
4476
- return check_buffer_access (env , reg , regno , reg -> off ,
4477
- access_size , zero_size_allowed ,
4478
- "rdonly" ,
4479
- & env -> prog -> aux -> max_rdonly_access );
4480
- case PTR_TO_RDWR_BUF :
4487
+ case PTR_TO_BUF :
4488
+ if (type_is_rdonly_mem (reg -> type )) {
4489
+ if (meta && meta -> raw_mode )
4490
+ return - EACCES ;
4491
+
4492
+ buf_info = "rdonly" ;
4493
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4494
+ } else {
4495
+ buf_info = "rdwr" ;
4496
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4497
+ }
4481
4498
return check_buffer_access (env , reg , regno , reg -> off ,
4482
4499
access_size , zero_size_allowed ,
4483
- "rdwr" ,
4484
- & env -> prog -> aux -> max_rdwr_access );
4500
+ buf_info , max_access );
4485
4501
case PTR_TO_STACK :
4486
4502
return check_stack_range_initialized (
4487
4503
env ,
@@ -4709,8 +4725,8 @@ static const struct bpf_reg_types mem_types = {
4709
4725
PTR_TO_MAP_KEY ,
4710
4726
PTR_TO_MAP_VALUE ,
4711
4727
PTR_TO_MEM ,
4712
- PTR_TO_RDONLY_BUF ,
4713
- PTR_TO_RDWR_BUF ,
4728
+ PTR_TO_BUF ,
4729
+ PTR_TO_BUF | MEM_RDONLY ,
4714
4730
},
4715
4731
};
4716
4732
0 commit comments