2021-01-14 18:17:50 +00:00
|
|
|
{
|
|
|
|
"atomic compare-and-exchange smoketest - 64bit",
|
|
|
|
.insns = {
|
|
|
|
/* val = 3; */
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
|
|
|
|
/* old = atomic_cmpxchg(&val, 2, 4); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 2),
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
/* if (old != 3) exit(2); */
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* if (val != 3) exit(3); */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 3),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* old = atomic_cmpxchg(&val, 3, 4); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 4),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 3),
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
/* if (old != 3) exit(4); */
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 4),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* if (val != 4) exit(5); */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 5),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"atomic compare-and-exchange smoketest - 32bit",
|
|
|
|
.insns = {
|
|
|
|
/* val = 3; */
|
|
|
|
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3),
|
|
|
|
/* old = atomic_cmpxchg(&val, 2, 4); */
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 4),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 2),
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4),
|
|
|
|
/* if (old != 3) exit(2); */
|
|
|
|
BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 2),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* if (val != 3) exit(3); */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
|
|
|
|
BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 3),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* old = atomic_cmpxchg(&val, 3, 4); */
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 4),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 3),
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4),
|
|
|
|
/* if (old != 3) exit(4); */
|
|
|
|
BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 4),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* if (val != 4) exit(5); */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
|
|
|
|
BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 4, 2),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 5),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Can't use cmpxchg on uninit src reg",
|
|
|
|
.insns = {
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 3),
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_2, -8),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "!read_ok",
|
|
|
|
},
|
2021-03-04 18:56:46 -08:00
|
|
|
{
|
|
|
|
"BPF_W cmpxchg should zero top 32 bits",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = U64_MAX; */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1),
|
|
|
|
/* u64 val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r0 = (u32)atomic_cmpxchg((u32 *)&val, r0, 1); */
|
|
|
|
BPF_MOV32_IMM(BPF_REG_1, 1),
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
/* r1 = 0x00000000FFFFFFFFull; */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 1),
|
|
|
|
BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
|
|
|
|
BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
|
|
|
|
/* if (r0 != r1) exit(1); */
|
|
|
|
BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_1, 2),
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV32_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
},
|
2021-10-15 09:33:18 +00:00
|
|
|
{
|
|
|
|
"Dest pointer in r0 - fail",
|
|
|
|
.insns = {
|
|
|
|
/* val = 0; */
|
|
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, 1); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 1),
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
/* if (r0 != 0) exit(1); */
|
|
|
|
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 1),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
bpf, selftests: Update test case for atomic cmpxchg on r0 with pointer
Fix up unprivileged test case results for 'Dest pointer in r0' verifier tests
given they now need to reject R0 containing a pointer value, and add a couple
of new related ones with 32bit cmpxchg as well.
root@foo:~/bpf/tools/testing/selftests/bpf# ./test_verifier
#0/u invalid and of negative number OK
#0/p invalid and of negative number OK
[...]
#1268/p XDP pkt read, pkt_meta' <= pkt_data, bad access 1 OK
#1269/p XDP pkt read, pkt_meta' <= pkt_data, bad access 2 OK
#1270/p XDP pkt read, pkt_data <= pkt_meta', good access OK
#1271/p XDP pkt read, pkt_data <= pkt_meta', bad access 1 OK
#1272/p XDP pkt read, pkt_data <= pkt_meta', bad access 2 OK
Summary: 1900 PASSED, 0 SKIPPED, 0 FAILED
Acked-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-12-13 22:25:23 +00:00
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R0 leaks addr into mem",
|
2021-10-15 09:33:18 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"Dest pointer in r0 - succeed",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, 0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_1, 0),
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
|
|
|
|
/* r1 = *r0 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
bpf, selftests: Add test case for atomic fetch on spilled pointer
Test whether unprivileged would be able to leak the spilled pointer either
by exporting the returned value from the atomic{32,64} operation or by reading
and exporting the value from the stack after the atomic operation took place.
Note that for unprivileged, the below atomic cmpxchg test case named "Dest
pointer in r0 - succeed" is failing. The reason is that in the dst memory
location (r10 -8) there is the spilled register r10:
0: R1=ctx(id=0,off=0,imm=0) R10=fp0
0: (bf) r0 = r10
1: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0
1: (7b) *(u64 *)(r10 -8) = r0
2: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0 fp-8_w=fp
2: (b7) r1 = 0
3: R0_w=fp0 R1_w=invP0 R10=fp0 fp-8_w=fp
3: (db) r0 = atomic64_cmpxchg((u64 *)(r10 -8), r0, r1)
4: R0_w=fp0 R1_w=invP0 R10=fp0 fp-8_w=mmmmmmmm
4: (79) r1 = *(u64 *)(r0 -8)
5: R0_w=fp0 R1_w=invP(id=0) R10=fp0 fp-8_w=mmmmmmmm
5: (b7) r0 = 0
6: R0_w=invP0 R1_w=invP(id=0) R10=fp0 fp-8_w=mmmmmmmm
6: (95) exit
However, allowing this case for unprivileged is a bit useless given an
update with a new pointer will fail anyway:
0: R1=ctx(id=0,off=0,imm=0) R10=fp0
0: (bf) r0 = r10
1: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0
1: (7b) *(u64 *)(r10 -8) = r0
2: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0 fp-8_w=fp
2: (db) r0 = atomic64_cmpxchg((u64 *)(r10 -8), r0, r10)
R10 leaks addr into mem
Acked-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-12-07 10:07:04 +00:00
|
|
|
.result_unpriv = REJECT,
|
bpf, selftests: Update test case for atomic cmpxchg on r0 with pointer
Fix up unprivileged test case results for 'Dest pointer in r0' verifier tests
given they now need to reject R0 containing a pointer value, and add a couple
of new related ones with 32bit cmpxchg as well.
root@foo:~/bpf/tools/testing/selftests/bpf# ./test_verifier
#0/u invalid and of negative number OK
#0/p invalid and of negative number OK
[...]
#1268/p XDP pkt read, pkt_meta' <= pkt_data, bad access 1 OK
#1269/p XDP pkt read, pkt_meta' <= pkt_data, bad access 2 OK
#1270/p XDP pkt read, pkt_data <= pkt_meta', good access OK
#1271/p XDP pkt read, pkt_data <= pkt_meta', bad access 1 OK
#1272/p XDP pkt read, pkt_data <= pkt_meta', bad access 2 OK
Summary: 1900 PASSED, 0 SKIPPED, 0 FAILED
Acked-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-12-13 22:25:23 +00:00
|
|
|
.errstr_unpriv = "R0 leaks addr into mem",
|
bpf, selftests: Add test case for atomic fetch on spilled pointer
Test whether unprivileged would be able to leak the spilled pointer either
by exporting the returned value from the atomic{32,64} operation or by reading
and exporting the value from the stack after the atomic operation took place.
Note that for unprivileged, the below atomic cmpxchg test case named "Dest
pointer in r0 - succeed" is failing. The reason is that in the dst memory
location (r10 -8) there is the spilled register r10:
0: R1=ctx(id=0,off=0,imm=0) R10=fp0
0: (bf) r0 = r10
1: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0
1: (7b) *(u64 *)(r10 -8) = r0
2: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0 fp-8_w=fp
2: (b7) r1 = 0
3: R0_w=fp0 R1_w=invP0 R10=fp0 fp-8_w=fp
3: (db) r0 = atomic64_cmpxchg((u64 *)(r10 -8), r0, r1)
4: R0_w=fp0 R1_w=invP0 R10=fp0 fp-8_w=mmmmmmmm
4: (79) r1 = *(u64 *)(r0 -8)
5: R0_w=fp0 R1_w=invP(id=0) R10=fp0 fp-8_w=mmmmmmmm
5: (b7) r0 = 0
6: R0_w=invP0 R1_w=invP(id=0) R10=fp0 fp-8_w=mmmmmmmm
6: (95) exit
However, allowing this case for unprivileged is a bit useless given an
update with a new pointer will fail anyway:
0: R1=ctx(id=0,off=0,imm=0) R10=fp0
0: (bf) r0 = r10
1: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0
1: (7b) *(u64 *)(r10 -8) = r0
2: R0_w=fp0 R1=ctx(id=0,off=0,imm=0) R10=fp0 fp-8_w=fp
2: (db) r0 = atomic64_cmpxchg((u64 *)(r10 -8), r0, r10)
R10 leaks addr into mem
Acked-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-12-07 10:07:04 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"Dest pointer in r0 - succeed, check 2",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r5 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, r5); */
|
|
|
|
BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
|
|
|
|
/* r1 = *r0 */
|
|
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
bpf, selftests: Update test case for atomic cmpxchg on r0 with pointer
Fix up unprivileged test case results for 'Dest pointer in r0' verifier tests
given they now need to reject R0 containing a pointer value, and add a couple
of new related ones with 32bit cmpxchg as well.
root@foo:~/bpf/tools/testing/selftests/bpf# ./test_verifier
#0/u invalid and of negative number OK
#0/p invalid and of negative number OK
[...]
#1268/p XDP pkt read, pkt_meta' <= pkt_data, bad access 1 OK
#1269/p XDP pkt read, pkt_meta' <= pkt_data, bad access 2 OK
#1270/p XDP pkt read, pkt_data <= pkt_meta', good access OK
#1271/p XDP pkt read, pkt_data <= pkt_meta', bad access 1 OK
#1272/p XDP pkt read, pkt_data <= pkt_meta', bad access 2 OK
Summary: 1900 PASSED, 0 SKIPPED, 0 FAILED
Acked-by: Brendan Jackman <jackmanb@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2021-12-13 22:25:23 +00:00
|
|
|
.errstr_unpriv = "R0 leaks addr into mem",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Dest pointer in r0 - succeed, check 3",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r5 = &val */
|
|
|
|
BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, r5); */
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "invalid size of register fill",
|
|
|
|
.errstr_unpriv = "R0 leaks addr into mem",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Dest pointer in r0 - succeed, check 4",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV32_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r5 = &val */
|
|
|
|
BPF_MOV32_REG(BPF_REG_5, BPF_REG_10),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, r5); */
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
|
|
|
|
/* r1 = *r10 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -8),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = ACCEPT,
|
|
|
|
.result_unpriv = REJECT,
|
|
|
|
.errstr_unpriv = "R10 partial copy of pointer",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Dest pointer in r0 - succeed, check 5",
|
|
|
|
.insns = {
|
|
|
|
/* r0 = &val */
|
|
|
|
BPF_MOV32_REG(BPF_REG_0, BPF_REG_10),
|
|
|
|
/* val = r0; */
|
|
|
|
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8),
|
|
|
|
/* r5 = &val */
|
|
|
|
BPF_MOV32_REG(BPF_REG_5, BPF_REG_10),
|
|
|
|
/* r0 = atomic_cmpxchg(&val, r0, r5); */
|
|
|
|
BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
|
|
|
|
/* r1 = *r0 */
|
|
|
|
BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -8),
|
|
|
|
/* exit(0); */
|
|
|
|
BPF_MOV64_IMM(BPF_REG_0, 0),
|
|
|
|
BPF_EXIT_INSN(),
|
|
|
|
},
|
|
|
|
.result = REJECT,
|
|
|
|
.errstr = "R0 invalid mem access",
|
|
|
|
.errstr_unpriv = "R10 partial copy of pointer",
|
2023-07-05 13:39:25 +02:00
|
|
|
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
|
2021-10-15 09:33:18 +00:00
|
|
|
},
|