@@ -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
@@ -2489,8 +2496,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
2489
2496
case PTR_TO_TCP_SOCK :
2490
2497
case PTR_TO_XDP_SOCK :
2491
2498
case PTR_TO_BTF_ID :
2492
- case PTR_TO_RDONLY_BUF :
2493
- case PTR_TO_RDWR_BUF :
2499
+ case PTR_TO_BUF :
2494
2500
case PTR_TO_PERCPU_BTF_ID :
2495
2501
case PTR_TO_MEM :
2496
2502
case PTR_TO_FUNC :
@@ -4185,22 +4191,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
4185
4191
} else if (reg -> type == CONST_PTR_TO_MAP ) {
4186
4192
err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
4187
4193
value_regno );
4188
- } else if (reg -> type == PTR_TO_RDONLY_BUF ) {
4189
- if (t == BPF_WRITE ) {
4190
- verbose (env , "R%d cannot write into %s\n" ,
4191
- regno , reg_type_str (env , reg -> type ));
4192
- return - EACCES ;
4194
+ } else if (base_type (reg -> type ) == PTR_TO_BUF ) {
4195
+ bool rdonly_mem = type_is_rdonly_mem (reg -> type );
4196
+ const char * buf_info ;
4197
+ u32 * max_access ;
4198
+
4199
+ if (rdonly_mem ) {
4200
+ if (t == BPF_WRITE ) {
4201
+ verbose (env , "R%d cannot write into %s\n" ,
4202
+ regno , reg_type_str (env , reg -> type ));
4203
+ return - EACCES ;
4204
+ }
4205
+ buf_info = "rdonly" ;
4206
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4207
+ } else {
4208
+ buf_info = "rdwr" ;
4209
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4193
4210
}
4211
+
4194
4212
err = check_buffer_access (env , reg , regno , off , size , false,
4195
- "rdonly" ,
4196
- & env -> prog -> aux -> max_rdonly_access );
4197
- if (!err && value_regno >= 0 )
4198
- mark_reg_unknown (env , regs , value_regno );
4199
- } else if (reg -> type == PTR_TO_RDWR_BUF ) {
4200
- err = check_buffer_access (env , reg , regno , off , size , false,
4201
- "rdwr" ,
4202
- & env -> prog -> aux -> max_rdwr_access );
4203
- if (!err && t == BPF_READ && value_regno >= 0 )
4213
+ buf_info , max_access );
4214
+
4215
+ if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ ))
4204
4216
mark_reg_unknown (env , regs , value_regno );
4205
4217
} else {
4206
4218
verbose (env , "R%d invalid mem access '%s'\n" , regno ,
@@ -4448,8 +4460,10 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4448
4460
struct bpf_call_arg_meta * meta )
4449
4461
{
4450
4462
struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4463
+ const char * buf_info ;
4464
+ u32 * max_access ;
4451
4465
4452
- switch (reg -> type ) {
4466
+ switch (base_type ( reg -> type ) ) {
4453
4467
case PTR_TO_PACKET :
4454
4468
case PTR_TO_PACKET_META :
4455
4469
return check_packet_access (env , regno , reg -> off , access_size ,
@@ -4468,18 +4482,20 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4468
4482
return check_mem_region_access (env , regno , reg -> off ,
4469
4483
access_size , reg -> mem_size ,
4470
4484
zero_size_allowed );
4471
- case PTR_TO_RDONLY_BUF :
4472
- if (meta && meta -> raw_mode )
4473
- return - EACCES ;
4474
- return check_buffer_access (env , reg , regno , reg -> off ,
4475
- access_size , zero_size_allowed ,
4476
- "rdonly" ,
4477
- & env -> prog -> aux -> max_rdonly_access );
4478
- case PTR_TO_RDWR_BUF :
4485
+ case PTR_TO_BUF :
4486
+ if (type_is_rdonly_mem (reg -> type )) {
4487
+ if (meta && meta -> raw_mode )
4488
+ return - EACCES ;
4489
+
4490
+ buf_info = "rdonly" ;
4491
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4492
+ } else {
4493
+ buf_info = "rdwr" ;
4494
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4495
+ }
4479
4496
return check_buffer_access (env , reg , regno , reg -> off ,
4480
4497
access_size , zero_size_allowed ,
4481
- "rdwr" ,
4482
- & env -> prog -> aux -> max_rdwr_access );
4498
+ buf_info , max_access );
4483
4499
case PTR_TO_STACK :
4484
4500
return check_stack_range_initialized (
4485
4501
env ,
@@ -4707,8 +4723,8 @@ static const struct bpf_reg_types mem_types = {
4707
4723
PTR_TO_MAP_KEY ,
4708
4724
PTR_TO_MAP_VALUE ,
4709
4725
PTR_TO_MEM ,
4710
- PTR_TO_RDONLY_BUF ,
4711
- PTR_TO_RDWR_BUF ,
4726
+ PTR_TO_BUF ,
4727
+ PTR_TO_BUF | MEM_RDONLY ,
4712
4728
},
4713
4729
};
4714
4730
0 commit comments