@@ -455,6 +455,11 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
455
455
base_type (type ) == PTR_TO_MEM ;
456
456
}
457
457
458
+ static bool type_is_rdonly_mem (u32 type )
459
+ {
460
+ return type & MEM_RDONLY ;
461
+ }
462
+
458
463
static bool arg_type_may_be_refcounted (enum bpf_arg_type type )
459
464
{
460
465
return type == ARG_PTR_TO_SOCK_COMMON ;
@@ -530,7 +535,7 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
530
535
static const char * reg_type_str (struct bpf_verifier_env * env ,
531
536
enum bpf_reg_type type )
532
537
{
533
- char postfix [16 ] = {0 };
538
+ char postfix [16 ] = {0 }, prefix [ 16 ] = { 0 } ;
534
539
static const char * const str [] = {
535
540
[NOT_INIT ] = "?" ,
536
541
[SCALAR_VALUE ] = "inv" ,
@@ -550,8 +555,7 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
550
555
[PTR_TO_BTF_ID ] = "ptr_" ,
551
556
[PTR_TO_PERCPU_BTF_ID ] = "percpu_ptr_" ,
552
557
[PTR_TO_MEM ] = "mem" ,
553
- [PTR_TO_RDONLY_BUF ] = "rdonly_buf" ,
554
- [PTR_TO_RDWR_BUF ] = "rdwr_buf" ,
558
+ [PTR_TO_BUF ] = "buf" ,
555
559
[PTR_TO_FUNC ] = "func" ,
556
560
[PTR_TO_MAP_KEY ] = "map_key" ,
557
561
};
@@ -564,8 +568,11 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
564
568
strncpy (postfix , "_or_null" , 16 );
565
569
}
566
570
567
- snprintf (env -> type_str_buf , TYPE_STR_BUF_LEN , "%s%s" ,
568
- str [base_type (type )], postfix );
571
+ if (type & MEM_RDONLY )
572
+ strncpy (prefix , "rdonly_" , 16 );
573
+
574
+ snprintf (env -> type_str_buf , TYPE_STR_BUF_LEN , "%s%s%s" ,
575
+ prefix , str [base_type (type )], postfix );
569
576
return env -> type_str_buf ;
570
577
}
571
578
@@ -2755,8 +2762,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
2755
2762
case PTR_TO_TCP_SOCK :
2756
2763
case PTR_TO_XDP_SOCK :
2757
2764
case PTR_TO_BTF_ID :
2758
- case PTR_TO_RDONLY_BUF :
2759
- case PTR_TO_RDWR_BUF :
2765
+ case PTR_TO_BUF :
2760
2766
case PTR_TO_PERCPU_BTF_ID :
2761
2767
case PTR_TO_MEM :
2762
2768
case PTR_TO_FUNC :
@@ -4508,22 +4514,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
4508
4514
} else if (reg -> type == CONST_PTR_TO_MAP ) {
4509
4515
err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
4510
4516
value_regno );
4511
- } else if (reg -> type == PTR_TO_RDONLY_BUF ) {
4512
- if (t == BPF_WRITE ) {
4513
- verbose (env , "R%d cannot write into %s\n" ,
4514
- regno , reg_type_str (env , reg -> type ));
4515
- return - EACCES ;
4517
+ } else if (base_type (reg -> type ) == PTR_TO_BUF ) {
4518
+ bool rdonly_mem = type_is_rdonly_mem (reg -> type );
4519
+ const char * buf_info ;
4520
+ u32 * max_access ;
4521
+
4522
+ if (rdonly_mem ) {
4523
+ if (t == BPF_WRITE ) {
4524
+ verbose (env , "R%d cannot write into %s\n" ,
4525
+ regno , reg_type_str (env , reg -> type ));
4526
+ return - EACCES ;
4527
+ }
4528
+ buf_info = "rdonly" ;
4529
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4530
+ } else {
4531
+ buf_info = "rdwr" ;
4532
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4516
4533
}
4534
+
4517
4535
err = check_buffer_access (env , reg , regno , off , size , false,
4518
- "rdonly" ,
4519
- & env -> prog -> aux -> max_rdonly_access );
4520
- if (!err && value_regno >= 0 )
4521
- mark_reg_unknown (env , regs , value_regno );
4522
- } else if (reg -> type == PTR_TO_RDWR_BUF ) {
4523
- err = check_buffer_access (env , reg , regno , off , size , false,
4524
- "rdwr" ,
4525
- & env -> prog -> aux -> max_rdwr_access );
4526
- if (!err && t == BPF_READ && value_regno >= 0 )
4536
+ buf_info , max_access );
4537
+
4538
+ if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ ))
4527
4539
mark_reg_unknown (env , regs , value_regno );
4528
4540
} else {
4529
4541
verbose (env , "R%d invalid mem access '%s'\n" , regno ,
@@ -4771,8 +4783,10 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4771
4783
struct bpf_call_arg_meta * meta )
4772
4784
{
4773
4785
struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4786
+ const char * buf_info ;
4787
+ u32 * max_access ;
4774
4788
4775
- switch (reg -> type ) {
4789
+ switch (base_type ( reg -> type ) ) {
4776
4790
case PTR_TO_PACKET :
4777
4791
case PTR_TO_PACKET_META :
4778
4792
return check_packet_access (env , regno , reg -> off , access_size ,
@@ -4791,18 +4805,20 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
4791
4805
return check_mem_region_access (env , regno , reg -> off ,
4792
4806
access_size , reg -> mem_size ,
4793
4807
zero_size_allowed );
4794
- case PTR_TO_RDONLY_BUF :
4795
- if (meta && meta -> raw_mode )
4796
- return - EACCES ;
4797
- return check_buffer_access (env , reg , regno , reg -> off ,
4798
- access_size , zero_size_allowed ,
4799
- "rdonly" ,
4800
- & env -> prog -> aux -> max_rdonly_access );
4801
- case PTR_TO_RDWR_BUF :
4808
+ case PTR_TO_BUF :
4809
+ if (type_is_rdonly_mem (reg -> type )) {
4810
+ if (meta && meta -> raw_mode )
4811
+ return - EACCES ;
4812
+
4813
+ buf_info = "rdonly" ;
4814
+ max_access = & env -> prog -> aux -> max_rdonly_access ;
4815
+ } else {
4816
+ buf_info = "rdwr" ;
4817
+ max_access = & env -> prog -> aux -> max_rdwr_access ;
4818
+ }
4802
4819
return check_buffer_access (env , reg , regno , reg -> off ,
4803
4820
access_size , zero_size_allowed ,
4804
- "rdwr" ,
4805
- & env -> prog -> aux -> max_rdwr_access );
4821
+ buf_info , max_access );
4806
4822
case PTR_TO_STACK :
4807
4823
return check_stack_range_initialized (
4808
4824
env ,
@@ -5081,8 +5097,8 @@ static const struct bpf_reg_types mem_types = {
5081
5097
PTR_TO_MAP_KEY ,
5082
5098
PTR_TO_MAP_VALUE ,
5083
5099
PTR_TO_MEM ,
5084
- PTR_TO_RDONLY_BUF ,
5085
- PTR_TO_RDWR_BUF ,
5100
+ PTR_TO_BUF ,
5101
+ PTR_TO_BUF | MEM_RDONLY ,
5086
5102
},
5087
5103
};
5088
5104
0 commit comments