xref: /linux/tools/testing/selftests/bpf/verifier/atomic_fetch_add.c (revision da1d9caf95def6f0320819cf941c9fd1069ba9e1)
1 {
2 	"BPF_ATOMIC_FETCH_ADD smoketest - 64bit",
3 	.insns = {
4 		BPF_MOV64_IMM(BPF_REG_0, 0),
5 		/* Write 3 to stack */
6 		BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
7 		/* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */
8 		BPF_MOV64_IMM(BPF_REG_1, 1),
9 		BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8),
10 		/* Check the value we loaded back was 3 */
11 		BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
12 		BPF_MOV64_IMM(BPF_REG_0, 1),
13 		BPF_EXIT_INSN(),
14 		/* Load value from stack */
15 		BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8),
16 		/* Check value loaded from stack was 4 */
17 		BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
18 		BPF_MOV64_IMM(BPF_REG_0, 2),
19 		BPF_EXIT_INSN(),
20 	},
21 	.result = ACCEPT,
22 },
23 {
24 	"BPF_ATOMIC_FETCH_ADD smoketest - 32bit",
25 	.insns = {
26 		BPF_MOV64_IMM(BPF_REG_0, 0),
27 		/* Write 3 to stack */
28 		BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3),
29 		/* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */
30 		BPF_MOV32_IMM(BPF_REG_1, 1),
31 		BPF_ATOMIC_OP(BPF_W, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4),
32 		/* Check the value we loaded back was 3 */
33 		BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2),
34 		BPF_MOV64_IMM(BPF_REG_0, 1),
35 		BPF_EXIT_INSN(),
36 		/* Load value from stack */
37 		BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4),
38 		/* Check value loaded from stack was 4 */
39 		BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1),
40 		BPF_MOV64_IMM(BPF_REG_0, 2),
41 		BPF_EXIT_INSN(),
42 	},
43 	.result = ACCEPT,
44 },
45 {
46 	"Can't use ATM_FETCH_ADD on frame pointer",
47 	.insns = {
48 		BPF_MOV64_IMM(BPF_REG_0, 0),
49 		BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
50 		BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_10, -8),
51 		BPF_EXIT_INSN(),
52 	},
53 	.result = REJECT,
54 	.errstr_unpriv = "R10 leaks addr into mem",
55 	.errstr = "frame pointer is read only",
56 },
57 {
58 	"Can't use ATM_FETCH_ADD on uninit src reg",
59 	.insns = {
60 		BPF_MOV64_IMM(BPF_REG_0, 0),
61 		BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
62 		BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_2, -8),
63 		BPF_EXIT_INSN(),
64 	},
65 	.result = REJECT,
66 	/* It happens that the address leak check is first, but it would also be
67 	 * complain about the fact that we're trying to modify R10.
68 	 */
69 	.errstr = "!read_ok",
70 },
71 {
72 	"Can't use ATM_FETCH_ADD on uninit dst reg",
73 	.insns = {
74 		BPF_MOV64_IMM(BPF_REG_0, 0),
75 		BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_0, -8),
76 		BPF_EXIT_INSN(),
77 	},
78 	.result = REJECT,
79 	/* It happens that the address leak check is first, but it would also be
80 	 * complain about the fact that we're trying to modify R10.
81 	 */
82 	.errstr = "!read_ok",
83 },
84 {
85 	"Can't use ATM_FETCH_ADD on kernel memory",
86 	.insns = {
87 		/* This is an fentry prog, context is array of the args of the
88 		 * kernel function being called. Load first arg into R2.
89 		 */
90 		BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 0),
91 		/* First arg of bpf_fentry_test7 is a pointer to a struct.
92 		 * Attempt to modify that struct. Verifier shouldn't let us
93 		 * because it's kernel memory.
94 		 */
95 		BPF_MOV64_IMM(BPF_REG_3, 1),
96 		BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_3, 0),
97 		/* Done */
98 		BPF_MOV64_IMM(BPF_REG_0, 0),
99 		BPF_EXIT_INSN(),
100 	},
101 	.prog_type = BPF_PROG_TYPE_TRACING,
102 	.expected_attach_type = BPF_TRACE_FENTRY,
103 	.kfunc = "bpf_fentry_test7",
104 	.result = REJECT,
105 	.errstr = "only read is supported",
106 },
107