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