18c2ecf20Sopenharmony_ci{
28c2ecf20Sopenharmony_ci	"variable-offset ctx access",
38c2ecf20Sopenharmony_ci	.insns = {
48c2ecf20Sopenharmony_ci	/* Get an unknown value */
58c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
68c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned */
78c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
88c2ecf20Sopenharmony_ci	/* add it to skb.  We now have either &skb->len or
98c2ecf20Sopenharmony_ci	 * &skb->pkt_type, but we don't know which
108c2ecf20Sopenharmony_ci	 */
118c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
128c2ecf20Sopenharmony_ci	/* dereference it */
138c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
148c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
158c2ecf20Sopenharmony_ci	},
168c2ecf20Sopenharmony_ci	.errstr = "variable ctx access var_off=(0x0; 0x4)",
178c2ecf20Sopenharmony_ci	.result = REJECT,
188c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
198c2ecf20Sopenharmony_ci},
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	"variable-offset stack read, priv vs unpriv",
228c2ecf20Sopenharmony_ci	.insns = {
238c2ecf20Sopenharmony_ci	/* Fill the top 8 bytes of the stack */
248c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
258c2ecf20Sopenharmony_ci	/* Get an unknown value */
268c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
278c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned */
288c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
298c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
308c2ecf20Sopenharmony_ci	/* add it to fp.  We now have either fp-4 or fp-8, but
318c2ecf20Sopenharmony_ci	 * we don't know which
328c2ecf20Sopenharmony_ci	 */
338c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
348c2ecf20Sopenharmony_ci	/* dereference it for a stack read */
358c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
368c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
378c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
388c2ecf20Sopenharmony_ci	},
398c2ecf20Sopenharmony_ci	.result = ACCEPT,
408c2ecf20Sopenharmony_ci	.result_unpriv = REJECT,
418c2ecf20Sopenharmony_ci	.errstr_unpriv = "R2 variable stack access prohibited for !root",
428c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
438c2ecf20Sopenharmony_ci},
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	"variable-offset stack read, uninitialized",
468c2ecf20Sopenharmony_ci	.insns = {
478c2ecf20Sopenharmony_ci	/* Get an unknown value */
488c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
498c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned */
508c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
518c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
528c2ecf20Sopenharmony_ci	/* add it to fp.  We now have either fp-4 or fp-8, but
538c2ecf20Sopenharmony_ci	 * we don't know which
548c2ecf20Sopenharmony_ci	 */
558c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
568c2ecf20Sopenharmony_ci	/* dereference it for a stack read */
578c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
588c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
598c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
608c2ecf20Sopenharmony_ci	},
618c2ecf20Sopenharmony_ci	.result = REJECT,
628c2ecf20Sopenharmony_ci	.errstr = "invalid variable-offset read from stack R2",
638c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
648c2ecf20Sopenharmony_ci},
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	"variable-offset stack write, priv vs unpriv",
678c2ecf20Sopenharmony_ci	.insns = {
688c2ecf20Sopenharmony_ci	/* Get an unknown value */
698c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
708c2ecf20Sopenharmony_ci	/* Make it small and 8-byte aligned */
718c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 8),
728c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
738c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-8 or fp-16, but
748c2ecf20Sopenharmony_ci	 * we don't know which
758c2ecf20Sopenharmony_ci	 */
768c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
778c2ecf20Sopenharmony_ci	/* Dereference it for a stack write */
788c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
798c2ecf20Sopenharmony_ci	/* Now read from the address we just wrote. This shows
808c2ecf20Sopenharmony_ci	 * that, after a variable-offset write, a priviledged
818c2ecf20Sopenharmony_ci	 * program can read the slots that were in the range of
828c2ecf20Sopenharmony_ci	 * that write (even if the verifier doesn't actually know
838c2ecf20Sopenharmony_ci	 * if the slot being read was really written to or not.
848c2ecf20Sopenharmony_ci	 */
858c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_2, 0),
868c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
878c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
888c2ecf20Sopenharmony_ci	},
898c2ecf20Sopenharmony_ci	/* Variable stack access is rejected for unprivileged.
908c2ecf20Sopenharmony_ci	 */
918c2ecf20Sopenharmony_ci	.errstr_unpriv = "R2 variable stack access prohibited for !root",
928c2ecf20Sopenharmony_ci	.result_unpriv = REJECT,
938c2ecf20Sopenharmony_ci	.result = ACCEPT,
948c2ecf20Sopenharmony_ci},
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	"variable-offset stack write clobbers spilled regs",
978c2ecf20Sopenharmony_ci	.insns = {
988c2ecf20Sopenharmony_ci	/* Dummy instruction; needed because we need to patch the next one
998c2ecf20Sopenharmony_ci	 * and we can't patch the first instruction.
1008c2ecf20Sopenharmony_ci	 */
1018c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_6, 0),
1028c2ecf20Sopenharmony_ci	/* Make R0 a map ptr */
1038c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_0, 0),
1048c2ecf20Sopenharmony_ci	/* Get an unknown value */
1058c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
1068c2ecf20Sopenharmony_ci	/* Make it small and 8-byte aligned */
1078c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 8),
1088c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
1098c2ecf20Sopenharmony_ci	/* Add it to fp. We now have either fp-8 or fp-16, but
1108c2ecf20Sopenharmony_ci	 * we don't know which.
1118c2ecf20Sopenharmony_ci	 */
1128c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
1138c2ecf20Sopenharmony_ci	/* Spill R0(map ptr) into stack */
1148c2ecf20Sopenharmony_ci	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
1158c2ecf20Sopenharmony_ci	/* Dereference the unknown value for a stack write */
1168c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
1178c2ecf20Sopenharmony_ci	/* Fill the register back into R2 */
1188c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8),
1198c2ecf20Sopenharmony_ci	/* Try to dereference R2 for a memory load */
1208c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 8),
1218c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
1228c2ecf20Sopenharmony_ci	},
1238c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 1 },
1248c2ecf20Sopenharmony_ci	/* The unpriviledged case is not too interesting; variable
1258c2ecf20Sopenharmony_ci	 * stack access is rejected.
1268c2ecf20Sopenharmony_ci	 */
1278c2ecf20Sopenharmony_ci	.errstr_unpriv = "R2 variable stack access prohibited for !root",
1288c2ecf20Sopenharmony_ci	.result_unpriv = REJECT,
1298c2ecf20Sopenharmony_ci	/* In the priviledged case, dereferencing a spilled-and-then-filled
1308c2ecf20Sopenharmony_ci	 * register is rejected because the previous variable offset stack
1318c2ecf20Sopenharmony_ci	 * write might have overwritten the spilled pointer (i.e. we lose track
1328c2ecf20Sopenharmony_ci	 * of the spilled register when we analyze the write).
1338c2ecf20Sopenharmony_ci	 */
1348c2ecf20Sopenharmony_ci	.errstr = "R2 invalid mem access 'inv'",
1358c2ecf20Sopenharmony_ci	.result = REJECT,
1368c2ecf20Sopenharmony_ci},
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, unbounded",
1398c2ecf20Sopenharmony_ci	.insns = {
1408c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_2, 6),
1418c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_3, 28),
1428c2ecf20Sopenharmony_ci	/* Fill the top 16 bytes of the stack. */
1438c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
1448c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
1458c2ecf20Sopenharmony_ci	/* Get an unknown value. */
1468c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_1, offsetof(struct bpf_sock_ops,
1478c2ecf20Sopenharmony_ci							   bytes_received)),
1488c2ecf20Sopenharmony_ci	/* Check the lower bound but don't check the upper one. */
1498c2ecf20Sopenharmony_ci	BPF_JMP_IMM(BPF_JSLT, BPF_REG_4, 0, 4),
1508c2ecf20Sopenharmony_ci	/* Point the lower bound to initialized stack. Offset is now in range
1518c2ecf20Sopenharmony_ci	 * from fp-16 to fp+0x7fffffffffffffef, i.e. max value is unbounded.
1528c2ecf20Sopenharmony_ci	 */
1538c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
1548c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
1558c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_5, 8),
1568c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
1578c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_getsockopt),
1588c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
1598c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
1608c2ecf20Sopenharmony_ci	},
1618c2ecf20Sopenharmony_ci	.errstr = "invalid unbounded variable-offset indirect access to stack R4",
1628c2ecf20Sopenharmony_ci	.result = REJECT,
1638c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_SOCK_OPS,
1648c2ecf20Sopenharmony_ci},
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, max out of bound",
1678c2ecf20Sopenharmony_ci	.insns = {
1688c2ecf20Sopenharmony_ci	/* Fill the top 8 bytes of the stack */
1698c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
1708c2ecf20Sopenharmony_ci	/* Get an unknown value */
1718c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
1728c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned */
1738c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
1748c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
1758c2ecf20Sopenharmony_ci	/* add it to fp.  We now have either fp-4 or fp-8, but
1768c2ecf20Sopenharmony_ci	 * we don't know which
1778c2ecf20Sopenharmony_ci	 */
1788c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
1798c2ecf20Sopenharmony_ci	/* dereference it indirectly */
1808c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
1818c2ecf20Sopenharmony_ci	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
1828c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
1838c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
1848c2ecf20Sopenharmony_ci	},
1858c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 5 },
1868c2ecf20Sopenharmony_ci	.errstr = "invalid variable-offset indirect access to stack R2",
1878c2ecf20Sopenharmony_ci	.result = REJECT,
1888c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
1898c2ecf20Sopenharmony_ci},
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, min out of bound",
1928c2ecf20Sopenharmony_ci	.insns = {
1938c2ecf20Sopenharmony_ci	/* Fill the top 8 bytes of the stack */
1948c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
1958c2ecf20Sopenharmony_ci	/* Get an unknown value */
1968c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
1978c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned */
1988c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
1998c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 516),
2008c2ecf20Sopenharmony_ci	/* add it to fp.  We now have either fp-516 or fp-512, but
2018c2ecf20Sopenharmony_ci	 * we don't know which
2028c2ecf20Sopenharmony_ci	 */
2038c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
2048c2ecf20Sopenharmony_ci	/* dereference it indirectly */
2058c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
2068c2ecf20Sopenharmony_ci	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
2078c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
2088c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
2098c2ecf20Sopenharmony_ci	},
2108c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 5 },
2118c2ecf20Sopenharmony_ci	.errstr = "invalid variable-offset indirect access to stack R2",
2128c2ecf20Sopenharmony_ci	.result = REJECT,
2138c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
2148c2ecf20Sopenharmony_ci},
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, max_off+size > max_initialized",
2178c2ecf20Sopenharmony_ci	.insns = {
2188c2ecf20Sopenharmony_ci	/* Fill only the second from top 8 bytes of the stack. */
2198c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
2208c2ecf20Sopenharmony_ci	/* Get an unknown value. */
2218c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
2228c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned. */
2238c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
2248c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
2258c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
2268c2ecf20Sopenharmony_ci	 * which. fp-12 size 8 is partially uninitialized stack.
2278c2ecf20Sopenharmony_ci	 */
2288c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
2298c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
2308c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
2318c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
2328c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
2338c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
2348c2ecf20Sopenharmony_ci	},
2358c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 5 },
2368c2ecf20Sopenharmony_ci	.errstr = "invalid indirect read from stack R2 var_off",
2378c2ecf20Sopenharmony_ci	.result = REJECT,
2388c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
2398c2ecf20Sopenharmony_ci},
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, min_off < min_initialized",
2428c2ecf20Sopenharmony_ci	.insns = {
2438c2ecf20Sopenharmony_ci	/* Fill only the top 8 bytes of the stack. */
2448c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
2458c2ecf20Sopenharmony_ci	/* Get an unknown value */
2468c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
2478c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned. */
2488c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
2498c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
2508c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
2518c2ecf20Sopenharmony_ci	 * which. fp-16 size 8 is partially uninitialized stack.
2528c2ecf20Sopenharmony_ci	 */
2538c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
2548c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
2558c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
2568c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
2578c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
2588c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
2598c2ecf20Sopenharmony_ci	},
2608c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 5 },
2618c2ecf20Sopenharmony_ci	.errstr = "invalid indirect read from stack R2 var_off",
2628c2ecf20Sopenharmony_ci	.result = REJECT,
2638c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
2648c2ecf20Sopenharmony_ci},
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, priv vs unpriv",
2678c2ecf20Sopenharmony_ci	.insns = {
2688c2ecf20Sopenharmony_ci	/* Fill the top 16 bytes of the stack. */
2698c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
2708c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
2718c2ecf20Sopenharmony_ci	/* Get an unknown value. */
2728c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
2738c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned. */
2748c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
2758c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
2768c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
2778c2ecf20Sopenharmony_ci	 * which, but either way it points to initialized stack.
2788c2ecf20Sopenharmony_ci	 */
2798c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
2808c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
2818c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
2828c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
2838c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
2848c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
2858c2ecf20Sopenharmony_ci	},
2868c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 6 },
2878c2ecf20Sopenharmony_ci	.errstr_unpriv = "R2 variable stack access prohibited for !root",
2888c2ecf20Sopenharmony_ci	.result_unpriv = REJECT,
2898c2ecf20Sopenharmony_ci	.result = ACCEPT,
2908c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
2918c2ecf20Sopenharmony_ci},
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, uninitialized",
2948c2ecf20Sopenharmony_ci	.insns = {
2958c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_2, 6),
2968c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_3, 28),
2978c2ecf20Sopenharmony_ci	/* Fill the top 16 bytes of the stack. */
2988c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
2998c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
3008c2ecf20Sopenharmony_ci	/* Get an unknown value. */
3018c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
3028c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned. */
3038c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
3048c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
3058c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
3068c2ecf20Sopenharmony_ci	 * which, but either way it points to initialized stack.
3078c2ecf20Sopenharmony_ci	 */
3088c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
3098c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_5, 8),
3108c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
3118c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_getsockopt),
3128c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
3138c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
3148c2ecf20Sopenharmony_ci	},
3158c2ecf20Sopenharmony_ci	.errstr = "invalid indirect read from stack R4 var_off",
3168c2ecf20Sopenharmony_ci	.result = REJECT,
3178c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_SOCK_OPS,
3188c2ecf20Sopenharmony_ci},
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	"indirect variable-offset stack access, ok",
3218c2ecf20Sopenharmony_ci	.insns = {
3228c2ecf20Sopenharmony_ci	/* Fill the top 16 bytes of the stack. */
3238c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
3248c2ecf20Sopenharmony_ci	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
3258c2ecf20Sopenharmony_ci	/* Get an unknown value. */
3268c2ecf20Sopenharmony_ci	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
3278c2ecf20Sopenharmony_ci	/* Make it small and 4-byte aligned. */
3288c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
3298c2ecf20Sopenharmony_ci	BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
3308c2ecf20Sopenharmony_ci	/* Add it to fp.  We now have either fp-12 or fp-16, we don't know
3318c2ecf20Sopenharmony_ci	 * which, but either way it points to initialized stack.
3328c2ecf20Sopenharmony_ci	 */
3338c2ecf20Sopenharmony_ci	BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
3348c2ecf20Sopenharmony_ci	/* Dereference it indirectly. */
3358c2ecf20Sopenharmony_ci	BPF_LD_MAP_FD(BPF_REG_1, 0),
3368c2ecf20Sopenharmony_ci	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
3378c2ecf20Sopenharmony_ci	BPF_MOV64_IMM(BPF_REG_0, 0),
3388c2ecf20Sopenharmony_ci	BPF_EXIT_INSN(),
3398c2ecf20Sopenharmony_ci	},
3408c2ecf20Sopenharmony_ci	.fixup_map_hash_8b = { 6 },
3418c2ecf20Sopenharmony_ci	.result = ACCEPT,
3428c2ecf20Sopenharmony_ci	.prog_type = BPF_PROG_TYPE_LWT_IN,
3438c2ecf20Sopenharmony_ci},
344