Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bpf-add-range-tracking-for-bpf_div-and-bpf_mod'

Yazhou Tang says:

====================
bpf: Add range tracking for BPF_DIV and BPF_MOD

From: Yazhou Tang <tangyazhou518@outlook.com>

Add range tracking (interval analysis) for BPF_DIV and BPF_MOD when
divisor is constant. Please see commit log of 1/2 for more details.

Changes v4 => v5:
1. Rename helper functions `__reset_reg(32|64)_and_tnum` to
`reset_reg(32|64)_and_tnum`. (Alexei)
2. Replace plain C division with `div64_u64` and `div64_s64` for 64-bit
operations, ensuring compatibility with 32-bit architectures. (Alexei
& kernel test robot)
3. Fixup an indent typo in selftest file `verifier_div_mod_bounds.c`.

v4: https://lore.kernel.org/bpf/20260116103246.2477635-1-tangyazhou@zju.edu.cn/

Changes v3 => v4:
1. Remove verbose helper functions for "division by zero" handling. (Alexei)
2. Put all "reset" logic in one place for clarity, and add 2 helper
function `__reset_reg64_and_tnum` and `__reset_reg32_and_tnum` to
reduce code duplication. (Alexei)
3. Update all multi-line comments to follow the standard kernel style. (Alexei)
4. Add new test cases to cover strictly positive and strictly negative
divisor scenarios in SDIV and SMOD analysis. (Alexei)
5. Fixup a typo in SDIV analysis functions.

v3: https://lore.kernel.org/bpf/20260113103552.3435695-1-tangyazhou@zju.edu.cn/

Changes v2 => v3:
1. Fixup a bug in `adjust_scalar_min_max_vals` function that lead to
incorrect range results. (Syzbot)
2. Remove tnum analysis logic. (Alexei)
3. Only handle "constant divisor" case. (Alexei)
4. Add BPF_MOD range analysis logic.
5. Update selftests accordingly.
6. Add detailed code comments and improve commit messages. (Yonghong)

v2: https://lore.kernel.org/bpf/20251223091120.2413435-1-tangyazhou@zju.edu.cn/

Changes v1 => v2:
1. Fixed 2 bugs in sdiv32 analysis logic and corrected the associated
selftest cases. (AI reviewer)
2. Renamed `tnum_bottom` to `tnum_empty` for better clarity, and updated
commit message to explain its role in signed BPF_DIV analysis.

v1:
https://lore.kernel.org/bpf/tencent_717092CD734D050CCD93401CA624BB3C8307@qq.com/
https://lore.kernel.org/bpf/tencent_7C98FAECA40C98489ACF4515CE346F031509@qq.com/
====================

