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