bounds.c (24553B)
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 .errstr_unpriv = "R0 invalid mem access 'scalar'", 512 .result_unpriv = REJECT, 513 .result = ACCEPT 514}, 515{ 516 "bounds check mixed 32bit and 64bit arithmetic. test2", 517 .insns = { 518 BPF_MOV64_IMM(BPF_REG_0, 0), 519 BPF_MOV64_IMM(BPF_REG_1, -1), 520 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32), 521 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1), 522 /* r1 = 0xffffFFFF00000001 */ 523 BPF_MOV64_IMM(BPF_REG_2, 3), 524 /* r1 = 0x2 */ 525 BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1), 526 /* check ALU32 op zero extends 64bit bounds */ 527 BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1), 528 BPF_JMP_A(1), 529 /* invalid ldx if bounds are lost above */ 530 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1), 531 BPF_EXIT_INSN(), 532 }, 533 .errstr_unpriv = "R0 invalid mem access 'scalar'", 534 .result_unpriv = REJECT, 535 .result = ACCEPT 536}, 537{ 538 "assigning 32bit bounds to 64bit for wA = 0, wB = wA", 539 .insns = { 540 BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1, 541 offsetof(struct __sk_buff, data_end)), 542 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, 543 offsetof(struct __sk_buff, data)), 544 BPF_MOV32_IMM(BPF_REG_9, 0), 545 BPF_MOV32_REG(BPF_REG_2, BPF_REG_9), 546 BPF_MOV64_REG(BPF_REG_6, BPF_REG_7), 547 BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2), 548 BPF_MOV64_REG(BPF_REG_3, BPF_REG_6), 549 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8), 550 BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1), 551 BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0), 552 BPF_MOV64_IMM(BPF_REG_0, 0), 553 BPF_EXIT_INSN(), 554 }, 555 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 556 .result = ACCEPT, 557 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 558}, 559{ 560 "bounds check for reg = 0, reg xor 1", 561 .insns = { 562 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 563 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 564 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 565 BPF_LD_MAP_FD(BPF_REG_1, 0), 566 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 567 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 568 BPF_EXIT_INSN(), 569 BPF_MOV64_IMM(BPF_REG_1, 0), 570 BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 1), 571 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1), 572 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 573 BPF_MOV64_IMM(BPF_REG_0, 0), 574 BPF_EXIT_INSN(), 575 }, 576 .errstr_unpriv = "R0 min value is outside of the allowed memory range", 577 .result_unpriv = REJECT, 578 .fixup_map_hash_8b = { 3 }, 579 .result = ACCEPT, 580}, 581{ 582 "bounds check for reg32 = 0, reg32 xor 1", 583 .insns = { 584 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 585 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 586 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 587 BPF_LD_MAP_FD(BPF_REG_1, 0), 588 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 589 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 590 BPF_EXIT_INSN(), 591 BPF_MOV32_IMM(BPF_REG_1, 0), 592 BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 1), 593 BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1), 594 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 595 BPF_MOV64_IMM(BPF_REG_0, 0), 596 BPF_EXIT_INSN(), 597 }, 598 .errstr_unpriv = "R0 min value is outside of the allowed memory range", 599 .result_unpriv = REJECT, 600 .fixup_map_hash_8b = { 3 }, 601 .result = ACCEPT, 602}, 603{ 604 "bounds check for reg = 2, reg xor 3", 605 .insns = { 606 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 607 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 608 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 609 BPF_LD_MAP_FD(BPF_REG_1, 0), 610 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 611 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 612 BPF_EXIT_INSN(), 613 BPF_MOV64_IMM(BPF_REG_1, 2), 614 BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3), 615 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0, 1), 616 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 617 BPF_MOV64_IMM(BPF_REG_0, 0), 618 BPF_EXIT_INSN(), 619 }, 620 .errstr_unpriv = "R0 min value is outside of the allowed memory range", 621 .result_unpriv = REJECT, 622 .fixup_map_hash_8b = { 3 }, 623 .result = ACCEPT, 624}, 625{ 626 "bounds check for reg = any, reg xor 3", 627 .insns = { 628 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 629 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 630 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 631 BPF_LD_MAP_FD(BPF_REG_1, 0), 632 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 633 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 634 BPF_EXIT_INSN(), 635 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 636 BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3), 637 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1), 638 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 639 BPF_MOV64_IMM(BPF_REG_0, 0), 640 BPF_EXIT_INSN(), 641 }, 642 .fixup_map_hash_8b = { 3 }, 643 .result = REJECT, 644 .errstr = "invalid access to map value", 645 .errstr_unpriv = "invalid access to map value", 646}, 647{ 648 "bounds check for reg32 = any, reg32 xor 3", 649 .insns = { 650 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 651 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 652 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 653 BPF_LD_MAP_FD(BPF_REG_1, 0), 654 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 655 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 656 BPF_EXIT_INSN(), 657 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 658 BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3), 659 BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1), 660 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 661 BPF_MOV64_IMM(BPF_REG_0, 0), 662 BPF_EXIT_INSN(), 663 }, 664 .fixup_map_hash_8b = { 3 }, 665 .result = REJECT, 666 .errstr = "invalid access to map value", 667 .errstr_unpriv = "invalid access to map value", 668}, 669{ 670 "bounds check for reg > 0, reg xor 3", 671 .insns = { 672 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 673 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 674 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 675 BPF_LD_MAP_FD(BPF_REG_1, 0), 676 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 677 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 678 BPF_EXIT_INSN(), 679 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 680 BPF_JMP_IMM(BPF_JLE, BPF_REG_1, 0, 3), 681 BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3), 682 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 1), 683 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 684 BPF_MOV64_IMM(BPF_REG_0, 0), 685 BPF_EXIT_INSN(), 686 }, 687 .errstr_unpriv = "R0 min value is outside of the allowed memory range", 688 .result_unpriv = REJECT, 689 .fixup_map_hash_8b = { 3 }, 690 .result = ACCEPT, 691}, 692{ 693 "bounds check for reg32 > 0, reg32 xor 3", 694 .insns = { 695 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 696 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 697 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 698 BPF_LD_MAP_FD(BPF_REG_1, 0), 699 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 700 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 701 BPF_EXIT_INSN(), 702 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 703 BPF_JMP32_IMM(BPF_JLE, BPF_REG_1, 0, 3), 704 BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3), 705 BPF_JMP32_IMM(BPF_JGE, BPF_REG_1, 0, 1), 706 BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8), 707 BPF_MOV64_IMM(BPF_REG_0, 0), 708 BPF_EXIT_INSN(), 709 }, 710 .errstr_unpriv = "R0 min value is outside of the allowed memory range", 711 .result_unpriv = REJECT, 712 .fixup_map_hash_8b = { 3 }, 713 .result = ACCEPT, 714}, 715{ 716 "bounds checks after 32-bit truncation. test 1", 717 .insns = { 718 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 719 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 720 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 721 BPF_LD_MAP_FD(BPF_REG_1, 0), 722 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 723 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 724 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), 725 /* This used to reduce the max bound to 0x7fffffff */ 726 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 727 BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0x7fffffff, 1), 728 BPF_MOV64_IMM(BPF_REG_0, 0), 729 BPF_EXIT_INSN(), 730 }, 731 .fixup_map_hash_8b = { 3 }, 732 .errstr_unpriv = "R0 leaks addr", 733 .result_unpriv = REJECT, 734 .result = ACCEPT, 735}, 736{ 737 "bounds checks after 32-bit truncation. test 2", 738 .insns = { 739 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 740 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 741 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 742 BPF_LD_MAP_FD(BPF_REG_1, 0), 743 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 744 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), 745 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), 746 BPF_JMP_IMM(BPF_JSLT, BPF_REG_1, 1, 1), 747 BPF_JMP32_IMM(BPF_JSLT, BPF_REG_1, 0, 1), 748 BPF_MOV64_IMM(BPF_REG_0, 0), 749 BPF_EXIT_INSN(), 750 }, 751 .fixup_map_hash_8b = { 3 }, 752 .errstr_unpriv = "R0 leaks addr", 753 .result_unpriv = REJECT, 754 .result = ACCEPT, 755},