| // SPDX-License-Identifier: GPL-2.0 |
| |
| #include <linux/bpf.h> |
| #include <limits.h> |
| #include <bpf/bpf_helpers.h> |
| #include "bpf_misc.h" |
| |
| /* This file contains unit tests for signed/unsigned division and modulo |
| * operations (with divisor as a constant), focusing on verifying whether |
| * BPF verifier's range tracking module soundly and precisely computes |
| * the results. |
| */ |
| |
| SEC("socket") |
| __description("UDIV32, positive divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 /= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=3,var_off=(0x0; 0x3))") |
| __naked void udiv32_pos_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w1 /= 3; \ |
| if w1 > 3 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UDIV32, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 /= w2 {{.*}}; R1=0") |
| __naked void udiv32_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w2 = 0; \ |
| w1 /= w2; \ |
| if w1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UDIV64, positive divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 /= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=3,var_off=(0x0; 0x3))") |
| __naked void udiv64_pos_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r1 /= 3; \ |
| if r1 > 3 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UDIV64, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 /= r2 {{.*}}; R1=0") |
| __naked void udiv64_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r2 = 0; \ |
| r1 /= r2; \ |
| if r1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, positive divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") |
| __naked void sdiv32_pos_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< 8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s/= 3; \ |
| if w1 s< 2 goto l1_%=; \ |
| if w1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, positive divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=umin=umin32=0xfffffffd,smax=umax=umax32=0xfffffffe,smin32=-3,smax32=-2,var_off=(0xfffffffc; 0x3))") |
| __naked void sdiv32_pos_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s> -8 goto l0_%=; \ |
| if w1 s< -10 goto l0_%=; \ |
| w1 s/= 3; \ |
| if w1 s< -3 goto l1_%=; \ |
| if w1 s> -2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, positive divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=3,var_off=(0x0; 0xffffffff))") |
| __naked void sdiv32_pos_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s/= 3; \ |
| if w1 s< -2 goto l1_%=; \ |
| if w1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=umin=umin32=0xfffffffd,smax=umax=umax32=0xfffffffe,smin32=-3,smax32=-2,var_off=(0xfffffffc; 0x3))") |
| __naked void sdiv32_neg_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< 8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s/= -3; \ |
| if w1 s< -3 goto l1_%=; \ |
| if w1 s> -2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") |
| __naked void sdiv32_neg_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s> -8 goto l0_%=; \ |
| if w1 s< -10 goto l0_%=; \ |
| w1 s/= -3; \ |
| if w1 s< 2 goto l1_%=; \ |
| if w1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, negative divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-3,smax32=2,var_off=(0x0; 0xffffffff))") |
| __naked void sdiv32_neg_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s/= -3; \ |
| if w1 s< -3 goto l1_%=; \ |
| if w1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= w2 {{.*}}; R1=0") |
| __naked void sdiv32_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w2 = 0; \ |
| w1 s/= w2; \ |
| if w1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, overflow (S32_MIN/-1)") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= -1 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))") |
| __naked void sdiv32_overflow_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w2 = %[int_min]; \ |
| w2 += 10; \ |
| if w1 s> w2 goto l0_%=; \ |
| w1 s/= -1; \ |
| r2 = r1; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| " : |
| : __imm_const(int_min, INT_MIN), |
| __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV32, overflow (S32_MIN/-1), constant dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s/= -1 {{.*}}; R1=0x80000000") |
| __naked void sdiv32_overflow_2(void) |
| { |
| asm volatile (" \ |
| w1 = %[int_min]; \ |
| w1 s/= -1; \ |
| if w1 != %[int_min] goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(int_min, INT_MIN) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, positive divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") |
| __naked void sdiv64_pos_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< 8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s/= 3; \ |
| if r1 s< 2 goto l1_%=; \ |
| if r1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, positive divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=-2,umin=0xfffffffffffffffd,umax=0xfffffffffffffffe,umin32=0xfffffffd,umax32=0xfffffffe,var_off=(0xfffffffffffffffc; 0x3))") |
| __naked void sdiv64_pos_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s> -8 goto l0_%=; \ |
| if r1 s< -10 goto l0_%=; \ |
| r1 s/= 3; \ |
| if r1 s< -3 goto l1_%=; \ |
| if r1 s> -2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, positive divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=3)") |
| __naked void sdiv64_pos_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s/= 3; \ |
| if r1 s< -2 goto l1_%=; \ |
| if r1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=-2,umin=0xfffffffffffffffd,umax=0xfffffffffffffffe,umin32=0xfffffffd,umax32=0xfffffffe,var_off=(0xfffffffffffffffc; 0x3))") |
| __naked void sdiv64_neg_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< 8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s/= -3; \ |
| if r1 s< -3 goto l1_%=; \ |
| if r1 s> -2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=umin=smin32=umin32=2,smax=umax=smax32=umax32=3,var_off=(0x2; 0x1))") |
| __naked void sdiv64_neg_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s> -8 goto l0_%=; \ |
| if r1 s< -10 goto l0_%=; \ |
| r1 s/= -3; \ |
| if r1 s< 2 goto l1_%=; \ |
| if r1 s> 3 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, negative divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= -3 {{.*}}; R1=scalar(smin=smin32=-3,smax=smax32=2)") |
| __naked void sdiv64_neg_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s/= -3; \ |
| if r1 s< -3 goto l1_%=; \ |
| if r1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= r2 {{.*}}; R1=0") |
| __naked void sdiv64_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r2 = 0; \ |
| r1 s/= r2; \ |
| if r1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, overflow (S64_MIN/-1)") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= -1 {{.*}}; R1=scalar()") |
| __naked void sdiv64_overflow_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_ktime_get_ns]; \ |
| r1 = r0; \ |
| r2 = %[llong_min] ll; \ |
| r2 += 10; \ |
| if r1 s> r2 goto l0_%=; \ |
| r1 s/= -1; \ |
| r2 = r1; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| " : |
| : __imm_const(llong_min, LLONG_MIN), |
| __imm(bpf_ktime_get_ns) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SDIV64, overflow (S64_MIN/-1), constant dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s/= -1 {{.*}}; R1=0x8000000000000000") |
| __naked void sdiv64_overflow_2(void) |
| { |
| asm volatile (" \ |
| r1 = %[llong_min] ll; \ |
| r1 s/= -1; \ |
| r2 = %[llong_min] ll; \ |
| if r1 != r2 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(llong_min, LLONG_MIN) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD32, positive divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 %= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void umod32_pos_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w1 %%= 3; \ |
| if w1 > 3 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD32, positive divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 %= 10 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") |
| __naked void umod32_pos_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w1 %%= 10; \ |
| if w1 < 1 goto l0_%=; \ |
| if w1 > 9 goto l0_%=; \ |
| if w1 & 1 != 1 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD32, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 %= w2 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") |
| __naked void umod32_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w1 &= 8; \ |
| w1 |= 1; \ |
| w2 = 0; \ |
| w1 %%= w2; \ |
| if w1 < 1 goto l0_%=; \ |
| if w1 > 9 goto l0_%=; \ |
| if w1 & 1 != 1 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD64, positive divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 %= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void umod64_pos_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r1 %%= 3; \ |
| if r1 > 3 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD64, positive divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 %= 10 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") |
| __naked void umod64_pos_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r1 %%= 10; \ |
| if r1 < 1 goto l0_%=; \ |
| if r1 > 9 goto l0_%=; \ |
| if r1 & 1 != 1 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("UMOD64, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 %= r2 {{.*}}; R1=scalar(smin=umin=smin32=umin32=1,smax=umax=smax32=umax32=9,var_off=(0x1; 0x8))") |
| __naked void umod64_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| r1 &= 8; \ |
| r1 |= 1; \ |
| r2 = 0; \ |
| r1 %%= r2; \ |
| if r1 < 1 goto l0_%=; \ |
| if r1 > 9 goto l0_%=; \ |
| if r1 & 1 != 1 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, positive divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void smod32_pos_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< 8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= 3; \ |
| if w1 s< 0 goto l1_%=; \ |
| if w1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, positive divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=0,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_pos_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s> -8 goto l0_%=; \ |
| if w1 s< -10 goto l0_%=; \ |
| w1 s%%= 3; \ |
| if w1 s< -2 goto l1_%=; \ |
| if w1 s> 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, positive divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= 3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=2,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_pos_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= 3; \ |
| if w1 s< -2 goto l1_%=; \ |
| if w1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, positive divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= 11 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_pos_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= 11; \ |
| if w1 s< -8 goto l1_%=; \ |
| if w1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void smod32_neg_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< 8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= -3; \ |
| if w1 s< 0 goto l1_%=; \ |
| if w1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, negative divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=0,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_neg_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s> -8 goto l0_%=; \ |
| if w1 s< -10 goto l0_%=; \ |
| w1 s%%= -3; \ |
| if w1 s< -2 goto l1_%=; \ |
| if w1 s> 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, negative divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -3 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-2,smax32=2,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_neg_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= -3; \ |
| if w1 s< -2 goto l1_%=; \ |
| if w1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, negative divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -11 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_neg_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w1 s%%= -11; \ |
| if w1 s< -8 goto l1_%=; \ |
| if w1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= w2 {{.*}}; R1=scalar(smin=0,smax=umax=0xffffffff,smin32=-8,smax32=10,var_off=(0x0; 0xffffffff))") |
| __naked void smod32_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| if w1 s< -8 goto l0_%=; \ |
| if w1 s> 10 goto l0_%=; \ |
| w2 = 0; \ |
| w1 s%%= w2; \ |
| if w1 s< -8 goto l1_%=; \ |
| if w1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, overflow (S32_MIN%-1)") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -1 {{.*}}; R1=0") |
| __naked void smod32_overflow_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| w1 = w0; \ |
| w2 = %[int_min]; \ |
| w2 += 10; \ |
| if w1 s> w2 goto l0_%=; \ |
| w1 s%%= -1; \ |
| if w1 != 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(int_min, INT_MIN), |
| __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD32, overflow (S32_MIN%-1), constant dividend") |
| __success __retval(0) __log_level(2) |
| __msg("w1 s%= -1 {{.*}}; R1=0") |
| __naked void smod32_overflow_2(void) |
| { |
| asm volatile (" \ |
| w1 = %[int_min]; \ |
| w1 s%%= -1; \ |
| if w1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(int_min, INT_MIN) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, positive divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void smod64_pos_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< 8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= 3; \ |
| if r1 s< 0 goto l1_%=; \ |
| if r1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, positive divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=0)") |
| __naked void smod64_pos_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s> -8 goto l0_%=; \ |
| if r1 s< -10 goto l0_%=; \ |
| r1 s%%= 3; \ |
| if r1 s< -2 goto l1_%=; \ |
| if r1 s> 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, positive divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= 3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=2)") |
| __naked void smod64_pos_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= 3; \ |
| if r1 s< -2 goto l1_%=; \ |
| if r1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, positive divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= 11 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10)") |
| __naked void smod64_pos_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= 11; \ |
| if r1 s< -8 goto l1_%=; \ |
| if r1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, negative divisor, positive dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=0,smax=umax=smax32=umax32=2,var_off=(0x0; 0x3))") |
| __naked void smod64_neg_divisor_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< 8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= -3; \ |
| if r1 s< 0 goto l1_%=; \ |
| if r1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, negative divisor, negative dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=0)") |
| __naked void smod64_neg_divisor_2(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s> -8 goto l0_%=; \ |
| if r1 s< -10 goto l0_%=; \ |
| r1 s%%= -3; \ |
| if r1 s< -2 goto l1_%=; \ |
| if r1 s> 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, negative divisor, mixed sign dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -3 {{.*}}; R1=scalar(smin=smin32=-2,smax=smax32=2)") |
| __naked void smod64_neg_divisor_3(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= -3; \ |
| if r1 s< -2 goto l1_%=; \ |
| if r1 s> 2 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, negative divisor, small dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -11 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10)") |
| __naked void smod64_neg_divisor_unchanged(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r1 s%%= -11; \ |
| if r1 s< -8 goto l1_%=; \ |
| if r1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, zero divisor") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= r2 {{.*}}; R1=scalar(smin=smin32=-8,smax=smax32=10)") |
| __naked void smod64_zero_divisor(void) |
| { |
| asm volatile (" \ |
| call %[bpf_get_prandom_u32]; \ |
| r1 = r0; \ |
| if r1 s< -8 goto l0_%=; \ |
| if r1 s> 10 goto l0_%=; \ |
| r2 = 0; \ |
| r1 s%%= r2; \ |
| if r1 s< -8 goto l1_%=; \ |
| if r1 s> 10 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm(bpf_get_prandom_u32) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, overflow (S64_MIN%-1)") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -1 {{.*}}; R1=0") |
| __naked void smod64_overflow_1(void) |
| { |
| asm volatile (" \ |
| call %[bpf_ktime_get_ns]; \ |
| r1 = r0; \ |
| r2 = %[llong_min] ll; \ |
| r2 += 10; \ |
| if r1 s> r2 goto l0_%=; \ |
| r1 s%%= -1; \ |
| if r1 != 0 goto l1_%=; \ |
| l0_%=: r0 = 0; \ |
| exit; \ |
| l1_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(llong_min, LLONG_MIN), |
| __imm(bpf_ktime_get_ns) |
| : __clobber_all); |
| } |
| |
| SEC("socket") |
| __description("SMOD64, overflow (S64_MIN%-1), constant dividend") |
| __success __retval(0) __log_level(2) |
| __msg("r1 s%= -1 {{.*}}; R1=0") |
| __naked void smod64_overflow_2(void) |
| { |
| asm volatile (" \ |
| r1 = %[llong_min] ll; \ |
| r1 s%%= -1; \ |
| if r1 != 0 goto l0_%=; \ |
| r0 = 0; \ |
| exit; \ |
| l0_%=: r0 = *(u64 *)(r1 + 0); \ |
| exit; \ |
| " : |
| : __imm_const(llong_min, LLONG_MIN) |
| : __clobber_all); |
| } |