Skip to content

Commit f999d64

Browse files
ecree-solarflaredavem330
authored andcommitted
selftests/bpf: add tests for subtraction & negative numbers
Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1f9ab38 commit f999d64

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

tools/testing/selftests/bpf/test_align.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,110 @@ static struct bpf_align_test tests[] = {
497497
{16, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
498498
}
499499
},
500+
{
501+
.descr = "variable subtraction",
502+
.insns = {
503+
/* Create an unknown offset, (4n+2)-aligned */
504+
LOAD_UNKNOWN(BPF_REG_6),
505+
BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
506+
BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
507+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
508+
/* Create another unknown, (4n)-aligned, and subtract
509+
* it from the first one
510+
*/
511+
BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
512+
BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_7),
513+
/* Bounds-check the result */
514+
BPF_JMP_IMM(BPF_JSGE, BPF_REG_6, 0, 1),
515+
BPF_EXIT_INSN(),
516+
/* Add it to the packet pointer */
517+
BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
518+
BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
519+
/* Check bounds and perform a read */
520+
BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
521+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
522+
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
523+
BPF_EXIT_INSN(),
524+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
525+
BPF_EXIT_INSN(),
526+
},
527+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
528+
.matches = {
529+
/* Calculated offset in R6 has unknown value, but known
530+
* alignment of 4.
531+
*/
532+
{7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
533+
{9, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
534+
/* Adding 14 makes R6 be (4n+2) */
535+
{10, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},
536+
/* New unknown value in R7 is (4n) */
537+
{11, "R7=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},
538+
/* Subtracting it from R6 blows our unsigned bounds */
539+
{12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,var_off=(0x2; 0xfffffffffffffffc))"},
540+
/* Checked s>= 0 */
541+
{14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
542+
/* At the time the word size load is performed from R5,
543+
* its total fixed offset is NET_IP_ALIGN + reg->off (0)
544+
* which is 2. Then the variable offset is (4n+2), so
545+
* the total offset is 4-byte aligned and meets the
546+
* load's requirements.
547+
*/
548+
{20, "R5=pkt(id=1,off=0,r=4,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},
549+
},
550+
},
551+
{
552+
.descr = "pointer variable subtraction",
553+
.insns = {
554+
/* Create an unknown offset, (4n+2)-aligned and bounded
555+
* to [14,74]
556+
*/
557+
LOAD_UNKNOWN(BPF_REG_6),
558+
BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),
559+
BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xf),
560+
BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
561+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),
562+
/* Subtract it from the packet pointer */
563+
BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
564+
BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_6),
565+
/* Create another unknown, (4n)-aligned and >= 74.
566+
* That in fact means >= 76, since 74 % 4 == 2
567+
*/
568+
BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),
569+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 76),
570+
/* Add it to the packet pointer */
571+
BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_7),
572+
/* Check bounds and perform a read */
573+
BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
574+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
575+
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
576+
BPF_EXIT_INSN(),
577+
BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),
578+
BPF_EXIT_INSN(),
579+
},
580+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
581+
.matches = {
582+
/* Calculated offset in R6 has unknown value, but known
583+
* alignment of 4.
584+
*/
585+
{7, "R2=pkt(id=0,off=0,r=8,imm=0)"},
586+
{10, "R6=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},
587+
/* Adding 14 makes R6 be (4n+2) */
588+
{11, "R6=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},
589+
/* Subtracting from packet pointer overflows ubounds */
590+
{13, "R5=pkt(id=1,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c))"},
591+
/* New unknown value in R7 is (4n), >= 76 */
592+
{15, "R7=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},
593+
/* Adding it to packet pointer gives nice bounds again */
594+
{16, "R5=pkt(id=2,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
595+
/* At the time the word size load is performed from R5,
596+
* its total fixed offset is NET_IP_ALIGN + reg->off (0)
597+
* which is 2. Then the variable offset is (4n+2), so
598+
* the total offset is 4-byte aligned and meets the
599+
* load's requirements.
600+
*/
601+
{20, "R5=pkt(id=2,off=0,r=4,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},
602+
},
603+
},
500604
};
501605

502606
static int probe_filter_length(const struct bpf_insn *fp)

0 commit comments

Comments
 (0)