at v4.12 453 lines 17 kB view raw
1#include <asm/types.h> 2#include <linux/types.h> 3#include <stdint.h> 4#include <stdio.h> 5#include <stdlib.h> 6#include <unistd.h> 7#include <errno.h> 8#include <string.h> 9#include <stddef.h> 10#include <stdbool.h> 11 12#include <linux/unistd.h> 13#include <linux/filter.h> 14#include <linux/bpf_perf_event.h> 15#include <linux/bpf.h> 16 17#include <bpf/bpf.h> 18 19#include "../../../include/linux/filter.h" 20 21#ifndef ARRAY_SIZE 22# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 23#endif 24 25#define MAX_INSNS 512 26#define MAX_MATCHES 16 27 28struct bpf_align_test { 29 const char *descr; 30 struct bpf_insn insns[MAX_INSNS]; 31 enum { 32 UNDEF, 33 ACCEPT, 34 REJECT 35 } result; 36 enum bpf_prog_type prog_type; 37 const char *matches[MAX_MATCHES]; 38}; 39 40static struct bpf_align_test tests[] = { 41 { 42 .descr = "mov", 43 .insns = { 44 BPF_MOV64_IMM(BPF_REG_3, 2), 45 BPF_MOV64_IMM(BPF_REG_3, 4), 46 BPF_MOV64_IMM(BPF_REG_3, 8), 47 BPF_MOV64_IMM(BPF_REG_3, 16), 48 BPF_MOV64_IMM(BPF_REG_3, 32), 49 BPF_MOV64_IMM(BPF_REG_0, 0), 50 BPF_EXIT_INSN(), 51 }, 52 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 53 .matches = { 54 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 55 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 56 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 57 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 58 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp", 59 }, 60 }, 61 { 62 .descr = "shift", 63 .insns = { 64 BPF_MOV64_IMM(BPF_REG_3, 1), 65 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 66 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 67 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 68 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 69 BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4), 70 BPF_MOV64_IMM(BPF_REG_4, 32), 71 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 72 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 73 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 74 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 75 BPF_MOV64_IMM(BPF_REG_0, 0), 76 BPF_EXIT_INSN(), 77 }, 78 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 79 .matches = { 80 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 81 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp", 82 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 83 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp", 84 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp", 85 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp", 86 "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", 87 "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", 88 "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", 89 "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", 90 "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", 91 }, 92 }, 93 { 94 .descr = "addsub", 95 .insns = { 96 BPF_MOV64_IMM(BPF_REG_3, 4), 97 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4), 98 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2), 99 BPF_MOV64_IMM(BPF_REG_4, 8), 100 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), 101 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2), 102 BPF_MOV64_IMM(BPF_REG_0, 0), 103 BPF_EXIT_INSN(), 104 }, 105 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 106 .matches = { 107 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp", 108 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp", 109 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp", 110 "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", 111 "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", 112 "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", 113 }, 114 }, 115 { 116 .descr = "mul", 117 .insns = { 118 BPF_MOV64_IMM(BPF_REG_3, 7), 119 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1), 120 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2), 121 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4), 122 BPF_MOV64_IMM(BPF_REG_0, 0), 123 BPF_EXIT_INSN(), 124 }, 125 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 126 .matches = { 127 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 128 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp", 129 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp", 130 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp", 131 }, 132 }, 133 134#define PREP_PKT_POINTERS \ 135 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \ 136 offsetof(struct __sk_buff, data)), \ 137 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \ 138 offsetof(struct __sk_buff, data_end)) 139 140#define LOAD_UNKNOWN(DST_REG) \ 141 PREP_PKT_POINTERS, \ 142 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \ 143 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \ 144 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \ 145 BPF_EXIT_INSN(), \ 146 BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0) 147 148 { 149 .descr = "unknown shift", 150 .insns = { 151 LOAD_UNKNOWN(BPF_REG_3), 152 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 153 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 154 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 155 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1), 156 LOAD_UNKNOWN(BPF_REG_4), 157 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5), 158 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 159 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 160 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 161 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1), 162 BPF_MOV64_IMM(BPF_REG_0, 0), 163 BPF_EXIT_INSN(), 164 }, 165 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 166 .matches = { 167 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 168 "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", 169 "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", 170 "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", 171 "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", 172 "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", 173 "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", 174 "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", 175 "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", 176 "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", 177 "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", 178 }, 179 }, 180 { 181 .descr = "unknown mul", 182 .insns = { 183 LOAD_UNKNOWN(BPF_REG_3), 184 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), 185 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1), 186 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), 187 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2), 188 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), 189 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4), 190 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3), 191 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8), 192 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2), 193 BPF_MOV64_IMM(BPF_REG_0, 0), 194 BPF_EXIT_INSN(), 195 }, 196 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 197 .matches = { 198 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp", 199 "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", 200 "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", 201 "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", 202 "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", 203 "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", 204 "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", 205 "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", 206 "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", 207 "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" 208 }, 209 }, 210 { 211 .descr = "packet const offset", 212 .insns = { 213 PREP_PKT_POINTERS, 214 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 215 216 BPF_MOV64_IMM(BPF_REG_0, 0), 217 218 /* Skip over ethernet header. */ 219 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 220 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 221 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), 222 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), 223 BPF_EXIT_INSN(), 224 225 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0), 226 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1), 227 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2), 228 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3), 229 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0), 230 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2), 231 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), 232 233 BPF_MOV64_IMM(BPF_REG_0, 0), 234 BPF_EXIT_INSN(), 235 }, 236 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 237 .matches = { 238 "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", 239 "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", 240 "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", 241 "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", 242 "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", 243 "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", 244 }, 245 }, 246 { 247 .descr = "packet variable offset", 248 .insns = { 249 LOAD_UNKNOWN(BPF_REG_6), 250 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2), 251 252 /* First, add a constant to the R5 packet pointer, 253 * then a variable with a known alignment. 254 */ 255 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 256 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 257 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 258 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 259 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), 260 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), 261 BPF_EXIT_INSN(), 262 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), 263 264 /* Now, test in the other direction. Adding first 265 * the variable offset to R5, then the constant. 266 */ 267 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 268 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 269 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 270 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), 272 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), 273 BPF_EXIT_INSN(), 274 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), 275 276 /* Test multiple accumulations of unknown values 277 * into a packet pointer. 278 */ 279 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2), 280 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14), 281 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4), 283 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6), 284 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5), 285 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4), 286 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1), 287 BPF_EXIT_INSN(), 288 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0), 289 290 BPF_MOV64_IMM(BPF_REG_0, 0), 291 BPF_EXIT_INSN(), 292 }, 293 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 294 .matches = { 295 /* Calculated offset in R6 has unknown value, but known 296 * alignment of 4. 297 */ 298 "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", 299 300 /* Offset is added to packet pointer R5, resulting in known 301 * auxiliary alignment and offset. 302 */ 303 "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", 304 305 /* At the time the word size load is performed from R5, 306 * it's total offset is NET_IP_ALIGN + reg->off (0) + 307 * reg->aux_off (14) which is 16. Then the variable 308 * offset is considered using reg->aux_off_align which 309 * is 4 and meets the load's requirements. 310 */ 311 "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", 312 313 314 /* Variable offset is added to R5 packet pointer, 315 * resulting in auxiliary alignment of 4. 316 */ 317 "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", 318 319 /* Constant offset is added to R5, resulting in 320 * reg->off of 14. 321 */ 322 "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", 323 324 /* At the time the word size load is performed from R5, 325 * it's total offset is NET_IP_ALIGN + reg->off (14) which 326 * is 16. Then the variable offset is considered using 327 * reg->aux_off_align which is 4 and meets the load's 328 * requirements. 329 */ 330 "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", 331 332 /* Constant offset is added to R5 packet pointer, 333 * resulting in reg->off value of 14. 334 */ 335 "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", 336 /* Variable offset is added to R5, resulting in an 337 * auxiliary offset of 14, and an auxiliary alignment of 4. 338 */ 339 "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", 340 /* Constant is added to R5 again, setting reg->off to 4. */ 341 "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", 342 /* And once more we add a variable, which causes an accumulation 343 * of reg->off into reg->aux_off_align, with resulting value of 344 * 18. The auxiliary alignment stays at 4. 345 */ 346 "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", 347 /* At the time the word size load is performed from R5, 348 * it's total offset is NET_IP_ALIGN + reg->off (0) + 349 * reg->aux_off (18) which is 20. Then the variable offset 350 * is considered using reg->aux_off_align which is 4 and meets 351 * the load's requirements. 352 */ 353 "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", 354 }, 355 }, 356}; 357 358static int probe_filter_length(const struct bpf_insn *fp) 359{ 360 int len; 361 362 for (len = MAX_INSNS - 1; len > 0; --len) 363 if (fp[len].code != 0 || fp[len].imm != 0) 364 break; 365 return len + 1; 366} 367 368static char bpf_vlog[32768]; 369 370static int do_test_single(struct bpf_align_test *test) 371{ 372 struct bpf_insn *prog = test->insns; 373 int prog_type = test->prog_type; 374 int prog_len, i; 375 int fd_prog; 376 int ret; 377 378 prog_len = probe_filter_length(prog); 379 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, 380 prog, prog_len, 1, "GPL", 0, 381 bpf_vlog, sizeof(bpf_vlog)); 382 if (fd_prog < 0) { 383 printf("Failed to load program.\n"); 384 printf("%s", bpf_vlog); 385 ret = 1; 386 } else { 387 ret = 0; 388 for (i = 0; i < MAX_MATCHES; i++) { 389 const char *t, *m = test->matches[i]; 390 391 if (!m) 392 break; 393 t = strstr(bpf_vlog, m); 394 if (!t) { 395 printf("Failed to find match: %s\n", m); 396 ret = 1; 397 printf("%s", bpf_vlog); 398 break; 399 } 400 } 401 close(fd_prog); 402 } 403 return ret; 404} 405 406static int do_test(unsigned int from, unsigned int to) 407{ 408 int all_pass = 0; 409 int all_fail = 0; 410 unsigned int i; 411 412 for (i = from; i < to; i++) { 413 struct bpf_align_test *test = &tests[i]; 414 int fail; 415 416 printf("Test %3d: %s ... ", 417 i, test->descr); 418 fail = do_test_single(test); 419 if (fail) { 420 all_fail++; 421 printf("FAIL\n"); 422 } else { 423 all_pass++; 424 printf("PASS\n"); 425 } 426 } 427 printf("Results: %d pass %d fail\n", 428 all_pass, all_fail); 429 return 0; 430} 431 432int main(int argc, char **argv) 433{ 434 unsigned int from = 0, to = ARRAY_SIZE(tests); 435 436 if (argc == 3) { 437 unsigned int l = atoi(argv[argc - 2]); 438 unsigned int u = atoi(argv[argc - 1]); 439 440 if (l < to && u < to) { 441 from = l; 442 to = u + 1; 443 } 444 } else if (argc == 2) { 445 unsigned int t = atoi(argv[argc - 1]); 446 447 if (t < to) { 448 from = t; 449 to = t + 1; 450 } 451 } 452 return do_test(from, to); 453}