Skip to content

Commit c2c3e11

Browse files
ecree-solarflaredavem330
authored andcommitted
selftests/bpf: add test for bogus operations on pointers
Tests non-add/sub operations (AND, LSH) on pointers decaying them to unknown scalars. Also tests that a pkt_ptr add which could potentially overflow is rejected (find_good_pkt_pointers ignores it and doesn't give us any reg->range). Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 715dddb commit c2c3e11

File tree

1 file changed

+64
-2
lines changed

1 file changed

+64
-2
lines changed

tools/testing/selftests/bpf/test_align.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,62 @@ static struct bpf_align_test tests[] = {
441441
{23, "R5=pkt(id=2,off=0,r=4,umin_value=14,umax_value=2054,var_off=(0x2; 0xffc))"},
442442
},
443443
},
444+
{
445+
.descr = "dubious pointer arithmetic",
446+
.insns = {
447+
PREP_PKT_POINTERS,
448+
BPF_MOV64_IMM(BPF_REG_0, 0),
449+
/* ptr & const => unknown & const */
450+
BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
451+
BPF_ALU64_IMM(BPF_AND, BPF_REG_5, 0x40),
452+
/* ptr << const => unknown << const */
453+
BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
454+
BPF_ALU64_IMM(BPF_LSH, BPF_REG_5, 2),
455+
/* We have a (4n) value. Let's make a packet offset
456+
* out of it. First add 14, to make it a (4n+2)
457+
*/
458+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
459+
/* Then make sure it's nonnegative */
460+
BPF_JMP_IMM(BPF_JSGE, BPF_REG_5, 0, 1),
461+
BPF_EXIT_INSN(),
462+
/* Add it to packet pointer */
463+
BPF_MOV64_REG(BPF_REG_6, BPF_REG_2),
464+
BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_5),
465+
/* Check bounds and perform a read */
466+
BPF_MOV64_REG(BPF_REG_4, BPF_REG_6),
467+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
468+
BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
469+
BPF_EXIT_INSN(),
470+
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_6, 0),
471+
BPF_EXIT_INSN(),
472+
},
473+
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
474+
.result = REJECT,
475+
.matches = {
476+
{4, "R5=pkt(id=0,off=0,r=0,imm=0)"},
477+
/* ptr & 0x40 == either 0 or 0x40 */
478+
{5, "R5=inv(id=0,umax_value=64,var_off=(0x0; 0x40))"},
479+
/* ptr << 2 == unknown, (4n) */
480+
{7, "R5=inv(id=0,smax_value=9223372036854775804,umax_value=18446744073709551612,var_off=(0x0; 0xfffffffffffffffc))"},
481+
/* (4n) + 14 == (4n+2). We blow our bounds, because
482+
* the add could overflow.
483+
*/
484+
{8, "R5=inv(id=0,var_off=(0x2; 0xfffffffffffffffc))"},
485+
/* Checked s>=0 */
486+
{10, "R5=inv(id=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
487+
/* packet pointer + nonnegative (4n+2) */
488+
{12, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
489+
{14, "R4=pkt(id=1,off=4,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
490+
/* NET_IP_ALIGN + (4n+2) == (4n), alignment is fine.
491+
* We checked the bounds, but it might have been able
492+
* to overflow if the packet pointer started in the
493+
* upper half of the address space.
494+
* So we did not get a 'range' on R6, and the access
495+
* attempt will fail.
496+
*/
497+
{16, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},
498+
}
499+
},
444500
};
445501

446502
static int probe_filter_length(const struct bpf_insn *fp)
@@ -470,10 +526,15 @@ static int do_test_single(struct bpf_align_test *test)
470526
fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
471527
prog, prog_len, 1, "GPL", 0,
472528
bpf_vlog, sizeof(bpf_vlog), 2);
473-
if (fd_prog < 0) {
529+
if (fd_prog < 0 && test->result != REJECT) {
474530
printf("Failed to load program.\n");
475531
printf("%s", bpf_vlog);
476532
ret = 1;
533+
} else if (fd_prog >= 0 && test->result == REJECT) {
534+
printf("Unexpected success to load!\n");
535+
printf("%s", bpf_vlog);
536+
ret = 1;
537+
close(fd_prog);
477538
} else {
478539
ret = 0;
479540
/* We make a local copy so that we can strtok() it */
@@ -506,7 +567,8 @@ static int do_test_single(struct bpf_align_test *test)
506567
break;
507568
}
508569
}
509-
close(fd_prog);
570+
if (fd_prog >= 0)
571+
close(fd_prog);
510572
}
511573
return ret;
512574
}

0 commit comments

Comments
 (0)