bpf: Fix propagation of 32-bit signed bounds from 64-bit bounds.
The 64-bit signed bounds should not affect 32-bit signed bounds unless the
verifier knows that upper 32-bits are either all 1s or all 0s. For example the
register with smin_value==1 doesn't mean that s32_min_value is also equal to 1,
since smax_value could be larger than 32-bit subregister can hold.
The verifier refines the smax/s32_max return value from certain helpers in
do_refine_retval_range(). Teach the verifier to recognize that smin/s32_min
value is also bounded. When both smin and smax bounds fit into 32-bit
subregister the verifier can propagate those bounds.
Fixes: 3f50f132d8 ("bpf: Verifier, do explicit ALU32 bounds tracking")
Reported-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									4e083fdfa3
								
							
						
					
					
						commit
						b02709587e
					
				| @ -1298,9 +1298,7 @@ static void __reg_combine_32_into_64(struct bpf_reg_state *reg) | ||||
| 
 | ||||
| static bool __reg64_bound_s32(s64 a) | ||||
| { | ||||
| 	if (a > S32_MIN && a < S32_MAX) | ||||
| 		return true; | ||||
| 	return false; | ||||
| 	return a > S32_MIN && a < S32_MAX; | ||||
| } | ||||
| 
 | ||||
| static bool __reg64_bound_u32(u64 a) | ||||
| @ -1314,10 +1312,10 @@ static void __reg_combine_64_into_32(struct bpf_reg_state *reg) | ||||
| { | ||||
| 	__mark_reg32_unbounded(reg); | ||||
| 
 | ||||
| 	if (__reg64_bound_s32(reg->smin_value)) | ||||
| 	if (__reg64_bound_s32(reg->smin_value) && __reg64_bound_s32(reg->smax_value)) { | ||||
| 		reg->s32_min_value = (s32)reg->smin_value; | ||||
| 	if (__reg64_bound_s32(reg->smax_value)) | ||||
| 		reg->s32_max_value = (s32)reg->smax_value; | ||||
| 	} | ||||
| 	if (__reg64_bound_u32(reg->umin_value)) | ||||
| 		reg->u32_min_value = (u32)reg->umin_value; | ||||
| 	if (__reg64_bound_u32(reg->umax_value)) | ||||
| @ -4895,6 +4893,8 @@ static void do_refine_retval_range(struct bpf_reg_state *regs, int ret_type, | ||||
| 
 | ||||
| 	ret_reg->smax_value = meta->msize_max_value; | ||||
| 	ret_reg->s32_max_value = meta->msize_max_value; | ||||
| 	ret_reg->smin_value = -MAX_ERRNO; | ||||
| 	ret_reg->s32_min_value = -MAX_ERRNO; | ||||
| 	__reg_deduce_bounds(ret_reg); | ||||
| 	__reg_bound_offset(ret_reg); | ||||
| 	__update_reg_bounds(ret_reg); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user