Two test cases for signed/unsigned 32-bit bounds refinement when s32 range crosses the sign boundary: - s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX], s32 range tail before sign boundary overlaps with u32 range. - s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3], s32 range head after the sign boundary overlaps with u32 range. This covers both branches added in the __reg32_deduce_bounds(). Also, crossing_32_bit_signed_boundary_2() no longer triggers invariant violations.
Unified · Split
| @@ -1148,7 +1148,7 @@ l0_%=: r0 = 0; \ · 1147 unmodified lines | |||
| 1148 | SEC("xdp") | 1148 | SEC("xdp") |
| 1149 | __description("bound check with JMP32_JSLT for crossing 32-bit signed boundary") | 1149 | __description("bound check with JMP32_JSLT for crossing 32-bit signed boundary") |
| 1150 | __success __retval(0) | 1150 | __success __retval(0) |
| 1151 | __flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */ | 1151 | __flag(BPF_F_TEST_REG_INVARIANTS) |
| 1152 | __naked void crossing_32_bit_signed_boundary_2(void) | 1152 | __naked void crossing_32_bit_signed_boundary_2(void) |
| 1153 | { | 1153 | { |
| 1154 | asm volatile (" \ | 1154 | asm volatile (" \ |
| @@ -2000,4 +2000,41 @@ __naked void bounds_refinement_multiple_overlaps(void *ctx) · 845 unmodified lines | |||
| 2000 | : __clobber_all); | 2000 | : __clobber_all); |
| 2001 | } | 2001 | } |
| 2002 | 2002 | ||
| 2003 | SEC("socket") | ||
| 2004 | __success | ||
| 2005 | __flag(BPF_F_TEST_REG_INVARIANTS) | ||
| 2006 | __naked void signed_unsigned_intersection32_case1(void *ctx) | ||
| 2007 | { | ||
| 2008 | asm volatile(" \ | ||
| 2009 | call %[bpf_get_prandom_u32]; \ | ||
| 2010 | w0 &= 0xffffffff; \ | ||
| 2011 | if w0 < 0x3 goto 1f; /* on fall-through u32 range [3..U32_MAX] */ \ | ||
| 2012 | if w0 s> 0x1 goto 1f; /* on fall-through s32 range [S32_MIN..1] */ \ | ||
| 2013 | if w0 s< 0x0 goto 1f; /* range can be narrowed to [S32_MIN..-1] */ \ | ||
| 2014 | r10 = 0; /* thus predicting the jump. */ \ | ||
| 2015 | 1: exit; \ | ||
| 2016 | " : | ||
| 2017 | : __imm(bpf_get_prandom_u32) | ||
| 2018 | : __clobber_all); | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | SEC("socket") | ||
| 2022 | __success | ||
| 2023 | __flag(BPF_F_TEST_REG_INVARIANTS) | ||
| 2024 | __naked void signed_unsigned_intersection32_case2(void *ctx) | ||
| 2025 | { | ||
| 2026 | asm volatile(" \ | ||
| 2027 | call %[bpf_get_prandom_u32]; \ | ||
| 2028 | w0 &= 0xffffffff; \ | ||
| 2029 | if w0 > 0x80000003 goto 1f; /* on fall-through u32 range [0..S32_MIN+3] */ \ | ||
| 2030 | if w0 s< -3 goto 1f; /* on fall-through s32 range [-3..S32_MAX] */ \ | ||
| 2031 | if w0 s> 5 goto 1f; /* on fall-through s32 range [-3..5] */ \ | ||
| 2032 | if w0 <= 5 goto 1f; /* range can be narrowed to [0..5] */ \ | ||
| 2033 | r10 = 0; /* thus predicting the jump */ \ | ||
| 2034 | 1: exit; \ | ||
| 2035 | " : | ||
| 2036 | : __imm(bpf_get_prandom_u32) | ||
| 2037 | : __clobber_all); | ||
| 2038 | } | ||
| 2039 | |||
| 2003 | char _license[] SEC("license") = "GPL"; | 2040 | char _license[] SEC("license") = "GPL"; |