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 array 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 array 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, 9), 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 /* r1 = 0 or 257 * [0x00ff'ffff'ff00'0000, 0x00ff'ffff'ffff'ffff] 258 */ 259 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8), 260 /* no-op or OOB pointer computation */ 261 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 262 /* potentially OOB access */ 263 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 264 /* exit */ 265 BPF_MOV64_IMM(BPF_REG_0, 0), 266 BPF_EXIT_INSN(), 267 }, 268 .fixup_map_hash_8b = { 3 }, 269 /* not actually fully unbounded, but the bound is very high */ 270 .errstr = "R0 unbounded memory access", 271 .result = REJECT 272 }, 273 { 274 "bounds check after truncation of boundary-crossing range (2)", 275 .insns = { 276 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 277 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 278 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 279 BPF_LD_MAP_FD(BPF_REG_1, 0), 280 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 281 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9), 282 /* r1 = [0x00, 0xff] */ 283 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0), 284 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1), 285 /* r1 = [0xffff'ff80, 0x1'0000'007f] */ 286 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1), 287 /* r1 = [0xffff'ff80, 0xffff'ffff] or 288 * [0x0000'0000, 0x0000'007f] 289 * difference to previous test: truncation via MOV32 290 * instead of ALU32. 291 */ 292 BPF_MOV32_REG(BPF_REG_1, BPF_REG_1), 293 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1), 294 /* r1 = [0x00, 0xff] or 295 * [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff] 296 */ 297 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1), 298 /* r1 = 0 or 299 * [0x00ff'ffff'ff00'0000, 0x00ff'ffff'ffff'ffff] 300 */ 301 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8), 302 /* no-op or OOB pointer computation */ 303 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 304 /* potentially OOB access */ 305 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 306 /* exit */ 307 BPF_MOV64_IMM(BPF_REG_0, 0), 308 BPF_EXIT_INSN(), 309 }, 310 .fixup_map_hash_8b = { 3 }, 311 /* not actually fully unbounded, but the bound is very high */ 312 .errstr = "R0 unbounded memory access", 313 .result = REJECT 314 }, 315 { 316 "bounds check after wrapping 32-bit addition", 317 .insns = { 318 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 319 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 320 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 321 BPF_LD_MAP_FD(BPF_REG_1, 0), 322 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 323 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), 324 /* r1 = 0x7fff'ffff */ 325 BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff), 326 /* r1 = 0xffff'fffe */ 327 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff), 328 /* r1 = 0 */ 329 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2), 330 /* no-op */ 331 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 332 /* access at offset 0 */ 333 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 334 /* exit */ 335 BPF_MOV64_IMM(BPF_REG_0, 0), 336 BPF_EXIT_INSN(), 337 }, 338 .fixup_map_hash_8b = { 3 }, 339 .result = ACCEPT 340 }, 341 { 342 "bounds check after shift with oversized count operand", 343 .insns = { 344 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 345 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 346 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 347 BPF_LD_MAP_FD(BPF_REG_1, 0), 348 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 349 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 350 BPF_MOV64_IMM(BPF_REG_2, 32), 351 BPF_MOV64_IMM(BPF_REG_1, 1), 352 /* r1 = (u32)1 << (u32)32 = ? */ 353 BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2), 354 /* r1 = [0x0000, 0xffff] */ 355 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff), 356 /* computes unknown pointer, potentially OOB */ 357 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 358 /* potentially OOB access */ 359 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 360 /* exit */ 361 BPF_MOV64_IMM(BPF_REG_0, 0), 362 BPF_EXIT_INSN(), 363 }, 364 .fixup_map_hash_8b = { 3 }, 365 .errstr = "R0 max value is outside of the array range", 366 .result = REJECT 367 }, 368 { 369 "bounds check after right shift of maybe-negative number", 370 .insns = { 371 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 372 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 373 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 374 BPF_LD_MAP_FD(BPF_REG_1, 0), 375 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 376 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 377 /* r1 = [0x00, 0xff] */ 378 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0), 379 /* r1 = [-0x01, 0xfe] */ 380 BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1), 381 /* r1 = 0 or 0xff'ffff'ffff'ffff */ 382 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8), 383 /* r1 = 0 or 0xffff'ffff'ffff */ 384 BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8), 385 /* computes unknown pointer, potentially OOB */ 386 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 387 /* potentially OOB access */ 388 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 389 /* exit */ 390 BPF_MOV64_IMM(BPF_REG_0, 0), 391 BPF_EXIT_INSN(), 392 }, 393 .fixup_map_hash_8b = { 3 }, 394 .errstr = "R0 unbounded memory access", 395 .result = REJECT 396 }, 397 { 398 "bounds check after 32-bit right shift with 64-bit input", 399 .insns = { 400 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 401 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 402 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 403 BPF_LD_MAP_FD(BPF_REG_1, 0), 404 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 405 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6), 406 /* r1 = 2 */ 407 BPF_MOV64_IMM(BPF_REG_1, 2), 408 /* r1 = 1<<32 */ 409 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31), 410 /* r1 = 0 (NOT 2!) */ 411 BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31), 412 /* r1 = 0xffff'fffe (NOT 0!) */ 413 BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2), 414 /* computes OOB pointer */ 415 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 416 /* OOB access */ 417 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0), 418 /* exit */ 419 BPF_MOV64_IMM(BPF_REG_0, 0), 420 BPF_EXIT_INSN(), 421 }, 422 .fixup_map_hash_8b = { 3 }, 423 .errstr = "R0 invalid mem access", 424 .result = REJECT, 425 }, 426 { 427 "bounds check map access with off+size signed 32bit overflow. test1", 428 .insns = { 429 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 430 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 431 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 432 BPF_LD_MAP_FD(BPF_REG_1, 0), 433 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 434 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 435 BPF_EXIT_INSN(), 436 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe), 437 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 438 BPF_JMP_A(0), 439 BPF_EXIT_INSN(), 440 }, 441 .fixup_map_hash_8b = { 3 }, 442 .errstr = "map_value pointer and 2147483646", 443 .result = REJECT 444 }, 445 { 446 "bounds check map access with off+size signed 32bit overflow. test2", 447 .insns = { 448 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 449 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 450 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 451 BPF_LD_MAP_FD(BPF_REG_1, 0), 452 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 453 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 454 BPF_EXIT_INSN(), 455 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff), 456 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff), 457 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff), 458 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), 459 BPF_JMP_A(0), 460 BPF_EXIT_INSN(), 461 }, 462 .fixup_map_hash_8b = { 3 }, 463 .errstr = "pointer offset 1073741822", 464 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range", 465 .result = REJECT 466 }, 467 { 468 "bounds check map access with off+size signed 32bit overflow. test3", 469 .insns = { 470 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 471 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 472 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 473 BPF_LD_MAP_FD(BPF_REG_1, 0), 474 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 475 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 476 BPF_EXIT_INSN(), 477 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff), 478 BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff), 479 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2), 480 BPF_JMP_A(0), 481 BPF_EXIT_INSN(), 482 }, 483 .fixup_map_hash_8b = { 3 }, 484 .errstr = "pointer offset -1073741822", 485 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range", 486 .result = REJECT 487 }, 488 { 489 "bounds check map access with off+size signed 32bit overflow. test4", 490 .insns = { 491 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 492 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 493 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 494 BPF_LD_MAP_FD(BPF_REG_1, 0), 495 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 496 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 497 BPF_EXIT_INSN(), 498 BPF_MOV64_IMM(BPF_REG_1, 1000000), 499 BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000), 500 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 501 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2), 502 BPF_JMP_A(0), 503 BPF_EXIT_INSN(), 504 }, 505 .fixup_map_hash_8b = { 3 }, 506 .errstr = "map_value pointer and 1000000000000", 507 .result = REJECT 508 }, 509