xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/bpf/verifier/bounds.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun {
2*4882a593Smuzhiyun 	"subtraction bounds (map value) variant 1",
3*4882a593Smuzhiyun 	.insns = {
4*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
5*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
8*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
9*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
10*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
11*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7),
12*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
13*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5),
14*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
15*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56),
16*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
17*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
18*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
19*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
20*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
21*4882a593Smuzhiyun 	},
22*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
23*4882a593Smuzhiyun 	.errstr = "R0 max value is outside of the allowed memory range",
24*4882a593Smuzhiyun 	.result = REJECT,
25*4882a593Smuzhiyun },
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	"subtraction bounds (map value) variant 2",
28*4882a593Smuzhiyun 	.insns = {
29*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
30*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
31*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
32*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
33*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
34*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
35*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
36*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
37*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
38*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
39*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
40*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
41*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
42*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
43*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
44*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
45*4882a593Smuzhiyun 	},
46*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
47*4882a593Smuzhiyun 	.errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
48*4882a593Smuzhiyun 	.errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
49*4882a593Smuzhiyun 	.result = REJECT,
50*4882a593Smuzhiyun },
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	"check subtraction on pointers for unpriv",
53*4882a593Smuzhiyun 	.insns = {
54*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
55*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
56*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
57*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
58*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 9),
59*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
60*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP),
61*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0),
62*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
63*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
64*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
65*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 0),
66*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
67*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
68*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
69*4882a593Smuzhiyun 	BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0),
70*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
71*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
72*4882a593Smuzhiyun 	},
73*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 1, 9 },
74*4882a593Smuzhiyun 	.result = ACCEPT,
75*4882a593Smuzhiyun 	.result_unpriv = REJECT,
76*4882a593Smuzhiyun 	.errstr_unpriv = "R9 pointer -= pointer prohibited",
77*4882a593Smuzhiyun },
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	"bounds check based on zero-extended MOV",
80*4882a593Smuzhiyun 	.insns = {
81*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
82*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
83*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
84*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
85*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
86*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
87*4882a593Smuzhiyun 	/* r2 = 0x0000'0000'ffff'ffff */
88*4882a593Smuzhiyun 	BPF_MOV32_IMM(BPF_REG_2, 0xffffffff),
89*4882a593Smuzhiyun 	/* r2 = 0 */
90*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
91*4882a593Smuzhiyun 	/* no-op */
92*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
93*4882a593Smuzhiyun 	/* access at offset 0 */
94*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
95*4882a593Smuzhiyun 	/* exit */
96*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
97*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
98*4882a593Smuzhiyun 	},
99*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
100*4882a593Smuzhiyun 	.result = ACCEPT
101*4882a593Smuzhiyun },
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	"bounds check based on sign-extended MOV. test1",
104*4882a593Smuzhiyun 	.insns = {
105*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
106*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
107*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
108*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
109*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
110*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
111*4882a593Smuzhiyun 	/* r2 = 0xffff'ffff'ffff'ffff */
112*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
113*4882a593Smuzhiyun 	/* r2 = 0xffff'ffff */
114*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
115*4882a593Smuzhiyun 	/* r0 = <oob pointer> */
116*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
117*4882a593Smuzhiyun 	/* access to OOB pointer */
118*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
119*4882a593Smuzhiyun 	/* exit */
120*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
121*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
122*4882a593Smuzhiyun 	},
123*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
124*4882a593Smuzhiyun 	.errstr = "map_value pointer and 4294967295",
125*4882a593Smuzhiyun 	.result = REJECT
126*4882a593Smuzhiyun },
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	"bounds check based on sign-extended MOV. test2",
129*4882a593Smuzhiyun 	.insns = {
130*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
131*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
132*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
133*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
134*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
135*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
136*4882a593Smuzhiyun 	/* r2 = 0xffff'ffff'ffff'ffff */
137*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
138*4882a593Smuzhiyun 	/* r2 = 0xfff'ffff */
139*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 36),
140*4882a593Smuzhiyun 	/* r0 = <oob pointer> */
141*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
142*4882a593Smuzhiyun 	/* access to OOB pointer */
143*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
144*4882a593Smuzhiyun 	/* exit */
145*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
146*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
147*4882a593Smuzhiyun 	},
148*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
149*4882a593Smuzhiyun 	.errstr = "R0 min value is outside of the allowed memory range",
150*4882a593Smuzhiyun 	.result = REJECT
151*4882a593Smuzhiyun },
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	"bounds check based on reg_off + var_off + insn_off. test1",
154*4882a593Smuzhiyun 	.insns = {
155*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
156*4882a593Smuzhiyun 		    offsetof(struct __sk_buff, mark)),
157*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
158*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
159*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
160*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
161*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
162*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
163*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
164*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 29) - 1),
165*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
166*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
167*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
168*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
169*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
170*4882a593Smuzhiyun 	},
171*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 4 },
172*4882a593Smuzhiyun 	.errstr = "value_size=8 off=1073741825",
173*4882a593Smuzhiyun 	.result = REJECT,
174*4882a593Smuzhiyun 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
175*4882a593Smuzhiyun },
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	"bounds check based on reg_off + var_off + insn_off. test2",
178*4882a593Smuzhiyun 	.insns = {
179*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
180*4882a593Smuzhiyun 		    offsetof(struct __sk_buff, mark)),
181*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
182*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
183*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
184*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
185*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
186*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
187*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
188*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 30) - 1),
189*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
190*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
191*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
192*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
193*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
194*4882a593Smuzhiyun 	},
195*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 4 },
196*4882a593Smuzhiyun 	.errstr = "value 1073741823",
197*4882a593Smuzhiyun 	.result = REJECT,
198*4882a593Smuzhiyun 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
199*4882a593Smuzhiyun },
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	"bounds check after truncation of non-boundary-crossing range",
202*4882a593Smuzhiyun 	.insns = {
203*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
204*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
205*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
206*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
207*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
208*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
209*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] */
210*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
211*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_2, 1),
212*4882a593Smuzhiyun 	/* r2 = 0x10'0000'0000 */
213*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 36),
214*4882a593Smuzhiyun 	/* r1 = [0x10'0000'0000, 0x10'0000'00ff] */
215*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
216*4882a593Smuzhiyun 	/* r1 = [0x10'7fff'ffff, 0x10'8000'00fe] */
217*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
218*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] */
219*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 0x7fffffff),
220*4882a593Smuzhiyun 	/* r1 = 0 */
221*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
222*4882a593Smuzhiyun 	/* no-op */
223*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
224*4882a593Smuzhiyun 	/* access at offset 0 */
225*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
226*4882a593Smuzhiyun 	/* exit */
227*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
228*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
229*4882a593Smuzhiyun 	},
230*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
231*4882a593Smuzhiyun 	.result = ACCEPT
232*4882a593Smuzhiyun },
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	"bounds check after truncation of boundary-crossing range (1)",
235*4882a593Smuzhiyun 	.insns = {
236*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
237*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
238*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
239*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
240*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
241*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
242*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] */
243*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
244*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
245*4882a593Smuzhiyun 	/* r1 = [0xffff'ff80, 0x1'0000'007f] */
246*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
247*4882a593Smuzhiyun 	/* r1 = [0xffff'ff80, 0xffff'ffff] or
248*4882a593Smuzhiyun 	 *      [0x0000'0000, 0x0000'007f]
249*4882a593Smuzhiyun 	 */
250*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 0),
251*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
252*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] or
253*4882a593Smuzhiyun 	 *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
254*4882a593Smuzhiyun 	 */
255*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
256*4882a593Smuzhiyun 	/* error on OOB pointer computation */
257*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
258*4882a593Smuzhiyun 	/* exit */
259*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
260*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
261*4882a593Smuzhiyun 	},
262*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
263*4882a593Smuzhiyun 	/* not actually fully unbounded, but the bound is very high */
264*4882a593Smuzhiyun 	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
265*4882a593Smuzhiyun 	.result = REJECT,
266*4882a593Smuzhiyun },
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	"bounds check after truncation of boundary-crossing range (2)",
269*4882a593Smuzhiyun 	.insns = {
270*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
271*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
272*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
273*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
274*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
275*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
276*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] */
277*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
278*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
279*4882a593Smuzhiyun 	/* r1 = [0xffff'ff80, 0x1'0000'007f] */
280*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
281*4882a593Smuzhiyun 	/* r1 = [0xffff'ff80, 0xffff'ffff] or
282*4882a593Smuzhiyun 	 *      [0x0000'0000, 0x0000'007f]
283*4882a593Smuzhiyun 	 * difference to previous test: truncation via MOV32
284*4882a593Smuzhiyun 	 * instead of ALU32.
285*4882a593Smuzhiyun 	 */
286*4882a593Smuzhiyun 	BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
287*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
288*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] or
289*4882a593Smuzhiyun 	 *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
290*4882a593Smuzhiyun 	 */
291*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
292*4882a593Smuzhiyun 	/* error on OOB pointer computation */
293*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
294*4882a593Smuzhiyun 	/* exit */
295*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
296*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
297*4882a593Smuzhiyun 	},
298*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
299*4882a593Smuzhiyun 	.errstr = "value -4294967168 makes map_value pointer be out of bounds",
300*4882a593Smuzhiyun 	.result = REJECT,
301*4882a593Smuzhiyun },
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	"bounds check after wrapping 32-bit addition",
304*4882a593Smuzhiyun 	.insns = {
305*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
306*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
307*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
308*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
309*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
310*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
311*4882a593Smuzhiyun 	/* r1 = 0x7fff'ffff */
312*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
313*4882a593Smuzhiyun 	/* r1 = 0xffff'fffe */
314*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
315*4882a593Smuzhiyun 	/* r1 = 0 */
316*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
317*4882a593Smuzhiyun 	/* no-op */
318*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
319*4882a593Smuzhiyun 	/* access at offset 0 */
320*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
321*4882a593Smuzhiyun 	/* exit */
322*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
323*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
324*4882a593Smuzhiyun 	},
325*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
326*4882a593Smuzhiyun 	.result = ACCEPT
327*4882a593Smuzhiyun },
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	"bounds check after shift with oversized count operand",
330*4882a593Smuzhiyun 	.insns = {
331*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
332*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
333*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
334*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
335*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
336*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
337*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_2, 32),
338*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 1),
339*4882a593Smuzhiyun 	/* r1 = (u32)1 << (u32)32 = ? */
340*4882a593Smuzhiyun 	BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
341*4882a593Smuzhiyun 	/* r1 = [0x0000, 0xffff] */
342*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
343*4882a593Smuzhiyun 	/* computes unknown pointer, potentially OOB */
344*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
345*4882a593Smuzhiyun 	/* potentially OOB access */
346*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
347*4882a593Smuzhiyun 	/* exit */
348*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
349*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
350*4882a593Smuzhiyun 	},
351*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
352*4882a593Smuzhiyun 	.errstr = "R0 max value is outside of the allowed memory range",
353*4882a593Smuzhiyun 	.result = REJECT
354*4882a593Smuzhiyun },
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun 	"bounds check after right shift of maybe-negative number",
357*4882a593Smuzhiyun 	.insns = {
358*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
359*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
360*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
361*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
362*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
363*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
364*4882a593Smuzhiyun 	/* r1 = [0x00, 0xff] */
365*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
366*4882a593Smuzhiyun 	/* r1 = [-0x01, 0xfe] */
367*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
368*4882a593Smuzhiyun 	/* r1 = 0 or 0xff'ffff'ffff'ffff */
369*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
370*4882a593Smuzhiyun 	/* r1 = 0 or 0xffff'ffff'ffff */
371*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
372*4882a593Smuzhiyun 	/* computes unknown pointer, potentially OOB */
373*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
374*4882a593Smuzhiyun 	/* potentially OOB access */
375*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
376*4882a593Smuzhiyun 	/* exit */
377*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
378*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
379*4882a593Smuzhiyun 	},
380*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
381*4882a593Smuzhiyun 	.errstr = "R0 unbounded memory access",
382*4882a593Smuzhiyun 	.result = REJECT
383*4882a593Smuzhiyun },
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	"bounds check after 32-bit right shift with 64-bit input",
386*4882a593Smuzhiyun 	.insns = {
387*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
388*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
389*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
390*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
391*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
392*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
393*4882a593Smuzhiyun 	/* r1 = 2 */
394*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 2),
395*4882a593Smuzhiyun 	/* r1 = 1<<32 */
396*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
397*4882a593Smuzhiyun 	/* r1 = 0 (NOT 2!) */
398*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
399*4882a593Smuzhiyun 	/* r1 = 0xffff'fffe (NOT 0!) */
400*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
401*4882a593Smuzhiyun 	/* error on computing OOB pointer */
402*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
403*4882a593Smuzhiyun 	/* exit */
404*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
405*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
406*4882a593Smuzhiyun 	},
407*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
408*4882a593Smuzhiyun 	.errstr = "math between map_value pointer and 4294967294 is not allowed",
409*4882a593Smuzhiyun 	.result = REJECT,
410*4882a593Smuzhiyun },
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	"bounds check map access with off+size signed 32bit overflow. test1",
413*4882a593Smuzhiyun 	.insns = {
414*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
415*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
416*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
417*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
418*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
419*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
420*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
421*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
422*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
423*4882a593Smuzhiyun 	BPF_JMP_A(0),
424*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
425*4882a593Smuzhiyun 	},
426*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
427*4882a593Smuzhiyun 	.errstr = "map_value pointer and 2147483646",
428*4882a593Smuzhiyun 	.result = REJECT
429*4882a593Smuzhiyun },
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun 	"bounds check map access with off+size signed 32bit overflow. test2",
432*4882a593Smuzhiyun 	.insns = {
433*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
434*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
435*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
436*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
437*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
438*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
439*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
440*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
441*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
442*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
443*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
444*4882a593Smuzhiyun 	BPF_JMP_A(0),
445*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
446*4882a593Smuzhiyun 	},
447*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
448*4882a593Smuzhiyun 	.errstr = "pointer offset 1073741822",
449*4882a593Smuzhiyun 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
450*4882a593Smuzhiyun 	.result = REJECT
451*4882a593Smuzhiyun },
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun 	"bounds check map access with off+size signed 32bit overflow. test3",
454*4882a593Smuzhiyun 	.insns = {
455*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
456*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
457*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
458*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
459*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
460*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
461*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
462*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
463*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
464*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
465*4882a593Smuzhiyun 	BPF_JMP_A(0),
466*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
467*4882a593Smuzhiyun 	},
468*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
469*4882a593Smuzhiyun 	.errstr = "pointer offset -1073741822",
470*4882a593Smuzhiyun 	.errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
471*4882a593Smuzhiyun 	.result = REJECT
472*4882a593Smuzhiyun },
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun 	"bounds check map access with off+size signed 32bit overflow. test4",
475*4882a593Smuzhiyun 	.insns = {
476*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
477*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
478*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
479*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
480*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
481*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
482*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
483*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 1000000),
484*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
485*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
486*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
487*4882a593Smuzhiyun 	BPF_JMP_A(0),
488*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
489*4882a593Smuzhiyun 	},
490*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
491*4882a593Smuzhiyun 	.errstr = "map_value pointer and 1000000000000",
492*4882a593Smuzhiyun 	.result = REJECT
493*4882a593Smuzhiyun },
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	"bounds check mixed 32bit and 64bit arithmetic. test1",
496*4882a593Smuzhiyun 	.insns = {
497*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
498*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, -1),
499*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
500*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
501*4882a593Smuzhiyun 	/* r1 = 0xffffFFFF00000001 */
502*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
503*4882a593Smuzhiyun 	/* check ALU64 op keeps 32bit bounds */
504*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
505*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
506*4882a593Smuzhiyun 	BPF_JMP_A(1),
507*4882a593Smuzhiyun 	/* invalid ldx if bounds are lost above */
508*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
509*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
510*4882a593Smuzhiyun 	},
511*4882a593Smuzhiyun 	.errstr_unpriv = "R0 invalid mem access 'inv'",
512*4882a593Smuzhiyun 	.result_unpriv = REJECT,
513*4882a593Smuzhiyun 	.result = ACCEPT
514*4882a593Smuzhiyun },
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun 	"bounds check mixed 32bit and 64bit arithmetic. test2",
517*4882a593Smuzhiyun 	.insns = {
518*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
519*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, -1),
520*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
521*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
522*4882a593Smuzhiyun 	/* r1 = 0xffffFFFF00000001 */
523*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_2, 3),
524*4882a593Smuzhiyun 	/* r1 = 0x2 */
525*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
526*4882a593Smuzhiyun 	/* check ALU32 op zero extends 64bit bounds */
527*4882a593Smuzhiyun 	BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
528*4882a593Smuzhiyun 	BPF_JMP_A(1),
529*4882a593Smuzhiyun 	/* invalid ldx if bounds are lost above */
530*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
531*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
532*4882a593Smuzhiyun 	},
533*4882a593Smuzhiyun 	.errstr_unpriv = "R0 invalid mem access 'inv'",
534*4882a593Smuzhiyun 	.result_unpriv = REJECT,
535*4882a593Smuzhiyun 	.result = ACCEPT
536*4882a593Smuzhiyun },
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun 	"assigning 32bit bounds to 64bit for wA = 0, wB = wA",
539*4882a593Smuzhiyun 	.insns = {
540*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
541*4882a593Smuzhiyun 		    offsetof(struct __sk_buff, data_end)),
542*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
543*4882a593Smuzhiyun 		    offsetof(struct __sk_buff, data)),
544*4882a593Smuzhiyun 	BPF_MOV32_IMM(BPF_REG_9, 0),
545*4882a593Smuzhiyun 	BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
546*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
547*4882a593Smuzhiyun 	BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
548*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
549*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
550*4882a593Smuzhiyun 	BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
551*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
552*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
553*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
554*4882a593Smuzhiyun 	},
555*4882a593Smuzhiyun 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
556*4882a593Smuzhiyun 	.result = ACCEPT,
557*4882a593Smuzhiyun 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
558*4882a593Smuzhiyun },
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	"bounds check for reg = 0, reg xor 1",
561*4882a593Smuzhiyun 	.insns = {
562*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
563*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
564*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
565*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
566*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
567*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
568*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
569*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 0),
570*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 1),
571*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
572*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
573*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
574*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
575*4882a593Smuzhiyun 	},
576*4882a593Smuzhiyun 	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
577*4882a593Smuzhiyun 	.result_unpriv = REJECT,
578*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
579*4882a593Smuzhiyun 	.result = ACCEPT,
580*4882a593Smuzhiyun },
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun 	"bounds check for reg32 = 0, reg32 xor 1",
583*4882a593Smuzhiyun 	.insns = {
584*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
585*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
586*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
587*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
588*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
589*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
590*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
591*4882a593Smuzhiyun 	BPF_MOV32_IMM(BPF_REG_1, 0),
592*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 1),
593*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
594*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
595*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
596*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
597*4882a593Smuzhiyun 	},
598*4882a593Smuzhiyun 	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
599*4882a593Smuzhiyun 	.result_unpriv = REJECT,
600*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
601*4882a593Smuzhiyun 	.result = ACCEPT,
602*4882a593Smuzhiyun },
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	"bounds check for reg = 2, reg xor 3",
605*4882a593Smuzhiyun 	.insns = {
606*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
607*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
608*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
609*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
610*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
611*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
612*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
613*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_1, 2),
614*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
615*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0, 1),
616*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
617*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
618*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
619*4882a593Smuzhiyun 	},
620*4882a593Smuzhiyun 	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
621*4882a593Smuzhiyun 	.result_unpriv = REJECT,
622*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
623*4882a593Smuzhiyun 	.result = ACCEPT,
624*4882a593Smuzhiyun },
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	"bounds check for reg = any, reg xor 3",
627*4882a593Smuzhiyun 	.insns = {
628*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
629*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
630*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
631*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
632*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
633*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
634*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
635*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
636*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
637*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
638*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
639*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
640*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
641*4882a593Smuzhiyun 	},
642*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
643*4882a593Smuzhiyun 	.result = REJECT,
644*4882a593Smuzhiyun 	.errstr = "invalid access to map value",
645*4882a593Smuzhiyun 	.errstr_unpriv = "invalid access to map value",
646*4882a593Smuzhiyun },
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun 	"bounds check for reg32 = any, reg32 xor 3",
649*4882a593Smuzhiyun 	.insns = {
650*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
651*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
652*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
653*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
654*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
655*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
656*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
657*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
658*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
659*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
660*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
661*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
662*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
663*4882a593Smuzhiyun 	},
664*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
665*4882a593Smuzhiyun 	.result = REJECT,
666*4882a593Smuzhiyun 	.errstr = "invalid access to map value",
667*4882a593Smuzhiyun 	.errstr_unpriv = "invalid access to map value",
668*4882a593Smuzhiyun },
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	"bounds check for reg > 0, reg xor 3",
671*4882a593Smuzhiyun 	.insns = {
672*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
673*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
674*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
675*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
676*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
677*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
678*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
679*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
680*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JLE, BPF_REG_1, 0, 3),
681*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
682*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 1),
683*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
684*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
685*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
686*4882a593Smuzhiyun 	},
687*4882a593Smuzhiyun 	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
688*4882a593Smuzhiyun 	.result_unpriv = REJECT,
689*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
690*4882a593Smuzhiyun 	.result = ACCEPT,
691*4882a593Smuzhiyun },
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun 	"bounds check for reg32 > 0, reg32 xor 3",
694*4882a593Smuzhiyun 	.insns = {
695*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
696*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
697*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
698*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
699*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
700*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
701*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
702*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
703*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JLE, BPF_REG_1, 0, 3),
704*4882a593Smuzhiyun 	BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
705*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JGE, BPF_REG_1, 0, 1),
706*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
707*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
708*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
709*4882a593Smuzhiyun 	},
710*4882a593Smuzhiyun 	.errstr_unpriv = "R0 min value is outside of the allowed memory range",
711*4882a593Smuzhiyun 	.result_unpriv = REJECT,
712*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
713*4882a593Smuzhiyun 	.result = ACCEPT,
714*4882a593Smuzhiyun },
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	"bounds checks after 32-bit truncation. test 1",
717*4882a593Smuzhiyun 	.insns = {
718*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
719*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
720*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
721*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
722*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
723*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
724*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
725*4882a593Smuzhiyun 	/* This used to reduce the max bound to 0x7fffffff */
726*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
727*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0x7fffffff, 1),
728*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
729*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
730*4882a593Smuzhiyun 	},
731*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
732*4882a593Smuzhiyun 	.errstr_unpriv = "R0 leaks addr",
733*4882a593Smuzhiyun 	.result_unpriv = REJECT,
734*4882a593Smuzhiyun 	.result = ACCEPT,
735*4882a593Smuzhiyun },
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun 	"bounds checks after 32-bit truncation. test 2",
738*4882a593Smuzhiyun 	.insns = {
739*4882a593Smuzhiyun 	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
740*4882a593Smuzhiyun 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
741*4882a593Smuzhiyun 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
742*4882a593Smuzhiyun 	BPF_LD_MAP_FD(BPF_REG_1, 0),
743*4882a593Smuzhiyun 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
744*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
745*4882a593Smuzhiyun 	BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
746*4882a593Smuzhiyun 	BPF_JMP_IMM(BPF_JSLT, BPF_REG_1, 1, 1),
747*4882a593Smuzhiyun 	BPF_JMP32_IMM(BPF_JSLT, BPF_REG_1, 0, 1),
748*4882a593Smuzhiyun 	BPF_MOV64_IMM(BPF_REG_0, 0),
749*4882a593Smuzhiyun 	BPF_EXIT_INSN(),
750*4882a593Smuzhiyun 	},
751*4882a593Smuzhiyun 	.fixup_map_hash_8b = { 3 },
752*4882a593Smuzhiyun 	.errstr_unpriv = "R0 leaks addr",
753*4882a593Smuzhiyun 	.result_unpriv = REJECT,
754*4882a593Smuzhiyun 	.result = ACCEPT,
755*4882a593Smuzhiyun },
756