diff options
Diffstat (limited to 'tools/testing/selftests/bpf/test_align.c')
| -rw-r--r-- | tools/testing/selftests/bpf/test_align.c | 453 | 
1 files changed, 453 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c new file mode 100644 index 000000000000..9644d4e069de --- /dev/null +++ b/tools/testing/selftests/bpf/test_align.c @@ -0,0 +1,453 @@ +#include <asm/types.h> +#include <linux/types.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <stddef.h> +#include <stdbool.h> + +#include <linux/unistd.h> +#include <linux/filter.h> +#include <linux/bpf_perf_event.h> +#include <linux/bpf.h> + +#include <bpf/bpf.h> + +#include "../../../include/linux/filter.h" + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define MAX_INSNS	512 +#define MAX_MATCHES	16 + +struct bpf_align_test { +	const char *descr; +	struct bpf_insn	insns[MAX_INSNS]; +	enum { +		UNDEF, +		ACCEPT, +		REJECT +	} result; +	enum bpf_prog_type prog_type; +	const char *matches[MAX_MATCHES]; +}; + +static struct bpf_align_test tests[] = { +	{ +		.descr = "mov", +		.insns = { +			BPF_MOV64_IMM(BPF_REG_3, 2), +			BPF_MOV64_IMM(BPF_REG_3, 4), +			BPF_MOV64_IMM(BPF_REG_3, 8), +			BPF_MOV64_IMM(BPF_REG_3, 16), +			BPF_MOV64_IMM(BPF_REG_3, 32), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", +			"2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", +			"3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", +			"4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", +			"5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp", +		}, +	}, +	{ +		.descr = "shift", +		.insns = { +			BPF_MOV64_IMM(BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4), +			BPF_MOV64_IMM(BPF_REG_4, 32), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", +			"2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", +			"3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", +			"4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", +			"5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", +			"6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", +			"7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp", +			"8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp", +			"9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", +			"10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp", +			"11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp", +		}, +	}, +	{ +		.descr = "addsub", +		.insns = { +			BPF_MOV64_IMM(BPF_REG_3, 4), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2), +			BPF_MOV64_IMM(BPF_REG_4, 8), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", +			"2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp", +			"3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp", +			"4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp", +			"5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp", +			"6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp", +		}, +	}, +	{ +		.descr = "mul", +		.insns = { +			BPF_MOV64_IMM(BPF_REG_3, 7), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", +			"2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", +			"3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp", +			"4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp", +		}, +	}, + +#define PREP_PKT_POINTERS \ +	BPF_LDX_MEM(BPF_W, BPF_REG_2, 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)) + +#define LOAD_UNKNOWN(DST_REG) \ +	PREP_PKT_POINTERS, \ +	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \ +	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \ +	BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \ +	BPF_EXIT_INSN(), \ +	BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0) + +	{ +		.descr = "unknown shift", +		.insns = { +			LOAD_UNKNOWN(BPF_REG_3), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), +			LOAD_UNKNOWN(BPF_REG_4), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", +			"8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp", +			"9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp", +			"10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp", +			"11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp", +			"18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp", +			"19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp", +			"20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp", +			"21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp", +			"22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp", +			"23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp", +		}, +	}, +	{ +		.descr = "unknown mul", +		.insns = { +			LOAD_UNKNOWN(BPF_REG_3), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8), +			BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2), +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", +			"8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", +			"9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp", +			"10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", +			"11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp", +			"12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", +			"13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp", +			"14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp", +			"15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp", +			"16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp" +		}, +	}, +	{ +		.descr = "packet const offset", +		.insns = { +			PREP_PKT_POINTERS, +			BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), + +			BPF_MOV64_IMM(BPF_REG_0, 0), + +			/* Skip over ethernet header.  */ +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), +			BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), +			BPF_EXIT_INSN(), + +			BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0), +			BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1), +			BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2), +			BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3), +			BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0), +			BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2), +			BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), + +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			"4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp", +			"5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp", +			"6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp", +			"10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp", +			"14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", +			"15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp", +		}, +	}, +	{ +		.descr = "packet variable offset", +		.insns = { +			LOAD_UNKNOWN(BPF_REG_6), +			BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2), + +			/* First, add a constant to the R5 packet pointer, +			 * then a variable with a known alignment. +			 */ +			BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), +			BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), +			BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), +			BPF_EXIT_INSN(), +			BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), + +			/* Now, test in the other direction.  Adding first +			 * the variable offset to R5, then the constant. +			 */ +			BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), +			BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), +			BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), +			BPF_EXIT_INSN(), +			BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), + +			/* Test multiple accumulations of unknown values +			 * into a packet pointer. +			 */ +			BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), +			BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4), +			BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), +			BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), +			BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), +			BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), +			BPF_EXIT_INSN(), +			BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), + +			BPF_MOV64_IMM(BPF_REG_0, 0), +			BPF_EXIT_INSN(), +		}, +		.prog_type = BPF_PROG_TYPE_SCHED_CLS, +		.matches = { +			/* Calculated offset in R6 has unknown value, but known +			 * alignment of 4. +			 */ +			"8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp", + +			/* Offset is added to packet pointer R5, resulting in known +			 * auxiliary alignment and offset. +			 */ +			"11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", + +			/* At the time the word size load is performed from R5, +			 * it's total offset is NET_IP_ALIGN + reg->off (0) + +			 * reg->aux_off (14) which is 16.  Then the variable +			 * offset is considered using reg->aux_off_align which +			 * is 4 and meets the load's requirements. +			 */ +			"15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", + + +			/* Variable offset is added to R5 packet pointer, +			 * resulting in auxiliary alignment of 4. +			 */ +			"18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", + +			/* Constant offset is added to R5, resulting in +			 * reg->off of 14. +			 */ +			"19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp", + +			/* At the time the word size load is performed from R5, +			 * it's total offset is NET_IP_ALIGN + reg->off (14) which +			 * is 16.  Then the variable offset is considered using +			 * reg->aux_off_align which is 4 and meets the load's +			 * requirements. +			 */ +			"23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp", + +			/* Constant offset is added to R5 packet pointer, +			 * resulting in reg->off value of 14. +			 */ +			"26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp", +			/* Variable offset is added to R5, resulting in an +			 * auxiliary offset of 14, and an auxiliary alignment of 4. +			 */ +			"27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", +			/* Constant is added to R5 again, setting reg->off to 4. */ +			"28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp", +			/* And once more we add a variable, which causes an accumulation +			 * of reg->off into reg->aux_off_align, with resulting value of +			 * 18.  The auxiliary alignment stays at 4. +			 */ +			"29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", +			/* At the time the word size load is performed from R5, +			 * it's total offset is NET_IP_ALIGN + reg->off (0) + +			 * reg->aux_off (18) which is 20.  Then the variable offset +			 * is considered using reg->aux_off_align which is 4 and meets +			 * the load's requirements. +			 */ +			"33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp", +		}, +	}, +}; + +static int probe_filter_length(const struct bpf_insn *fp) +{ +	int len; + +	for (len = MAX_INSNS - 1; len > 0; --len) +		if (fp[len].code != 0 || fp[len].imm != 0) +			break; +	return len + 1; +} + +static char bpf_vlog[32768]; + +static int do_test_single(struct bpf_align_test *test) +{ +	struct bpf_insn *prog = test->insns; +	int prog_type = test->prog_type; +	int prog_len, i; +	int fd_prog; +	int ret; + +	prog_len = probe_filter_length(prog); +	fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, +				     prog, prog_len, 1, "GPL", 0, +				     bpf_vlog, sizeof(bpf_vlog)); +	if (fd_prog < 0) { +		printf("Failed to load program.\n"); +		printf("%s", bpf_vlog); +		ret = 1; +	} else { +		ret = 0; +		for (i = 0; i < MAX_MATCHES; i++) { +			const char *t, *m = test->matches[i]; + +			if (!m) +				break; +			t = strstr(bpf_vlog, m); +			if (!t) { +				printf("Failed to find match: %s\n", m); +				ret = 1; +				printf("%s", bpf_vlog); +				break; +			} +		} +		close(fd_prog); +	} +	return ret; +} + +static int do_test(unsigned int from, unsigned int to) +{ +	int all_pass = 0; +	int all_fail = 0; +	unsigned int i; + +	for (i = from; i < to; i++) { +		struct bpf_align_test *test = &tests[i]; +		int fail; + +		printf("Test %3d: %s ... ", +		       i, test->descr); +		fail = do_test_single(test); +		if (fail) { +			all_fail++; +			printf("FAIL\n"); +		} else { +			all_pass++; +			printf("PASS\n"); +		} +	} +	printf("Results: %d pass %d fail\n", +	       all_pass, all_fail); +	return 0; +} + +int main(int argc, char **argv) +{ +	unsigned int from = 0, to = ARRAY_SIZE(tests); + +	if (argc == 3) { +		unsigned int l = atoi(argv[argc - 2]); +		unsigned int u = atoi(argv[argc - 1]); + +		if (l < to && u < to) { +			from = l; +			to   = u + 1; +		} +	} else if (argc == 2) { +		unsigned int t = atoi(argv[argc - 1]); + +		if (t < to) { +			from = t; +			to   = t + 1; +		} +	} +	return do_test(from, to); +}  | 
