{
	"helper access to variable memory: stack, bitwise AND + JMP, correct bounds",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
	BPF_MOV64_IMM(BPF_REG_2, 16),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, bitwise AND, zero included",
	.insns = {
	/* set max stack size */
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
	/* set r3 to a random value */
	BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
	BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
	/* use bitwise AND to limit r3 range to [0, 64] */
	BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 64),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	/* Call bpf_ringbuf_output(), it is one of a few helper functions with
	 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
	 * For unpriv this should signal an error, because memory at &fp[-64] is
	 * not initialized.
	 */
	BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
	BPF_EXIT_INSN(),
	},
	.fixup_map_ringbuf = { 4 },
	.errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
	.result_unpriv = REJECT,
	/* in privileged mode reads from uninitialized stack locations are permitted */
	.result = ACCEPT,
},
{
	"helper access to variable memory: stack, bitwise AND + JMP, wrong max",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 65),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr = "invalid indirect access to stack R1 off=-64 size=65",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP, correct bounds",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
	BPF_MOV64_IMM(BPF_REG_2, 16),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP (signed), correct bounds",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
	BPF_MOV64_IMM(BPF_REG_2, 16),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP, bounds + offset",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 5),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 3),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr = "invalid indirect access to stack R1 off=-64 size=65",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP, wrong max",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 65, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr = "invalid indirect access to stack R1 off=-64 size=65",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP, no max check",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	/* because max wasn't checked, signed min is negative */
	.errstr = "R2 min value is negative, either use unsigned or 'var &= const'",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: stack, JMP, no min check",
	.insns = {
	/* set max stack size */
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
	/* set r3 to a random value */
	BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
	BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
	/* use JMP to limit r3 range to [0, 64] */
	BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 64, 6),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	/* Call bpf_ringbuf_output(), it is one of a few helper functions with
	 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
	 * For unpriv this should signal an error, because memory at &fp[-64] is
	 * not initialized.
	 */
	BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_ringbuf = { 4 },
	.errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
	.result_unpriv = REJECT,
	/* in privileged mode reads from uninitialized stack locations are permitted */
	.result = ACCEPT,
},
{
	"helper access to variable memory: stack, JMP (signed), no min check",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, 64, 3),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.errstr = "R2 min value is negative",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: map, JMP, correct bounds",
	.insns = {
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val), 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_48b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: map, JMP, wrong max",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) + 1, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_48b = { 4 },
	.errstr = "invalid access to map value, value_size=48 off=0 size=49",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: map adjusted, JMP, correct bounds",
	.insns = {
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20),
	BPF_MOV64_IMM(BPF_REG_2, sizeof(struct test_val)),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) - 20, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_48b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: map adjusted, JMP, wrong max",
	.insns = {
	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 8),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 20),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_6),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
	BPF_JMP_IMM(BPF_JSGT, BPF_REG_2, sizeof(struct test_val) - 19, 4),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_JMP_REG(BPF_JSGE, BPF_REG_4, BPF_REG_2, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_48b = { 4 },
	.errstr = "R1 min value is outside of the allowed memory range",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size = 0 allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_MOV64_IMM(BPF_REG_1, 0),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size > 0 not allowed on NULL (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
	BPF_MOV64_IMM(BPF_REG_1, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.errstr = "R1 type=scalar expected=fp",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 0),
	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 8),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 7),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
	BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size possible = 0 allowed on != NULL map pointer (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
{
	"helper access to variable memory: size possible = 0 allowed on != NULL packet pointer (ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
		    offsetof(struct __sk_buff, data)),
	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
		    offsetof(struct __sk_buff, data_end)),
	BPF_MOV64_REG(BPF_REG_0, BPF_REG_6),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8),
	BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 7),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_6, 0),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	BPF_MOV64_IMM(BPF_REG_5, 0),
	BPF_EMIT_CALL(BPF_FUNC_csum_diff),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
	.retval = 0 /* csum_diff of 64-byte packet */,
	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
	"helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_MOV64_IMM(BPF_REG_1, 0),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.errstr = "R1 type=scalar expected=fp",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size > 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_MOV64_IMM(BPF_REG_1, 0),
	BPF_MOV64_IMM(BPF_REG_2, 1),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.errstr = "R1 type=scalar expected=fp",
	.result = REJECT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size possible = 0 allowed on != NULL stack pointer (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 4),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: size possible = 0 allowed on != NULL map pointer (!ARG_PTR_TO_MEM_OR_NULL)",
	.insns = {
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
	BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 8, 2),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_EXIT_INSN(),
	},
	.fixup_map_hash_8b = { 3 },
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
{
	"helper access to variable memory: 8 bytes leak",
	.insns = {
	/* set max stack size */
	BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
	/* set r3 to a random value */
	BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
	BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
	BPF_LD_MAP_FD(BPF_REG_1, 0),
	BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
	/* Note: fp[-32] left uninitialized */
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
	/* Limit r3 range to [1, 64] */
	BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 63),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1),
	BPF_MOV64_IMM(BPF_REG_4, 0),
	/* Call bpf_ringbuf_output(), it is one of a few helper functions with
	 * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
	 * For unpriv this should signal an error, because memory region [1, 64]
	 * at &fp[-64] is not fully initialized.
	 */
	BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_EXIT_INSN(),
	},
	.fixup_map_ringbuf = { 3 },
	.errstr_unpriv = "invalid indirect read from stack R2 off -64+32 size 64",
	.result_unpriv = REJECT,
	/* in privileged mode reads from uninitialized stack locations are permitted */
	.result = ACCEPT,
},
{
	"helper access to variable memory: 8 bytes no leak (init memory)",
	.insns = {
	BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_MOV64_IMM(BPF_REG_0, 0),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -32),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
	BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
	BPF_MOV64_IMM(BPF_REG_2, 0),
	BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 32),
	BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 32),
	BPF_MOV64_IMM(BPF_REG_3, 0),
	BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
	BPF_EXIT_INSN(),
	},
	.result = ACCEPT,
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
},
