@@ -455,6 +455,11 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
455455 base_type (type ) == PTR_TO_MEM ;
456456}
457457
458+ static bool type_is_rdonly_mem (u32 type )
459+ {
460+ return type & MEM_RDONLY ;
461+ }
462+
458463static bool arg_type_may_be_refcounted (enum bpf_arg_type type )
459464{
460465 return type == ARG_PTR_TO_SOCK_COMMON ;
@@ -530,7 +535,7 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
530535static const char * reg_type_str (struct bpf_verifier_env * env ,
531536 enum bpf_reg_type type )
532537{
533- char postfix [16 ] = {0 };
538+ char postfix [16 ] = {0 }, prefix [ 16 ] = { 0 } ;
534539 static const char * const str [] = {
535540 [NOT_INIT ] = "?" ,
536541 [SCALAR_VALUE ] = "inv" ,
@@ -550,8 +555,7 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
550555 [PTR_TO_BTF_ID ] = "ptr_" ,
551556 [PTR_TO_PERCPU_BTF_ID ] = "percpu_ptr_" ,
552557 [PTR_TO_MEM ] = "mem" ,
553- [PTR_TO_RDONLY_BUF ] = "rdonly_buf" ,
554- [PTR_TO_RDWR_BUF ] = "rdwr_buf" ,
558+ [PTR_TO_BUF ] = "buf" ,
555559 [PTR_TO_FUNC ] = "func" ,
556560 [PTR_TO_MAP_KEY ] = "map_key" ,
557561 };
@@ -564,8 +568,11 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
564568 strncpy (postfix , "_or_null" , 16 );
565569 }
566570
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 );
569576 return env -> type_str_buf ;
570577}
571578
@@ -2755,8 +2762,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
27552762 case PTR_TO_TCP_SOCK :
27562763 case PTR_TO_XDP_SOCK :
27572764 case PTR_TO_BTF_ID :
2758- case PTR_TO_RDONLY_BUF :
2759- case PTR_TO_RDWR_BUF :
2765+ case PTR_TO_BUF :
27602766 case PTR_TO_PERCPU_BTF_ID :
27612767 case PTR_TO_MEM :
27622768 case PTR_TO_FUNC :
@@ -4508,22 +4514,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
45084514 } else if (reg -> type == CONST_PTR_TO_MAP ) {
45094515 err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
45104516 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 ;
45164533 }
4534+
45174535 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 ))
45274539 mark_reg_unknown (env , regs , value_regno );
45284540 } else {
45294541 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,
47714783 struct bpf_call_arg_meta * meta )
47724784{
47734785 struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4786+ const char * buf_info ;
4787+ u32 * max_access ;
47744788
4775- switch (reg -> type ) {
4789+ switch (base_type ( reg -> type ) ) {
47764790 case PTR_TO_PACKET :
47774791 case PTR_TO_PACKET_META :
47784792 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,
47914805 return check_mem_region_access (env , regno , reg -> off ,
47924806 access_size , reg -> mem_size ,
47934807 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+ }
48024819 return check_buffer_access (env , reg , regno , reg -> off ,
48034820 access_size , zero_size_allowed ,
4804- "rdwr" ,
4805- & env -> prog -> aux -> max_rdwr_access );
4821+ buf_info , max_access );
48064822 case PTR_TO_STACK :
48074823 return check_stack_range_initialized (
48084824 env ,
@@ -5081,8 +5097,8 @@ static const struct bpf_reg_types mem_types = {
50815097 PTR_TO_MAP_KEY ,
50825098 PTR_TO_MAP_VALUE ,
50835099 PTR_TO_MEM ,
5084- PTR_TO_RDONLY_BUF ,
5085- PTR_TO_RDWR_BUF ,
5100+ PTR_TO_BUF ,
5101+ PTR_TO_BUF | MEM_RDONLY ,
50865102 },
50875103};
50885104
0 commit comments