Link: https://patch.msgid.link/20260119085458.182221-1-tangyazhou@zju.edu.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+1456 -5
+299
kernel/bpf/verifier.c
··· 2349 2349 reg->u32_max_value = U32_MAX; 2350 2350 } 2351 2351 2352 + static void reset_reg64_and_tnum(struct bpf_reg_state *reg) 2353 + { 2354 + __mark_reg64_unbounded(reg); 2355 + reg->var_off = tnum_unknown; 2356 + } 2357 + 2358 + static void reset_reg32_and_tnum(struct bpf_reg_state *reg) 2359 + { 2360 + __mark_reg32_unbounded(reg); 2361 + reg->var_off = tnum_unknown; 2362 + } 2363 + 2352 2364 static void __update_reg32_bounds(struct bpf_reg_state *reg) 2353 2365 { 2354 2366 struct tnum var32_off = tnum_subreg(reg->var_off); ··· 15171 15159 } 15172 15160 } 15173 15161 15162 + static void scalar32_min_max_udiv(struct bpf_reg_state *dst_reg, 15163 + struct bpf_reg_state *src_reg) 15164 + { 15165 + u32 *dst_umin = &dst_reg->u32_min_value; 15166 + u32 *dst_umax = &dst_reg->u32_max_value; 15167 + u32 src_val = src_reg->u32_min_value; /* non-zero, const divisor */ 15168 + 15169 + *dst_umin = *dst_umin / src_val; 15170 + *dst_umax = *dst_umax / src_val; 15171 + 15172 + /* Reset other ranges/tnum to unbounded/unknown. */ 15173 + dst_reg->s32_min_value = S32_MIN; 15174 + dst_reg->s32_max_value = S32_MAX; 15175 + reset_reg64_and_tnum(dst_reg); 15176 + } 15177 + 15178 + static void scalar_min_max_udiv(struct bpf_reg_state *dst_reg, 15179 + struct bpf_reg_state *src_reg) 15180 + { 15181 + u64 *dst_umin = &dst_reg->umin_value; 15182 + u64 *dst_umax = &dst_reg->umax_value; 15183 + u64 src_val = src_reg->umin_value; /* non-zero, const divisor */ 15184 + 15185 + *dst_umin = div64_u64(*dst_umin, src_val); 15186 + *dst_umax = div64_u64(*dst_umax, src_val); 15187 + 15188 + /* Reset other ranges/tnum to unbounded/unknown. */ 15189 + dst_reg->smin_value = S64_MIN; 15190 + dst_reg->smax_value = S64_MAX; 15191 + reset_reg32_and_tnum(dst_reg); 15192 + } 15193 + 15194 + static void scalar32_min_max_sdiv(struct bpf_reg_state *dst_reg, 15195 + struct bpf_reg_state *src_reg) 15196 + { 15197 + s32 *dst_smin = &dst_reg->s32_min_value; 15198 + s32 *dst_smax = &dst_reg->s32_max_value; 15199 + s32 src_val = src_reg->s32_min_value; /* non-zero, const divisor */ 15200 + s32 res1, res2; 15201 + 15202 + /* BPF div specification: S32_MIN / -1 = S32_MIN */ 15203 + if (*dst_smin == S32_MIN && src_val == -1) { 15204 + /* 15205 + * If the dividend range contains more than just S32_MIN, 15206 + * we cannot precisely track the result, so it becomes unbounded. 15207 + * e.g., [S32_MIN, S32_MIN+10]/(-1), 15208 + * = {S32_MIN} U [-(S32_MIN+10), -(S32_MIN+1)] 15209 + * = {S32_MIN} U [S32_MAX-9, S32_MAX] = [S32_MIN, S32_MAX] 15210 + * Otherwise (if dividend is exactly S32_MIN), result remains S32_MIN. 15211 + */ 15212 + if (*dst_smax != S32_MIN) { 15213 + *dst_smin = S32_MIN; 15214 + *dst_smax = S32_MAX; 15215 + } 15216 + goto reset; 15217 + } 15218 + 15219 + res1 = *dst_smin / src_val; 15220 + res2 = *dst_smax / src_val; 15221 + *dst_smin = min(res1, res2); 15222 + *dst_smax = max(res1, res2); 15223 + 15224 + reset: 15225 + /* Reset other ranges/tnum to unbounded/unknown. */ 15226 + dst_reg->u32_min_value = 0; 15227 + dst_reg->u32_max_value = U32_MAX; 15228 + reset_reg64_and_tnum(dst_reg); 15229 + } 15230 + 15231 + static void scalar_min_max_sdiv(struct bpf_reg_state *dst_reg, 15232 + struct bpf_reg_state *src_reg) 15233 + { 15234 + s64 *dst_smin = &dst_reg->smin_value; 15235 + s64 *dst_smax = &dst_reg->smax_value; 15236 + s64 src_val = src_reg->smin_value; /* non-zero, const divisor */ 15237 + s64 res1, res2; 15238 + 15239 + /* BPF div specification: S64_MIN / -1 = S64_MIN */ 15240 + if (*dst_smin == S64_MIN && src_val == -1) { 15241 + /* 15242 + * If the dividend range contains more than just S64_MIN, 15243 + * we cannot precisely track the result, so it becomes unbounded. 15244 + * e.g., [S64_MIN, S64_MIN+10]/(-1), 15245 + * = {S64_MIN} U [-(S64_MIN+10), -(S64_MIN+1)] 15246 + * = {S64_MIN} U [S64_MAX-9, S64_MAX] = [S64_MIN, S64_MAX] 15247 + * Otherwise (if dividend is exactly S64_MIN), result remains S64_MIN. 15248 + */ 15249 + if (*dst_smax != S64_MIN) { 15250 + *dst_smin = S64_MIN; 15251 + *dst_smax = S64_MAX; 15252 + } 15253 + goto reset; 15254 + } 15255 + 15256 + res1 = div64_s64(*dst_smin, src_val); 15257 + res2 = div64_s64(*dst_smax, src_val); 15258 + *dst_smin = min(res1, res2); 15259 + *dst_smax = max(res1, res2); 15260 + 15261 + reset: 15262 + /* Reset other ranges/tnum to unbounded/unknown. */ 15263 + dst_reg->umin_value = 0; 15264 + dst_reg->umax_value = U64_MAX; 15265 + reset_reg32_and_tnum(dst_reg); 15266 + } 15267 + 15268 + static void scalar32_min_max_umod(struct bpf_reg_state *dst_reg, 15269 + struct bpf_reg_state *src_reg) 15270 + { 15271 + u32 *dst_umin = &dst_reg->u32_min_value; 15272 + u32 *dst_umax = &dst_reg->u32_max_value; 15273 + u32 src_val = src_reg->u32_min_value; /* non-zero, const divisor */ 15274 + u32 res_max = src_val - 1; 15275 + 15276 + /* 15277 + * If dst_umax <= res_max, the result remains unchanged. 15278 + * e.g., [2, 5] % 10 = [2, 5]. 15279 + */ 15280 + if (*dst_umax <= res_max) 15281 + return; 15282 + 15283 + *dst_umin = 0; 15284 + *dst_umax = min(*dst_umax, res_max); 15285 + 15286 + /* Reset other ranges/tnum to unbounded/unknown. */ 15287 + dst_reg->s32_min_value = S32_MIN; 15288 + dst_reg->s32_max_value = S32_MAX; 15289 + reset_reg64_and_tnum(dst_reg); 15290 + } 15291 + 15292 + static void scalar_min_max_umod(struct bpf_reg_state *dst_reg, 15293 + struct bpf_reg_state *src_reg) 15294 + { 15295 + u64 *dst_umin = &dst_reg->umin_value; 15296 + u64 *dst_umax = &dst_reg->umax_value; 15297 + u64 src_val = src_reg->umin_value; /* non-zero, const divisor */ 15298 + u64 res_max = src_val - 1; 15299 + 15300 + /* 15301 + * If dst_umax <= res_max, the result remains unchanged. 15302 + * e.g., [2, 5] % 10 = [2, 5]. 15303 + */ 15304 + if (*dst_umax <= res_max) 15305 + return; 15306 + 15307 + *dst_umin = 0; 15308 + *dst_umax = min(*dst_umax, res_max); 15309 + 15310 + /* Reset other ranges/tnum to unbounded/unknown. */ 15311 + dst_reg->smin_value = S64_MIN; 15312 + dst_reg->smax_value = S64_MAX; 15313 + reset_reg32_and_tnum(dst_reg); 15314 + } 15315 + 15316 + static void scalar32_min_max_smod(struct bpf_reg_state *dst_reg, 15317 + struct bpf_reg_state *src_reg) 15318 + { 15319 + s32 *dst_smin = &dst_reg->s32_min_value; 15320 + s32 *dst_smax = &dst_reg->s32_max_value; 15321 + s32 src_val = src_reg->s32_min_value; /* non-zero, const divisor */ 15322 + 15323 + /* 15324 + * Safe absolute value calculation: 15325 + * If src_val == S32_MIN (-2147483648), src_abs becomes 2147483648. 15326 + * Here use unsigned integer to avoid overflow. 15327 + */ 15328 + u32 src_abs = (src_val > 0) ? (u32)src_val : -(u32)src_val; 15329 + 15330 + /* 15331 + * Calculate the maximum possible absolute value of the result. 15332 + * Even if src_abs is 2147483648 (S32_MIN), subtracting 1 gives 15333 + * 2147483647 (S32_MAX), which fits perfectly in s32. 15334 + */ 15335 + s32 res_max_abs = src_abs - 1; 15336 + 15337 + /* 15338 + * If the dividend is already within the result range, 15339 + * the result remains unchanged. e.g., [-2, 5] % 10 = [-2, 5]. 15340 + */ 15341 + if (*dst_smin >= -res_max_abs && *dst_smax <= res_max_abs) 15342 + return; 15343 + 15344 + /* General case: result has the same sign as the dividend. */ 15345 + if (*dst_smin >= 0) { 15346 + *dst_smin = 0; 15347 + *dst_smax = min(*dst_smax, res_max_abs); 15348 + } else if (*dst_smax <= 0) { 15349 + *dst_smax = 0; 15350 + *dst_smin = max(*dst_smin, -res_max_abs); 15351 + } else { 15352 + *dst_smin = -res_max_abs; 15353 + *dst_smax = res_max_abs; 15354 + } 15355 + 15356 + /* Reset other ranges/tnum to unbounded/unknown. */ 15357 + dst_reg->u32_min_value = 0; 15358 + dst_reg->u32_max_value = U32_MAX; 15359 + reset_reg64_and_tnum(dst_reg); 15360 + } 15361 + 15362 + static void scalar_min_max_smod(struct bpf_reg_state *dst_reg, 15363 + struct bpf_reg_state *src_reg) 15364 + { 15365 + s64 *dst_smin = &dst_reg->smin_value; 15366 + s64 *dst_smax = &dst_reg->smax_value; 15367 + s64 src_val = src_reg->smin_value; /* non-zero, const divisor */ 15368 + 15369 + /* 15370 + * Safe absolute value calculation: 15371 + * If src_val == S64_MIN (-2^63), src_abs becomes 2^63. 15372 + * Here use unsigned integer to avoid overflow. 15373 + */ 15374 + u64 src_abs = (src_val > 0) ? (u64)src_val : -(u64)src_val; 15375 + 15376 + /* 15377 + * Calculate the maximum possible absolute value of the result. 15378 + * Even if src_abs is 2^63 (S64_MIN), subtracting 1 gives 15379 + * 2^63 - 1 (S64_MAX), which fits perfectly in s64. 15380 + */ 15381 + s64 res_max_abs = src_abs - 1; 15382 + 15383 + /* 15384 + * If the dividend is already within the result range, 15385 + * the result remains unchanged. e.g., [-2, 5] % 10 = [-2, 5]. 15386 + */ 15387 + if (*dst_smin >= -res_max_abs && *dst_smax <= res_max_abs) 15388 + return; 15389 + 15390 + /* General case: result has the same sign as the dividend. */ 15391 + if (*dst_smin >= 0) { 15392 + *dst_smin = 0; 15393 + *dst_smax = min(*dst_smax, res_max_abs); 15394 + } else if (*dst_smax <= 0) { 15395 + *dst_smax = 0; 15396 + *dst_smin = max(*dst_smin, -res_max_abs); 15397 + } else { 15398 + *dst_smin = -res_max_abs; 15399 + *dst_smax = res_max_abs; 15400 + } 15401 + 15402 + /* Reset other ranges/tnum to unbounded/unknown. */ 15403 + dst_reg->umin_value = 0; 15404 + dst_reg->umax_value = U64_MAX; 15405 + reset_reg32_and_tnum(dst_reg); 15406 + } 15407 + 15174 15408 static void scalar32_min_max_and(struct bpf_reg_state *dst_reg, 15175 15409 struct bpf_reg_state *src_reg) 15176 15410 { ··· 15822 15564 case BPF_MUL: 15823 15565 return true; 15824 15566 15567 + /* 15568 + * Division and modulo operators range is only safe to compute when the 15569 + * divisor is a constant. 15570 + */ 15571 + case BPF_DIV: 15572 + case BPF_MOD: 15573 + return src_is_const; 15574 + 15825 15575 /* Shift operators range is only computable if shift dimension operand 15826 15576 * is a constant. Shifts greater than 31 or 63 are undefined. This 15827 15577 * includes shifts by a negative number. ··· 15882 15616 struct bpf_reg_state src_reg) 15883 15617 { 15884 15618 u8 opcode = BPF_OP(insn->code); 15619 + s16 off = insn->off; 15885 15620 bool alu32 = (BPF_CLASS(insn->code) != BPF_ALU64); 15886 15621 int ret; 15887 15622 ··· 15933 15666 dst_reg->var_off = tnum_mul(dst_reg->var_off, src_reg.var_off); 15934 15667 scalar32_min_max_mul(dst_reg, &src_reg); 15935 15668 scalar_min_max_mul(dst_reg, &src_reg); 15669 + break; 15670 + case BPF_DIV: 15671 + /* BPF div specification: x / 0 = 0 */ 15672 + if ((alu32 && src_reg.u32_min_value == 0) || (!alu32 && src_reg.umin_value == 0)) { 15673 + ___mark_reg_known(dst_reg, 0); 15674 + break; 15675 + } 15676 + if (alu32) 15677 + if (off == 1) 15678 + scalar32_min_max_sdiv(dst_reg, &src_reg); 15679 + else 15680 + scalar32_min_max_udiv(dst_reg, &src_reg); 15681 + else 15682 + if (off == 1) 15683 + scalar_min_max_sdiv(dst_reg, &src_reg); 15684 + else 15685 + scalar_min_max_udiv(dst_reg, &src_reg); 15686 + break; 15687 + case BPF_MOD: 15688 + /* BPF mod specification: x % 0 = x */ 15689 + if ((alu32 && src_reg.u32_min_value == 0) || (!alu32 && src_reg.umin_value == 0)) 15690 + break; 15691 + if (alu32) 15692 + if (off == 1) 15693 + scalar32_min_max_smod(dst_reg, &src_reg); 15694 + else 15695 + scalar32_min_max_umod(dst_reg, &src_reg); 15696 + else 15697 + if (off == 1) 15698 + scalar_min_max_smod(dst_reg, &src_reg); 15699 + else 15700 + scalar_min_max_umod(dst_reg, &src_reg); 15936 15701 break; 15937 15702 case BPF_AND: 15938 15703 if (tnum_is_const(src_reg.var_off)) {
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 33 33 #include "verifier_direct_packet_access.skel.h" 34 34 #include "verifier_direct_stack_access_wraparound.skel.h" 35 35 #include "verifier_div0.skel.h" 36 + #include "verifier_div_mod_bounds.skel.h" 36 37 #include "verifier_div_overflow.skel.h" 37 38 #include "verifier_global_subprogs.skel.h" 38 39 #include "verifier_global_ptr_args.skel.h" ··· 176 175 void test_verifier_direct_packet_access(void) { RUN(verifier_direct_packet_access); } 177 176 void test_verifier_direct_stack_access_wraparound(void) { RUN(verifier_direct_stack_access_wraparound); } 178 177 void test_verifier_div0(void) { RUN(verifier_div0); } 178 + void test_verifier_div_mod_bounds(void) { RUN(verifier_div_mod_bounds); } 179 179 void test_verifier_div_overflow(void) { RUN(verifier_div_overflow); } 180 180 void test_verifier_global_subprogs(void) { RUN(verifier_global_subprogs); } 181 181 void test_verifier_global_ptr_args(void) { RUN(verifier_global_ptr_args); }
+1149
tools/testing/selftests/bpf/progs/verifier_div_mod_bounds.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bpf.h> 4 + #include <limits.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 7 + 8 + /* This file contains unit tests for signed/unsigned division and modulo 9 + * operations (with divisor as a constant), focusing on verifying whether 10 + * BPF verifier's range tracking module soundly and precisely computes 11 + * the results. 12 + */ 13 + 14 + SEC("socket") 15 + __description("UDIV32, positive divisor") 16 + __success __retval(0) __log_level(2) 17 + __msg("w1 /= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=3,var_off=(0x0; 0x3))") 18 + __naked void udiv32_pos_divisor(void) 19 + { 20 + asm volatile (" \ 21 + call %[bpf_get_prandom_u32]; \ 22 + w1 = w0; \ 23 + w1 &= 8; \ 24 + w1 |= 1; \ 25 + w1 /= 3; \ 26 + if w1 > 3 goto l0_%=; \ 27 + r0 = 0; \ 28 + exit; \ 29 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 30 + exit; \ 31 + " : 32 + : __imm(bpf_get_prandom_u32) 33 + : __clobber_all); 34 + } 35 + 36 + SEC("socket") 37 + __description("UDIV32, zero divisor") 38 + __success __retval(0) __log_level(2) 39 + __msg("w1 /= w2 {{.*}}; R1=0 R2=0") 40 + __naked void udiv32_zero_divisor(void) 41 + { 42 + asm volatile (" \ 43 + call %[bpf_get_prandom_u32]; \ 44 + w1 = w0; \ 45 + w1 &= 8; \ 46 + w1 |= 1; \ 47 + w2 = 0; \ 48 + w1 /= w2; \ 49 + if w1 != 0 goto l0_%=; \ 50 + r0 = 0; \ 51 + exit; \ 52 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 53 + exit; \ 54 + " : 55 + : __imm(bpf_get_prandom_u32) 56 + : __clobber_all); 57 + } 58 + 59 + SEC("socket") 60 + __description("UDIV64, positive divisor") 61 + __success __retval(0) __log_level(2) 62 + __msg("r1 /= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=3,var_off=(0x0; 0x3))") 63 + __naked void udiv64_pos_divisor(void) 64 + { 65 + asm volatile (" \ 66 + call %[bpf_get_prandom_u32]; \ 67 + r1 = r0; \ 68 + r1 &= 8; \ 69 + r1 |= 1; \ 70 + r1 /= 3; \ 71 + if r1 > 3 goto l0_%=; \ 72 + r0 = 0; \ 73 + exit; \ 74 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 75 + exit; \ 76 + " : 77 + : __imm(bpf_get_prandom_u32) 78 + : __clobber_all); 79 + } 80 + 81 + SEC("socket") 82 + __description("UDIV64, zero divisor") 83 + __success __retval(0) __log_level(2) 84 + __msg("r1 /= r2 {{.*}}; R1=0 R2=0") 85 + __naked void udiv64_zero_divisor(void) 86 + { 87 + asm volatile (" \ 88 + call %[bpf_get_prandom_u32]; \ 89 + r1 = r0; \ 90 + r1 &= 8; \ 91 + r1 |= 1; \ 92 + r2 = 0; \ 93 + r1 /= r2; \ 94 + if r1 != 0 goto l0_%=; \ 95 + r0 = 0; \ 96 + exit; \ 97 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 98 + exit; \ 99 + " : 100 + : __imm(bpf_get_prandom_u32) 101 + : __clobber_all); 102 + } 103 + 104 + SEC("socket") 105 + __description("SDIV32, positive divisor, positive dividend") 106 + __success __retval(0) __log_level(2) 107 + __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") 108 + __naked void sdiv32_pos_divisor_1(void) 109 + { 110 + asm volatile (" \ 111 + call %[bpf_get_prandom_u32]; \ 112 + w1 = w0; \ 113 + if w1 s< 8 goto l0_%=; \ 114 + if w1 s> 10 goto l0_%=; \ 115 + w1 s/= 3; \ 116 + if w1 s< 2 goto l1_%=; \ 117 + if w1 s> 3 goto l1_%=; \ 118 + l0_%=: r0 = 0; \ 119 + exit; \ 120 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 121 + exit; \ 122 + " : 123 + : __imm(bpf_get_prandom_u32) 124 + : __clobber_all); 125 + } 126 + 127 + SEC("socket") 128 + __description("SDIV32, positive divisor, negative dividend") 129 + __success __retval(0) __log_level(2) 130 + __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=umin=umin32=0xfffffffd,smax=umax=umax32=0xfffffffe,smin32=-3,smax32=-2,var_off=(0xfffffffc; 0x3))") 131 + __naked void sdiv32_pos_divisor_2(void) 132 + { 133 + asm volatile (" \ 134 + call %[bpf_get_prandom_u32]; \ 135 + w1 = w0; \ 136 + if w1 s> -8 goto l0_%=; \ 137 + if w1 s< -10 goto l0_%=; \ 138 + w1 s/= 3; \ 139 + if w1 s< -3 goto l1_%=; \ 140 + if w1 s> -2 goto l1_%=; \ 141 + l0_%=: r0 = 0; \ 142 + exit; \ 143 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 144 + exit; \ 145 + " : 146 + : __imm(bpf_get_prandom_u32) 147 + : __clobber_all); 148 + } 149 + 150 + SEC("socket") 151 + __description("SDIV32, positive divisor, mixed sign dividend") 152 + __success __retval(0) __log_level(2) 153 + __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=3,var_off=(0x0; 0xffffffff))") 154 + __naked void sdiv32_pos_divisor_3(void) 155 + { 156 + asm volatile (" \ 157 + call %[bpf_get_prandom_u32]; \ 158 + w1 = w0; \ 159 + if w1 s< -8 goto l0_%=; \ 160 + if w1 s> 10 goto l0_%=; \ 161 + w1 s/= 3; \ 162 + if w1 s< -2 goto l1_%=; \ 163 + if w1 s> 3 goto l1_%=; \ 164 + l0_%=: r0 = 0; \ 165 + exit; \ 166 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 167 + exit; \ 168 + " : 169 + : __imm(bpf_get_prandom_u32) 170 + : __clobber_all); 171 + } 172 + 173 + SEC("socket") 174 + __description("SDIV32, negative divisor, positive dividend") 175 + __success __retval(0) __log_level(2) 176 + __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=umin=umin32=0xfffffffd,smax=umax=umax32=0xfffffffe,smin32=-3,smax32=-2,var_off=(0xfffffffc; 0x3))") 177 + __naked void sdiv32_neg_divisor_1(void) 178 + { 179 + asm volatile (" \ 180 + call %[bpf_get_prandom_u32]; \ 181 + w1 = w0; \ 182 + if w1 s< 8 goto l0_%=; \ 183 + if w1 s> 10 goto l0_%=; \ 184 + w1 s/= -3; \ 185 + if w1 s< -3 goto l1_%=; \ 186 + if w1 s> -2 goto l1_%=; \ 187 + l0_%=: r0 = 0; \ 188 + exit; \ 189 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 190 + exit; \ 191 + " : 192 + : __imm(bpf_get_prandom_u32) 193 + : __clobber_all); 194 + } 195 + 196 + SEC("socket") 197 + __description("SDIV32, negative divisor, positive dividend") 198 + __success __retval(0) __log_level(2) 199 + __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") 200 + __naked void sdiv32_neg_divisor_2(void) 201 + { 202 + asm volatile (" \ 203 + call %[bpf_get_prandom_u32]; \ 204 + w1 = w0; \ 205 + if w1 s> -8 goto l0_%=; \ 206 + if w1 s< -10 goto l0_%=; \ 207 + w1 s/= -3; \ 208 + if w1 s< 2 goto l1_%=; \ 209 + if w1 s> 3 goto l1_%=; \ 210 + l0_%=: r0 = 0; \ 211 + exit; \ 212 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 213 + exit; \ 214 + " : 215 + : __imm(bpf_get_prandom_u32) 216 + : __clobber_all); 217 + } 218 + 219 + SEC("socket") 220 + __description("SDIV32, negative divisor, mixed sign dividend") 221 + __success __retval(0) __log_level(2) 222 + __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-3,smax32=2,var_off=(0x0; 0xffffffff))") 223 + __naked void sdiv32_neg_divisor_3(void) 224 + { 225 + asm volatile (" \ 226 + call %[bpf_get_prandom_u32]; \ 227 + w1 = w0; \ 228 + if w1 s< -8 goto l0_%=; \ 229 + if w1 s> 10 goto l0_%=; \ 230 + w1 s/= -3; \ 231 + if w1 s< -3 goto l1_%=; \ 232 + if w1 s> 2 goto l1_%=; \ 233 + l0_%=: r0 = 0; \ 234 + exit; \ 235 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 236 + exit; \ 237 + " : 238 + : __imm(bpf_get_prandom_u32) 239 + : __clobber_all); 240 + } 241 + 242 + SEC("socket") 243 + __description("SDIV32, zero divisor") 244 + __success __retval(0) __log_level(2) 245 + __msg("w1 s/= w2 {{.*}}; R1=0 R2=0") 246 + __naked void sdiv32_zero_divisor(void) 247 + { 248 + asm volatile (" \ 249 + call %[bpf_get_prandom_u32]; \ 250 + w1 = w0; \ 251 + w1 &= 8; \ 252 + w1 |= 1; \ 253 + w2 = 0; \ 254 + w1 s/= w2; \ 255 + if w1 != 0 goto l0_%=; \ 256 + r0 = 0; \ 257 + exit; \ 258 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 259 + exit; \ 260 + " : 261 + : __imm(bpf_get_prandom_u32) 262 + : __clobber_all); 263 + } 264 + 265 + SEC("socket") 266 + __description("SDIV32, overflow (S32_MIN/-1)") 267 + __success __retval(0) __log_level(2) 268 + __msg("w1 s/= -1 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))") 269 + __naked void sdiv32_overflow_1(void) 270 + { 271 + asm volatile (" \ 272 + call %[bpf_get_prandom_u32]; \ 273 + w1 = w0; \ 274 + w2 = %[int_min]; \ 275 + w2 += 10; \ 276 + if w1 s> w2 goto l0_%=; \ 277 + w1 s/= -1; \ 278 + l0_%=: r0 = 0; \ 279 + exit; \ 280 + " : 281 + : __imm_const(int_min, INT_MIN), 282 + __imm(bpf_get_prandom_u32) 283 + : __clobber_all); 284 + } 285 + 286 + SEC("socket") 287 + __description("SDIV32, overflow (S32_MIN/-1), constant dividend") 288 + __success __retval(0) __log_level(2) 289 + __msg("w1 s/= -1 {{.*}}; R1=0x80000000") 290 + __naked void sdiv32_overflow_2(void) 291 + { 292 + asm volatile (" \ 293 + w1 = %[int_min]; \ 294 + w1 s/= -1; \ 295 + if w1 != %[int_min] goto l0_%=; \ 296 + r0 = 0; \ 297 + exit; \ 298 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 299 + exit; \ 300 + " : 301 + : __imm_const(int_min, INT_MIN) 302 + : __clobber_all); 303 + } 304 + 305 + SEC("socket") 306 + __description("SDIV64, positive divisor, positive dividend") 307 + __success __retval(0) __log_level(2) 308 + __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") 309 + __naked void sdiv64_pos_divisor_1(void) 310 + { 311 + asm volatile (" \ 312 + call %[bpf_get_prandom_u32]; \ 313 + r1 = r0; \ 314 + if r1 s< 8 goto l0_%=; \ 315 + if r1 s> 10 goto l0_%=; \ 316 + r1 s/= 3; \ 317 + if r1 s< 2 goto l1_%=; \ 318 + if r1 s> 3 goto l1_%=; \ 319 + l0_%=: r0 = 0; \ 320 + exit; \ 321 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 322 + exit; \ 323 + " : 324 + : __imm(bpf_get_prandom_u32) 325 + : __clobber_all); 326 + } 327 + 328 + SEC("socket") 329 + __description("SDIV64, positive divisor, negative dividend") 330 + __success __retval(0) __log_level(2) 331 + __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=-2,umin=0xfffffffffffffffd,umax=0xfffffffffffffffe,umin32=0xfffffffd,umax32=0xfffffffe,var_off=(0xfffffffffffffffc; 0x3))") 332 + __naked void sdiv64_pos_divisor_2(void) 333 + { 334 + asm volatile (" \ 335 + call %[bpf_get_prandom_u32]; \ 336 + r1 = r0; \ 337 + if r1 s> -8 goto l0_%=; \ 338 + if r1 s< -10 goto l0_%=; \ 339 + r1 s/= 3; \ 340 + if r1 s< -3 goto l1_%=; \ 341 + if r1 s> -2 goto l1_%=; \ 342 + l0_%=: r0 = 0; \ 343 + exit; \ 344 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 345 + exit; \ 346 + " : 347 + : __imm(bpf_get_prandom_u32) 348 + : __clobber_all); 349 + } 350 + 351 + SEC("socket") 352 + __description("SDIV64, positive divisor, mixed sign dividend") 353 + __success __retval(0) __log_level(2) 354 + __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=3)") 355 + __naked void sdiv64_pos_divisor_3(void) 356 + { 357 + asm volatile (" \ 358 + call %[bpf_get_prandom_u32]; \ 359 + r1 = r0; \ 360 + if r1 s< -8 goto l0_%=; \ 361 + if r1 s> 10 goto l0_%=; \ 362 + r1 s/= 3; \ 363 + if r1 s< -2 goto l1_%=; \ 364 + if r1 s> 3 goto l1_%=; \ 365 + l0_%=: r0 = 0; \ 366 + exit; \ 367 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 368 + exit; \ 369 + " : 370 + : __imm(bpf_get_prandom_u32) 371 + : __clobber_all); 372 + } 373 + 374 + SEC("socket") 375 + __description("SDIV64, negative divisor, positive dividend") 376 + __success __retval(0) __log_level(2) 377 + __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=-2,umin=0xfffffffffffffffd,umax=0xfffffffffffffffe,umin32=0xfffffffd,umax32=0xfffffffe,var_off=(0xfffffffffffffffc; 0x3))") 378 + __naked void sdiv64_neg_divisor_1(void) 379 + { 380 + asm volatile (" \ 381 + call %[bpf_get_prandom_u32]; \ 382 + r1 = r0; \ 383 + if r1 s< 8 goto l0_%=; \ 384 + if r1 s> 10 goto l0_%=; \ 385 + r1 s/= -3; \ 386 + if r1 s< -3 goto l1_%=; \ 387 + if r1 s> -2 goto l1_%=; \ 388 + l0_%=: r0 = 0; \ 389 + exit; \ 390 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 391 + exit; \ 392 + " : 393 + : __imm(bpf_get_prandom_u32) 394 + : __clobber_all); 395 + } 396 + 397 + SEC("socket") 398 + __description("SDIV64, negative divisor, positive dividend") 399 + __success __retval(0) __log_level(2) 400 + __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") 401 + __naked void sdiv64_neg_divisor_2(void) 402 + { 403 + asm volatile (" \ 404 + call %[bpf_get_prandom_u32]; \ 405 + r1 = r0; \ 406 + if r1 s> -8 goto l0_%=; \ 407 + if r1 s< -10 goto l0_%=; \ 408 + r1 s/= -3; \ 409 + if r1 s< 2 goto l1_%=; \ 410 + if r1 s> 3 goto l1_%=; \ 411 + l0_%=: r0 = 0; \ 412 + exit; \ 413 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 414 + exit; \ 415 + " : 416 + : __imm(bpf_get_prandom_u32) 417 + : __clobber_all); 418 + } 419 + 420 + SEC("socket") 421 + __description("SDIV64, negative divisor, mixed sign dividend") 422 + __success __retval(0) __log_level(2) 423 + __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=2)") 424 + __naked void sdiv64_neg_divisor_3(void) 425 + { 426 + asm volatile (" \ 427 + call %[bpf_get_prandom_u32]; \ 428 + r1 = r0; \ 429 + if r1 s< -8 goto l0_%=; \ 430 + if r1 s> 10 goto l0_%=; \ 431 + r1 s/= -3; \ 432 + if r1 s< -3 goto l1_%=; \ 433 + if r1 s> 2 goto l1_%=; \ 434 + l0_%=: r0 = 0; \ 435 + exit; \ 436 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 437 + exit; \ 438 + " : 439 + : __imm(bpf_get_prandom_u32) 440 + : __clobber_all); 441 + } 442 + 443 + SEC("socket") 444 + __description("SDIV64, zero divisor") 445 + __success __retval(0) __log_level(2) 446 + __msg("r1 s/= r2 {{.*}}; R1=0 R2=0") 447 + __naked void sdiv64_zero_divisor(void) 448 + { 449 + asm volatile (" \ 450 + call %[bpf_get_prandom_u32]; \ 451 + r1 = r0; \ 452 + r1 &= 8; \ 453 + r1 |= 1; \ 454 + r2 = 0; \ 455 + r1 s/= r2; \ 456 + if r1 != 0 goto l0_%=; \ 457 + r0 = 0; \ 458 + exit; \ 459 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 460 + exit; \ 461 + " : 462 + : __imm(bpf_get_prandom_u32) 463 + : __clobber_all); 464 + } 465 + 466 + SEC("socket") 467 + __description("SDIV64, overflow (S64_MIN/-1)") 468 + __success __retval(0) __log_level(2) 469 + __msg("r1 s/= -1 {{.*}}; R1=scalar()") 470 + __naked void sdiv64_overflow_1(void) 471 + { 472 + asm volatile (" \ 473 + call %[bpf_ktime_get_ns]; \ 474 + r1 = r0; \ 475 + r2 = %[llong_min] ll; \ 476 + r2 += 10; \ 477 + if r1 s> r2 goto l0_%=; \ 478 + r1 s/= -1; \ 479 + l0_%=: r0 = 0; \ 480 + exit; \ 481 + " : 482 + : __imm_const(llong_min, LLONG_MIN), 483 + __imm(bpf_ktime_get_ns) 484 + : __clobber_all); 485 + } 486 + 487 + SEC("socket") 488 + __description("SDIV64, overflow (S64_MIN/-1), constant dividend") 489 + __success __retval(0) __log_level(2) 490 + __msg("r1 s/= -1 {{.*}}; R1=0x8000000000000000") 491 + __naked void sdiv64_overflow_2(void) 492 + { 493 + asm volatile (" \ 494 + r1 = %[llong_min] ll; \ 495 + r1 s/= -1; \ 496 + r2 = %[llong_min] ll; \ 497 + if r1 != r2 goto l0_%=; \ 498 + r0 = 0; \ 499 + exit; \ 500 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 501 + exit; \ 502 + " : 503 + : __imm_const(llong_min, LLONG_MIN) 504 + : __clobber_all); 505 + } 506 + 507 + SEC("socket") 508 + __description("UMOD32, positive divisor") 509 + __success __retval(0) __log_level(2) 510 + __msg("w1 %= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 511 + __naked void umod32_pos_divisor(void) 512 + { 513 + asm volatile (" \ 514 + call %[bpf_get_prandom_u32]; \ 515 + w1 = w0; \ 516 + w1 &= 8; \ 517 + w1 |= 1; \ 518 + w1 %%= 3; \ 519 + if w1 > 3 goto l0_%=; \ 520 + r0 = 0; \ 521 + exit; \ 522 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 523 + exit; \ 524 + " : 525 + : __imm(bpf_get_prandom_u32) 526 + : __clobber_all); 527 + } 528 + 529 + SEC("socket") 530 + __description("UMOD32, positive divisor, small dividend") 531 + __success __retval(0) __log_level(2) 532 + __msg("w1 %= 10 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") 533 + __naked void umod32_pos_divisor_unchanged(void) 534 + { 535 + asm volatile (" \ 536 + call %[bpf_get_prandom_u32]; \ 537 + w1 = w0; \ 538 + w1 &= 8; \ 539 + w1 |= 1; \ 540 + w1 %%= 10; \ 541 + if w1 < 1 goto l0_%=; \ 542 + if w1 > 9 goto l0_%=; \ 543 + if w1 & 1 != 1 goto l0_%=; \ 544 + r0 = 0; \ 545 + exit; \ 546 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 547 + exit; \ 548 + " : 549 + : __imm(bpf_get_prandom_u32) 550 + : __clobber_all); 551 + } 552 + 553 + SEC("socket") 554 + __description("UMOD32, zero divisor") 555 + __success __retval(0) __log_level(2) 556 + __msg("w1 %= w2 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8)) R2=0") 557 + __naked void umod32_zero_divisor(void) 558 + { 559 + asm volatile (" \ 560 + call %[bpf_get_prandom_u32]; \ 561 + w1 = w0; \ 562 + w1 &= 8; \ 563 + w1 |= 1; \ 564 + w2 = 0; \ 565 + w1 %%= w2; \ 566 + if w1 < 1 goto l0_%=; \ 567 + if w1 > 9 goto l0_%=; \ 568 + if w1 & 1 != 1 goto l0_%=; \ 569 + r0 = 0; \ 570 + exit; \ 571 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 572 + exit; \ 573 + " : 574 + : __imm(bpf_get_prandom_u32) 575 + : __clobber_all); 576 + } 577 + 578 + SEC("socket") 579 + __description("UMOD64, positive divisor") 580 + __success __retval(0) __log_level(2) 581 + __msg("r1 %= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 582 + __naked void umod64_pos_divisor(void) 583 + { 584 + asm volatile (" \ 585 + call %[bpf_get_prandom_u32]; \ 586 + r1 = r0; \ 587 + r1 &= 8; \ 588 + r1 |= 1; \ 589 + r1 %%= 3; \ 590 + if r1 > 3 goto l0_%=; \ 591 + r0 = 0; \ 592 + exit; \ 593 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 594 + exit; \ 595 + " : 596 + : __imm(bpf_get_prandom_u32) 597 + : __clobber_all); 598 + } 599 + 600 + SEC("socket") 601 + __description("UMOD64, positive divisor, small dividend") 602 + __success __retval(0) __log_level(2) 603 + __msg("r1 %= 10 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") 604 + __naked void umod64_pos_divisor_unchanged(void) 605 + { 606 + asm volatile (" \ 607 + call %[bpf_get_prandom_u32]; \ 608 + r1 = r0; \ 609 + r1 &= 8; \ 610 + r1 |= 1; \ 611 + r1 %%= 10; \ 612 + if r1 < 1 goto l0_%=; \ 613 + if r1 > 9 goto l0_%=; \ 614 + if r1 & 1 != 1 goto l0_%=; \ 615 + r0 = 0; \ 616 + exit; \ 617 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 618 + exit; \ 619 + " : 620 + : __imm(bpf_get_prandom_u32) 621 + : __clobber_all); 622 + } 623 + 624 + SEC("socket") 625 + __description("UMOD64, zero divisor") 626 + __success __retval(0) __log_level(2) 627 + __msg("r1 %= r2 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8)) R2=0") 628 + __naked void umod64_zero_divisor(void) 629 + { 630 + asm volatile (" \ 631 + call %[bpf_get_prandom_u32]; \ 632 + r1 = r0; \ 633 + r1 &= 8; \ 634 + r1 |= 1; \ 635 + r2 = 0; \ 636 + r1 %%= r2; \ 637 + if r1 < 1 goto l0_%=; \ 638 + if r1 > 9 goto l0_%=; \ 639 + if r1 & 1 != 1 goto l0_%=; \ 640 + r0 = 0; \ 641 + exit; \ 642 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 643 + exit; \ 644 + " : 645 + : __imm(bpf_get_prandom_u32) 646 + : __clobber_all); 647 + } 648 + 649 + SEC("socket") 650 + __description("SMOD32, positive divisor, positive dividend") 651 + __success __retval(0) __log_level(2) 652 + __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 653 + __naked void smod32_pos_divisor_1(void) 654 + { 655 + asm volatile (" \ 656 + call %[bpf_get_prandom_u32]; \ 657 + w1 = w0; \ 658 + if w1 s< 8 goto l0_%=; \ 659 + if w1 s> 10 goto l0_%=; \ 660 + w1 s%%= 3; \ 661 + if w1 s< 0 goto l1_%=; \ 662 + if w1 s> 2 goto l1_%=; \ 663 + l0_%=: r0 = 0; \ 664 + exit; \ 665 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 666 + exit; \ 667 + " : 668 + : __imm(bpf_get_prandom_u32) 669 + : __clobber_all); 670 + } 671 + 672 + SEC("socket") 673 + __description("SMOD32, positive divisor, negative dividend") 674 + __success __retval(0) __log_level(2) 675 + __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=0,var_off=(0x0; 0xffffffff))") 676 + __naked void smod32_pos_divisor_2(void) 677 + { 678 + asm volatile (" \ 679 + call %[bpf_get_prandom_u32]; \ 680 + w1 = w0; \ 681 + if w1 s> -8 goto l0_%=; \ 682 + if w1 s< -10 goto l0_%=; \ 683 + w1 s%%= 3; \ 684 + if w1 s< -2 goto l1_%=; \ 685 + if w1 s> 0 goto l1_%=; \ 686 + l0_%=: r0 = 0; \ 687 + exit; \ 688 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 689 + exit; \ 690 + " : 691 + : __imm(bpf_get_prandom_u32) 692 + : __clobber_all); 693 + } 694 + 695 + SEC("socket") 696 + __description("SMOD32, positive divisor, mixed sign dividend") 697 + __success __retval(0) __log_level(2) 698 + __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=2,var_off=(0x0; 0xffffffff))") 699 + __naked void smod32_pos_divisor_3(void) 700 + { 701 + asm volatile (" \ 702 + call %[bpf_get_prandom_u32]; \ 703 + w1 = w0; \ 704 + if w1 s< -8 goto l0_%=; \ 705 + if w1 s> 10 goto l0_%=; \ 706 + w1 s%%= 3; \ 707 + if w1 s< -2 goto l1_%=; \ 708 + if w1 s> 2 goto l1_%=; \ 709 + l0_%=: r0 = 0; \ 710 + exit; \ 711 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 712 + exit; \ 713 + " : 714 + : __imm(bpf_get_prandom_u32) 715 + : __clobber_all); 716 + } 717 + 718 + SEC("socket") 719 + __description("SMOD32, positive divisor, small dividend") 720 + __success __retval(0) __log_level(2) 721 + __msg("w1 s%= 11 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff))") 722 + __naked void smod32_pos_divisor_unchanged(void) 723 + { 724 + asm volatile (" \ 725 + call %[bpf_get_prandom_u32]; \ 726 + w1 = w0; \ 727 + if w1 s< -8 goto l0_%=; \ 728 + if w1 s> 10 goto l0_%=; \ 729 + w1 s%%= 11; \ 730 + if w1 s< -8 goto l1_%=; \ 731 + if w1 s> 10 goto l1_%=; \ 732 + l0_%=: r0 = 0; \ 733 + exit; \ 734 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 735 + exit; \ 736 + " : 737 + : __imm(bpf_get_prandom_u32) 738 + : __clobber_all); 739 + } 740 + 741 + SEC("socket") 742 + __description("SMOD32, negative divisor, positive dividend") 743 + __success __retval(0) __log_level(2) 744 + __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 745 + __naked void smod32_neg_divisor_1(void) 746 + { 747 + asm volatile (" \ 748 + call %[bpf_get_prandom_u32]; \ 749 + w1 = w0; \ 750 + if w1 s< 8 goto l0_%=; \ 751 + if w1 s> 10 goto l0_%=; \ 752 + w1 s%%= -3; \ 753 + if w1 s< 0 goto l1_%=; \ 754 + if w1 s> 2 goto l1_%=; \ 755 + l0_%=: r0 = 0; \ 756 + exit; \ 757 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 758 + exit; \ 759 + " : 760 + : __imm(bpf_get_prandom_u32) 761 + : __clobber_all); 762 + } 763 + 764 + SEC("socket") 765 + __description("SMOD32, negative divisor, negative dividend") 766 + __success __retval(0) __log_level(2) 767 + __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=0,var_off=(0x0; 0xffffffff))") 768 + __naked void smod32_neg_divisor_2(void) 769 + { 770 + asm volatile (" \ 771 + call %[bpf_get_prandom_u32]; \ 772 + w1 = w0; \ 773 + if w1 s> -8 goto l0_%=; \ 774 + if w1 s< -10 goto l0_%=; \ 775 + w1 s%%= -3; \ 776 + if w1 s< -2 goto l1_%=; \ 777 + if w1 s> 0 goto l1_%=; \ 778 + l0_%=: r0 = 0; \ 779 + exit; \ 780 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 781 + exit; \ 782 + " : 783 + : __imm(bpf_get_prandom_u32) 784 + : __clobber_all); 785 + } 786 + 787 + SEC("socket") 788 + __description("SMOD32, negative divisor, mixed sign dividend") 789 + __success __retval(0) __log_level(2) 790 + __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=2,var_off=(0x0; 0xffffffff))") 791 + __naked void smod32_neg_divisor_3(void) 792 + { 793 + asm volatile (" \ 794 + call %[bpf_get_prandom_u32]; \ 795 + w1 = w0; \ 796 + if w1 s< -8 goto l0_%=; \ 797 + if w1 s> 10 goto l0_%=; \ 798 + w1 s%%= -3; \ 799 + if w1 s< -2 goto l1_%=; \ 800 + if w1 s> 2 goto l1_%=; \ 801 + l0_%=: r0 = 0; \ 802 + exit; \ 803 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 804 + exit; \ 805 + " : 806 + : __imm(bpf_get_prandom_u32) 807 + : __clobber_all); 808 + } 809 + 810 + SEC("socket") 811 + __description("SMOD32, negative divisor, small dividend") 812 + __success __retval(0) __log_level(2) 813 + __msg("w1 s%= -11 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff))") 814 + __naked void smod32_neg_divisor_unchanged(void) 815 + { 816 + asm volatile (" \ 817 + call %[bpf_get_prandom_u32]; \ 818 + w1 = w0; \ 819 + if w1 s< -8 goto l0_%=; \ 820 + if w1 s> 10 goto l0_%=; \ 821 + w1 s%%= -11; \ 822 + if w1 s< -8 goto l1_%=; \ 823 + if w1 s> 10 goto l1_%=; \ 824 + l0_%=: r0 = 0; \ 825 + exit; \ 826 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 827 + exit; \ 828 + " : 829 + : __imm(bpf_get_prandom_u32) 830 + : __clobber_all); 831 + } 832 + 833 + SEC("socket") 834 + __description("SMOD32, zero divisor") 835 + __success __retval(0) __log_level(2) 836 + __msg("w1 s%= w2 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff)) R2=0") 837 + __naked void smod32_zero_divisor(void) 838 + { 839 + asm volatile (" \ 840 + call %[bpf_get_prandom_u32]; \ 841 + w1 = w0; \ 842 + if w1 s< -8 goto l0_%=; \ 843 + if w1 s> 10 goto l0_%=; \ 844 + w2 = 0; \ 845 + w1 s%%= w2; \ 846 + if w1 s< -8 goto l1_%=; \ 847 + if w1 s> 10 goto l1_%=; \ 848 + l0_%=: r0 = 0; \ 849 + exit; \ 850 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 851 + exit; \ 852 + " : 853 + : __imm(bpf_get_prandom_u32) 854 + : __clobber_all); 855 + } 856 + 857 + SEC("socket") 858 + __description("SMOD32, overflow (S32_MIN%-1)") 859 + __success __retval(0) __log_level(2) 860 + __msg("w1 s%= -1 {{.*}}; R1=0") 861 + __naked void smod32_overflow_1(void) 862 + { 863 + asm volatile (" \ 864 + call %[bpf_get_prandom_u32]; \ 865 + w1 = w0; \ 866 + w2 = %[int_min]; \ 867 + w2 += 10; \ 868 + if w1 s> w2 goto l0_%=; \ 869 + w1 s%%= -1; \ 870 + if w1 != 0 goto l1_%=; \ 871 + l0_%=: r0 = 0; \ 872 + exit; \ 873 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 874 + exit; \ 875 + " : 876 + : __imm_const(int_min, INT_MIN), 877 + __imm(bpf_get_prandom_u32) 878 + : __clobber_all); 879 + } 880 + 881 + SEC("socket") 882 + __description("SMOD32, overflow (S32_MIN%-1), constant dividend") 883 + __success __retval(0) __log_level(2) 884 + __msg("w1 s%= -1 {{.*}}; R1=0") 885 + __naked void smod32_overflow_2(void) 886 + { 887 + asm volatile (" \ 888 + w1 = %[int_min]; \ 889 + w1 s%%= -1; \ 890 + if w1 != 0 goto l0_%=; \ 891 + r0 = 0; \ 892 + exit; \ 893 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 894 + exit; \ 895 + " : 896 + : __imm_const(int_min, INT_MIN) 897 + : __clobber_all); 898 + } 899 + 900 + SEC("socket") 901 + __description("SMOD64, positive divisor, positive dividend") 902 + __success __retval(0) __log_level(2) 903 + __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 904 + __naked void smod64_pos_divisor_1(void) 905 + { 906 + asm volatile (" \ 907 + call %[bpf_get_prandom_u32]; \ 908 + r1 = r0; \ 909 + if r1 s< 8 goto l0_%=; \ 910 + if r1 s> 10 goto l0_%=; \ 911 + r1 s%%= 3; \ 912 + if r1 s< 0 goto l1_%=; \ 913 + if r1 s> 2 goto l1_%=; \ 914 + l0_%=: r0 = 0; \ 915 + exit; \ 916 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 917 + exit; \ 918 + " : 919 + : __imm(bpf_get_prandom_u32) 920 + : __clobber_all); 921 + } 922 + 923 + SEC("socket") 924 + __description("SMOD64, positive divisor, negative dividend") 925 + __success __retval(0) __log_level(2) 926 + __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=0)") 927 + __naked void smod64_pos_divisor_2(void) 928 + { 929 + asm volatile (" \ 930 + call %[bpf_get_prandom_u32]; \ 931 + r1 = r0; \ 932 + if r1 s> -8 goto l0_%=; \ 933 + if r1 s< -10 goto l0_%=; \ 934 + r1 s%%= 3; \ 935 + if r1 s< -2 goto l1_%=; \ 936 + if r1 s> 0 goto l1_%=; \ 937 + l0_%=: r0 = 0; \ 938 + exit; \ 939 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 940 + exit; \ 941 + " : 942 + : __imm(bpf_get_prandom_u32) 943 + : __clobber_all); 944 + } 945 + 946 + SEC("socket") 947 + __description("SMOD64, positive divisor, mixed sign dividend") 948 + __success __retval(0) __log_level(2) 949 + __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=2)") 950 + __naked void smod64_pos_divisor_3(void) 951 + { 952 + asm volatile (" \ 953 + call %[bpf_get_prandom_u32]; \ 954 + r1 = r0; \ 955 + if r1 s< -8 goto l0_%=; \ 956 + if r1 s> 10 goto l0_%=; \ 957 + r1 s%%= 3; \ 958 + if r1 s< -2 goto l1_%=; \ 959 + if r1 s> 2 goto l1_%=; \ 960 + l0_%=: r0 = 0; \ 961 + exit; \ 962 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 963 + exit; \ 964 + " : 965 + : __imm(bpf_get_prandom_u32) 966 + : __clobber_all); 967 + } 968 + 969 + SEC("socket") 970 + __description("SMOD64, positive divisor, small dividend") 971 + __success __retval(0) __log_level(2) 972 + __msg("r1 s%= 11 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10)") 973 + __naked void smod64_pos_divisor_unchanged(void) 974 + { 975 + asm volatile (" \ 976 + call %[bpf_get_prandom_u32]; \ 977 + r1 = r0; \ 978 + if r1 s< -8 goto l0_%=; \ 979 + if r1 s> 10 goto l0_%=; \ 980 + r1 s%%= 11; \ 981 + if r1 s< -8 goto l1_%=; \ 982 + if r1 s> 10 goto l1_%=; \ 983 + l0_%=: r0 = 0; \ 984 + exit; \ 985 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 986 + exit; \ 987 + " : 988 + : __imm(bpf_get_prandom_u32) 989 + : __clobber_all); 990 + } 991 + 992 + SEC("socket") 993 + __description("SMOD64, negative divisor, positive dividend") 994 + __success __retval(0) __log_level(2) 995 + __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") 996 + __naked void smod64_neg_divisor_1(void) 997 + { 998 + asm volatile (" \ 999 + call %[bpf_get_prandom_u32]; \ 1000 + r1 = r0; \ 1001 + if r1 s< 8 goto l0_%=; \ 1002 + if r1 s> 10 goto l0_%=; \ 1003 + r1 s%%= -3; \ 1004 + if r1 s< 0 goto l1_%=; \ 1005 + if r1 s> 2 goto l1_%=; \ 1006 + l0_%=: r0 = 0; \ 1007 + exit; \ 1008 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1009 + exit; \ 1010 + " : 1011 + : __imm(bpf_get_prandom_u32) 1012 + : __clobber_all); 1013 + } 1014 + 1015 + SEC("socket") 1016 + __description("SMOD64, negative divisor, negative dividend") 1017 + __success __retval(0) __log_level(2) 1018 + __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=0)") 1019 + __naked void smod64_neg_divisor_2(void) 1020 + { 1021 + asm volatile (" \ 1022 + call %[bpf_get_prandom_u32]; \ 1023 + r1 = r0; \ 1024 + if r1 s> -8 goto l0_%=; \ 1025 + if r1 s< -10 goto l0_%=; \ 1026 + r1 s%%= -3; \ 1027 + if r1 s< -2 goto l1_%=; \ 1028 + if r1 s> 0 goto l1_%=; \ 1029 + l0_%=: r0 = 0; \ 1030 + exit; \ 1031 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1032 + exit; \ 1033 + " : 1034 + : __imm(bpf_get_prandom_u32) 1035 + : __clobber_all); 1036 + } 1037 + 1038 + SEC("socket") 1039 + __description("SMOD64, negative divisor, mixed sign dividend") 1040 + __success __retval(0) __log_level(2) 1041 + __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=2)") 1042 + __naked void smod64_neg_divisor_3(void) 1043 + { 1044 + asm volatile (" \ 1045 + call %[bpf_get_prandom_u32]; \ 1046 + r1 = r0; \ 1047 + if r1 s< -8 goto l0_%=; \ 1048 + if r1 s> 10 goto l0_%=; \ 1049 + r1 s%%= -3; \ 1050 + if r1 s< -2 goto l1_%=; \ 1051 + if r1 s> 2 goto l1_%=; \ 1052 + l0_%=: r0 = 0; \ 1053 + exit; \ 1054 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1055 + exit; \ 1056 + " : 1057 + : __imm(bpf_get_prandom_u32) 1058 + : __clobber_all); 1059 + } 1060 + 1061 + SEC("socket") 1062 + __description("SMOD64, negative divisor, small dividend") 1063 + __success __retval(0) __log_level(2) 1064 + __msg("r1 s%= -11 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10)") 1065 + __naked void smod64_neg_divisor_unchanged(void) 1066 + { 1067 + asm volatile (" \ 1068 + call %[bpf_get_prandom_u32]; \ 1069 + r1 = r0; \ 1070 + if r1 s< -8 goto l0_%=; \ 1071 + if r1 s> 10 goto l0_%=; \ 1072 + r1 s%%= -11; \ 1073 + if r1 s< -8 goto l1_%=; \ 1074 + if r1 s> 10 goto l1_%=; \ 1075 + l0_%=: r0 = 0; \ 1076 + exit; \ 1077 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1078 + exit; \ 1079 + " : 1080 + : __imm(bpf_get_prandom_u32) 1081 + : __clobber_all); 1082 + } 1083 + 1084 + SEC("socket") 1085 + __description("SMOD64, zero divisor") 1086 + __success __retval(0) __log_level(2) 1087 + __msg("r1 s%= r2 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10) R2=0") 1088 + __naked void smod64_zero_divisor(void) 1089 + { 1090 + asm volatile (" \ 1091 + call %[bpf_get_prandom_u32]; \ 1092 + r1 = r0; \ 1093 + if r1 s< -8 goto l0_%=; \ 1094 + if r1 s> 10 goto l0_%=; \ 1095 + r2 = 0; \ 1096 + r1 s%%= r2; \ 1097 + if r1 s< -8 goto l1_%=; \ 1098 + if r1 s> 10 goto l1_%=; \ 1099 + l0_%=: r0 = 0; \ 1100 + exit; \ 1101 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1102 + exit; \ 1103 + " : 1104 + : __imm(bpf_get_prandom_u32) 1105 + : __clobber_all); 1106 + } 1107 + 1108 + SEC("socket") 1109 + __description("SMOD64, overflow (S64_MIN%-1)") 1110 + __success __retval(0) __log_level(2) 1111 + __msg("r1 s%= -1 {{.*}}; R1=0") 1112 + __naked void smod64_overflow_1(void) 1113 + { 1114 + asm volatile (" \ 1115 + call %[bpf_ktime_get_ns]; \ 1116 + r1 = r0; \ 1117 + r2 = %[llong_min] ll; \ 1118 + r2 += 10; \ 1119 + if r1 s> r2 goto l0_%=; \ 1120 + r1 s%%= -1; \ 1121 + if r1 != 0 goto l1_%=; \ 1122 + l0_%=: r0 = 0; \ 1123 + exit; \ 1124 + l1_%=: r0 = *(u64 *)(r1 + 0); \ 1125 + exit; \ 1126 + " : 1127 + : __imm_const(llong_min, LLONG_MIN), 1128 + __imm(bpf_ktime_get_ns) 1129 + : __clobber_all); 1130 + } 1131 + 1132 + SEC("socket") 1133 + __description("SMOD64, overflow (S64_MIN%-1), constant dividend") 1134 + __success __retval(0) __log_level(2) 1135 + __msg("r1 s%= -1 {{.*}}; R1=0") 1136 + __naked void smod64_overflow_2(void) 1137 + { 1138 + asm volatile (" \ 1139 + r1 = %[llong_min] ll; \ 1140 + r1 s%%= -1; \ 1141 + if r1 != 0 goto l0_%=; \ 1142 + r0 = 0; \ 1143 + exit; \ 1144 + l0_%=: r0 = *(u64 *)(r1 + 0); \ 1145 + exit; \ 1146 + " : 1147 + : __imm_const(llong_min, LLONG_MIN) 1148 + : __clobber_all); 1149 + }
+4 -3
tools/testing/selftests/bpf/progs/verifier_value_illegal_alu.c
··· 173 173 asm volatile(" \ 174 174 r6 = r1; \ 175 175 r7 = *(u64*)(r6 + %[flow_keys_off]); \ 176 - r8 = 8; \ 177 - r8 /= 1; \ 176 + call %[bpf_get_prandom_u32]; \ 177 + r8 = r0; \ 178 178 r8 &= 8; \ 179 179 r7 += r8; \ 180 180 r0 = *(u64*)(r7 + 0); \ 181 181 exit; \ 182 182 " : 183 - : __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys)) 183 + : __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys)), 184 + __imm(bpf_get_prandom_u32) 184 185 : __clobber_all); 185 186 } 186 187
+2 -2
tools/testing/selftests/bpf/verifier/precise.c
··· 229 229 { 230 230 "precise: program doesn't prematurely prune branches", 231 231 .insns = { 232 - BPF_ALU64_IMM(BPF_MOV, BPF_REG_6, 0x400), 232 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32), 233 + BPF_ALU64_REG(BPF_MOV, BPF_REG_6, BPF_REG_0), 233 234 BPF_ALU64_IMM(BPF_MOV, BPF_REG_7, 0), 234 235 BPF_ALU64_IMM(BPF_MOV, BPF_REG_8, 0), 235 236 BPF_ALU64_IMM(BPF_MOV, BPF_REG_9, 0x80000000), 236 - BPF_ALU64_IMM(BPF_MOD, BPF_REG_6, 0x401), 237 237 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 238 238 BPF_JMP_REG(BPF_JLE, BPF_REG_6, BPF_REG_9, 2), 239 239 BPF_ALU64_IMM(BPF_MOD, BPF_REG_6, 1),