@@ -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
@@ -2489,8 +2496,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
24892496 case PTR_TO_TCP_SOCK :
24902497 case PTR_TO_XDP_SOCK :
24912498 case PTR_TO_BTF_ID :
2492- case PTR_TO_RDONLY_BUF :
2493- case PTR_TO_RDWR_BUF :
2499+ case PTR_TO_BUF :
24942500 case PTR_TO_PERCPU_BTF_ID :
24952501 case PTR_TO_MEM :
24962502 case PTR_TO_FUNC :
@@ -4185,22 +4191,28 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
41854191 } else if (reg -> type == CONST_PTR_TO_MAP ) {
41864192 err = check_ptr_to_map_access (env , regs , regno , off , size , t ,
41874193 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 ;
41934210 }
4211+
41944212 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 ))
42044216 mark_reg_unknown (env , regs , value_regno );
42054217 } else {
42064218 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,
44484460 struct bpf_call_arg_meta * meta )
44494461{
44504462 struct bpf_reg_state * regs = cur_regs (env ), * reg = & regs [regno ];
4463+ const char * buf_info ;
4464+ u32 * max_access ;
44514465
4452- switch (reg -> type ) {
4466+ switch (base_type ( reg -> type ) ) {
44534467 case PTR_TO_PACKET :
44544468 case PTR_TO_PACKET_META :
44554469 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,
44684482 return check_mem_region_access (env , regno , reg -> off ,
44694483 access_size , reg -> mem_size ,
44704484 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+ }
44794496 return check_buffer_access (env , reg , regno , reg -> off ,
44804497 access_size , zero_size_allowed ,
4481- "rdwr" ,
4482- & env -> prog -> aux -> max_rdwr_access );
4498+ buf_info , max_access );
44834499 case PTR_TO_STACK :
44844500 return check_stack_range_initialized (
44854501 env ,
@@ -4707,8 +4723,8 @@ static const struct bpf_reg_types mem_types = {
47074723 PTR_TO_MAP_KEY ,
47084724 PTR_TO_MAP_VALUE ,
47094725 PTR_TO_MEM ,
4710- PTR_TO_RDONLY_BUF ,
4711- PTR_TO_RDWR_BUF ,
4726+ PTR_TO_BUF ,
4727+ PTR_TO_BUF | MEM_RDONLY ,
47124728 },
47134729};
47144730
0 commit comments