@@ -459,6 +459,11 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
459459 base_type (type ) == PTR_TO_MEM ;
460460}
461461
462+ static bool type_is_rdonly_mem (u32 type )
463+ {
464+ return type & MEM_RDONLY ;
465+ }
466+
462467static bool arg_type_may_be_refcounted (enum bpf_arg_type type )
463468{
464469 return type == ARG_PTR_TO_SOCK_COMMON ;
@@ -534,7 +539,7 @@ static bool is_cmpxchg_insn(const struct bpf_insn *insn)
534539static const char * reg_type_str (struct bpf_verifier_env * env ,
535540 enum bpf_reg_type type )
536541{
537- char postfix [16 ] = {0 };
542+ char postfix [16 ] = {0 }, prefix [ 16 ] = { 0 } ;
538543 static const char * const str [] = {
539544 [NOT_INIT ] = "?" ,
540545 [SCALAR_VALUE ] = "inv" ,
@@ -554,8 +559,7 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
554559 [PTR_TO_BTF_ID ] = "ptr_" ,
555560 [PTR_TO_PERCPU_BTF_ID ] = "percpu_ptr_" ,
556561 [PTR_TO_MEM ] = "mem" ,
557- [PTR_TO_RDONLY_BUF ] = "rdonly_buf" ,
558- [PTR_TO_RDWR_BUF ] = "rdwr_buf" ,
562+ [PTR_TO_BUF ] = "buf" ,
559563 [PTR_TO_FUNC ] = "func" ,
560564 [PTR_TO_MAP_KEY ] = "map_key" ,
561565 };
@@ -568,8 +572,11 @@ static const char *reg_type_str(struct bpf_verifier_env *env,
568572 strncpy (postfix , "_or_null" , 16 );
569573 }
570574
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 );
573580 return env -> type_str_buf ;
574581}
575582
@@ -2493,8 +2500,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
24932500 case PTR_TO_TCP_SOCK :
24942501 case PTR_TO_XDP_SOCK :
24952502 case PTR_TO_BTF_ID :
2496- case PTR_TO_RDONLY_BUF :
2497- case PTR_TO_RDWR_BUF :
2503+ case PTR_TO_BUF :
24982504 case PTR_TO_PERCPU_BTF_ID :
24992505 case PTR_TO_MEM :
25002506 case PTR_TO_FUNC :
@@ -4187,22 +4193,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
41874193 } else if (reg -> type == CONST_PTR_TO_MAP ) {
41884194 err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
41894195 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 ;
41954212 }
4213+
41964214 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 ))
42064218 mark_reg_unknown (env , regs , value_regno );
42074219 } else {
42084220 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,
44504462 struct bpf_call_arg_meta * meta )
44514463{
44524464 struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4465+ const char * buf_info ;
4466+ u32 * max_access ;
44534467
4454- switch (reg -> type ) {
4468+ switch (base_type ( reg -> type ) ) {
44554469 case PTR_TO_PACKET :
44564470 case PTR_TO_PACKET_META :
44574471 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,
44704484 return check_mem_region_access (env , regno , reg -> off ,
44714485 access_size , reg -> mem_size ,
44724486 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+ }
44814498 return check_buffer_access (env , reg , regno , reg -> off ,
44824499 access_size , zero_size_allowed ,
4483- "rdwr" ,
4484- & env -> prog -> aux -> max_rdwr_access );
4500+ buf_info , max_access );
44854501 case PTR_TO_STACK :
44864502 return check_stack_range_initialized (
44874503 env ,
@@ -4709,8 +4725,8 @@ static const struct bpf_reg_types mem_types = {
47094725 PTR_TO_MAP_KEY ,
47104726 PTR_TO_MAP_VALUE ,
47114727 PTR_TO_MEM ,
4712- PTR_TO_RDONLY_BUF ,
4713- PTR_TO_RDWR_BUF ,
4728+ PTR_TO_BUF ,
4729+ PTR_TO_BUF | MEM_RDONLY ,
47144730 },
47154731};
47164732
0 commit comments