Back to home page

OSCL-LXR

 
 

    


0001 {
0002     "subtraction bounds (map value) variant 1",
0003     .insns = {
0004     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0005     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0006     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0007     BPF_LD_MAP_FD(BPF_REG_1, 0),
0008     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0009     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
0010     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0011     BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 7),
0012     BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
0013     BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 5),
0014     BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
0015     BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 56),
0016     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0017     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0018     BPF_EXIT_INSN(),
0019     BPF_MOV64_IMM(BPF_REG_0, 0),
0020     BPF_EXIT_INSN(),
0021     },
0022     .fixup_map_hash_8b = { 3 },
0023     .errstr = "R0 max value is outside of the allowed memory range",
0024     .result = REJECT,
0025 },
0026 {
0027     "subtraction bounds (map value) variant 2",
0028     .insns = {
0029     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0030     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0031     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0032     BPF_LD_MAP_FD(BPF_REG_1, 0),
0033     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0034     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
0035     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0036     BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0xff, 6),
0037     BPF_LDX_MEM(BPF_B, BPF_REG_3, BPF_REG_0, 1),
0038     BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 0xff, 4),
0039     BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_3),
0040     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0041     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0042     BPF_EXIT_INSN(),
0043     BPF_MOV64_IMM(BPF_REG_0, 0),
0044     BPF_EXIT_INSN(),
0045     },
0046     .fixup_map_hash_8b = { 3 },
0047     .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
0048     .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
0049     .result = REJECT,
0050 },
0051 {
0052     "check subtraction on pointers for unpriv",
0053     .insns = {
0054     BPF_MOV64_IMM(BPF_REG_0, 0),
0055     BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
0056     BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
0057     BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
0058     BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 9),
0059     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0060     BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP),
0061     BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0),
0062     BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
0063     BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
0064     BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
0065     BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 0),
0066     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0067     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0068     BPF_EXIT_INSN(),
0069     BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0),
0070     BPF_MOV64_IMM(BPF_REG_0, 0),
0071     BPF_EXIT_INSN(),
0072     },
0073     .fixup_map_hash_8b = { 1, 9 },
0074     .result = ACCEPT,
0075     .result_unpriv = REJECT,
0076     .errstr_unpriv = "R9 pointer -= pointer prohibited",
0077 },
0078 {
0079     "bounds check based on zero-extended MOV",
0080     .insns = {
0081     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0082     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0083     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0084     BPF_LD_MAP_FD(BPF_REG_1, 0),
0085     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0086     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0087     /* r2 = 0x0000'0000'ffff'ffff */
0088     BPF_MOV32_IMM(BPF_REG_2, 0xffffffff),
0089     /* r2 = 0 */
0090     BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
0091     /* no-op */
0092     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
0093     /* access at offset 0 */
0094     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0095     /* exit */
0096     BPF_MOV64_IMM(BPF_REG_0, 0),
0097     BPF_EXIT_INSN(),
0098     },
0099     .fixup_map_hash_8b = { 3 },
0100     .result = ACCEPT
0101 },
0102 {
0103     "bounds check based on sign-extended MOV. test1",
0104     .insns = {
0105     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0106     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0107     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0108     BPF_LD_MAP_FD(BPF_REG_1, 0),
0109     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0110     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0111     /* r2 = 0xffff'ffff'ffff'ffff */
0112     BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
0113     /* r2 = 0xffff'ffff */
0114     BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 32),
0115     /* r0 = <oob pointer> */
0116     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
0117     /* access to OOB pointer */
0118     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0119     /* exit */
0120     BPF_MOV64_IMM(BPF_REG_0, 0),
0121     BPF_EXIT_INSN(),
0122     },
0123     .fixup_map_hash_8b = { 3 },
0124     .errstr = "map_value pointer and 4294967295",
0125     .result = REJECT
0126 },
0127 {
0128     "bounds check based on sign-extended MOV. test2",
0129     .insns = {
0130     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0131     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0132     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0133     BPF_LD_MAP_FD(BPF_REG_1, 0),
0134     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0135     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0136     /* r2 = 0xffff'ffff'ffff'ffff */
0137     BPF_MOV64_IMM(BPF_REG_2, 0xffffffff),
0138     /* r2 = 0xfff'ffff */
0139     BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 36),
0140     /* r0 = <oob pointer> */
0141     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_2),
0142     /* access to OOB pointer */
0143     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0144     /* exit */
0145     BPF_MOV64_IMM(BPF_REG_0, 0),
0146     BPF_EXIT_INSN(),
0147     },
0148     .fixup_map_hash_8b = { 3 },
0149     .errstr = "R0 min value is outside of the allowed memory range",
0150     .result = REJECT
0151 },
0152 {
0153     "bounds check based on reg_off + var_off + insn_off. test1",
0154     .insns = {
0155     BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
0156             offsetof(struct __sk_buff, mark)),
0157     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0158     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0159     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0160     BPF_LD_MAP_FD(BPF_REG_1, 0),
0161     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0162     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0163     BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
0164     BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 29) - 1),
0165     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
0166     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
0167     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
0168     BPF_MOV64_IMM(BPF_REG_0, 0),
0169     BPF_EXIT_INSN(),
0170     },
0171     .fixup_map_hash_8b = { 4 },
0172     .errstr = "value_size=8 off=1073741825",
0173     .result = REJECT,
0174     .prog_type = BPF_PROG_TYPE_SCHED_CLS,
0175 },
0176 {
0177     "bounds check based on reg_off + var_off + insn_off. test2",
0178     .insns = {
0179     BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_1,
0180             offsetof(struct __sk_buff, mark)),
0181     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0182     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0183     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0184     BPF_LD_MAP_FD(BPF_REG_1, 0),
0185     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0186     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0187     BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 1),
0188     BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, (1 << 30) - 1),
0189     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_6),
0190     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, (1 << 29) - 1),
0191     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 3),
0192     BPF_MOV64_IMM(BPF_REG_0, 0),
0193     BPF_EXIT_INSN(),
0194     },
0195     .fixup_map_hash_8b = { 4 },
0196     .errstr = "value 1073741823",
0197     .result = REJECT,
0198     .prog_type = BPF_PROG_TYPE_SCHED_CLS,
0199 },
0200 {
0201     "bounds check after truncation of non-boundary-crossing range",
0202     .insns = {
0203     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0204     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0205     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0206     BPF_LD_MAP_FD(BPF_REG_1, 0),
0207     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0208     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9),
0209     /* r1 = [0x00, 0xff] */
0210     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0211     BPF_MOV64_IMM(BPF_REG_2, 1),
0212     /* r2 = 0x10'0000'0000 */
0213     BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 36),
0214     /* r1 = [0x10'0000'0000, 0x10'0000'00ff] */
0215     BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
0216     /* r1 = [0x10'7fff'ffff, 0x10'8000'00fe] */
0217     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
0218     /* r1 = [0x00, 0xff] */
0219     BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 0x7fffffff),
0220     /* r1 = 0 */
0221     BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
0222     /* no-op */
0223     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0224     /* access at offset 0 */
0225     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0226     /* exit */
0227     BPF_MOV64_IMM(BPF_REG_0, 0),
0228     BPF_EXIT_INSN(),
0229     },
0230     .fixup_map_hash_8b = { 3 },
0231     .result = ACCEPT
0232 },
0233 {
0234     "bounds check after truncation of boundary-crossing range (1)",
0235     .insns = {
0236     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0237     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0238     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0239     BPF_LD_MAP_FD(BPF_REG_1, 0),
0240     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0241     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
0242     /* r1 = [0x00, 0xff] */
0243     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0244     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
0245     /* r1 = [0xffff'ff80, 0x1'0000'007f] */
0246     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
0247     /* r1 = [0xffff'ff80, 0xffff'ffff] or
0248      *      [0x0000'0000, 0x0000'007f]
0249      */
0250     BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 0),
0251     BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
0252     /* r1 = [0x00, 0xff] or
0253      *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
0254      */
0255     BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
0256     /* error on OOB pointer computation */
0257     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0258     /* exit */
0259     BPF_MOV64_IMM(BPF_REG_0, 0),
0260     BPF_EXIT_INSN(),
0261     },
0262     .fixup_map_hash_8b = { 3 },
0263     /* not actually fully unbounded, but the bound is very high */
0264     .errstr = "value -4294967168 makes map_value pointer be out of bounds",
0265     .result = REJECT,
0266 },
0267 {
0268     "bounds check after truncation of boundary-crossing range (2)",
0269     .insns = {
0270     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0271     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0272     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0273     BPF_LD_MAP_FD(BPF_REG_1, 0),
0274     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0275     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
0276     /* r1 = [0x00, 0xff] */
0277     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0278     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
0279     /* r1 = [0xffff'ff80, 0x1'0000'007f] */
0280     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0xffffff80 >> 1),
0281     /* r1 = [0xffff'ff80, 0xffff'ffff] or
0282      *      [0x0000'0000, 0x0000'007f]
0283      * difference to previous test: truncation via MOV32
0284      * instead of ALU32.
0285      */
0286     BPF_MOV32_REG(BPF_REG_1, BPF_REG_1),
0287     BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
0288     /* r1 = [0x00, 0xff] or
0289      *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]
0290      */
0291     BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 0xffffff80 >> 1),
0292     /* error on OOB pointer computation */
0293     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0294     /* exit */
0295     BPF_MOV64_IMM(BPF_REG_0, 0),
0296     BPF_EXIT_INSN(),
0297     },
0298     .fixup_map_hash_8b = { 3 },
0299     .errstr = "value -4294967168 makes map_value pointer be out of bounds",
0300     .result = REJECT,
0301 },
0302 {
0303     "bounds check after wrapping 32-bit addition",
0304     .insns = {
0305     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0306     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0307     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0308     BPF_LD_MAP_FD(BPF_REG_1, 0),
0309     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0310     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
0311     /* r1 = 0x7fff'ffff */
0312     BPF_MOV64_IMM(BPF_REG_1, 0x7fffffff),
0313     /* r1 = 0xffff'fffe */
0314     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0x7fffffff),
0315     /* r1 = 0 */
0316     BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 2),
0317     /* no-op */
0318     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0319     /* access at offset 0 */
0320     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0321     /* exit */
0322     BPF_MOV64_IMM(BPF_REG_0, 0),
0323     BPF_EXIT_INSN(),
0324     },
0325     .fixup_map_hash_8b = { 3 },
0326     .result = ACCEPT
0327 },
0328 {
0329     "bounds check after shift with oversized count operand",
0330     .insns = {
0331     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0332     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0333     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0334     BPF_LD_MAP_FD(BPF_REG_1, 0),
0335     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0336     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
0337     BPF_MOV64_IMM(BPF_REG_2, 32),
0338     BPF_MOV64_IMM(BPF_REG_1, 1),
0339     /* r1 = (u32)1 << (u32)32 = ? */
0340     BPF_ALU32_REG(BPF_LSH, BPF_REG_1, BPF_REG_2),
0341     /* r1 = [0x0000, 0xffff] */
0342     BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xffff),
0343     /* computes unknown pointer, potentially OOB */
0344     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0345     /* potentially OOB access */
0346     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0347     /* exit */
0348     BPF_MOV64_IMM(BPF_REG_0, 0),
0349     BPF_EXIT_INSN(),
0350     },
0351     .fixup_map_hash_8b = { 3 },
0352     .errstr = "R0 max value is outside of the allowed memory range",
0353     .result = REJECT
0354 },
0355 {
0356     "bounds check after right shift of maybe-negative number",
0357     .insns = {
0358     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0359     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0360     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0361     BPF_LD_MAP_FD(BPF_REG_1, 0),
0362     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0363     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
0364     /* r1 = [0x00, 0xff] */
0365     BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
0366     /* r1 = [-0x01, 0xfe] */
0367     BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
0368     /* r1 = 0 or 0xff'ffff'ffff'ffff */
0369     BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
0370     /* r1 = 0 or 0xffff'ffff'ffff */
0371     BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 8),
0372     /* computes unknown pointer, potentially OOB */
0373     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0374     /* potentially OOB access */
0375     BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
0376     /* exit */
0377     BPF_MOV64_IMM(BPF_REG_0, 0),
0378     BPF_EXIT_INSN(),
0379     },
0380     .fixup_map_hash_8b = { 3 },
0381     .errstr = "R0 unbounded memory access",
0382     .result = REJECT
0383 },
0384 {
0385     "bounds check after 32-bit right shift with 64-bit input",
0386     .insns = {
0387     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0388     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0389     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0390     BPF_LD_MAP_FD(BPF_REG_1, 0),
0391     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0392     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
0393     /* r1 = 2 */
0394     BPF_MOV64_IMM(BPF_REG_1, 2),
0395     /* r1 = 1<<32 */
0396     BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
0397     /* r1 = 0 (NOT 2!) */
0398     BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
0399     /* r1 = 0xffff'fffe (NOT 0!) */
0400     BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
0401     /* error on computing OOB pointer */
0402     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0403     /* exit */
0404     BPF_MOV64_IMM(BPF_REG_0, 0),
0405     BPF_EXIT_INSN(),
0406     },
0407     .fixup_map_hash_8b = { 3 },
0408     .errstr = "math between map_value pointer and 4294967294 is not allowed",
0409     .result = REJECT,
0410 },
0411 {
0412     "bounds check map access with off+size signed 32bit overflow. test1",
0413     .insns = {
0414     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0415     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0416     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0417     BPF_LD_MAP_FD(BPF_REG_1, 0),
0418     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0419     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0420     BPF_EXIT_INSN(),
0421     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x7ffffffe),
0422     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
0423     BPF_JMP_A(0),
0424     BPF_EXIT_INSN(),
0425     },
0426     .fixup_map_hash_8b = { 3 },
0427     .errstr = "map_value pointer and 2147483646",
0428     .result = REJECT
0429 },
0430 {
0431     "bounds check map access with off+size signed 32bit overflow. test2",
0432     .insns = {
0433     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0434     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0435     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0436     BPF_LD_MAP_FD(BPF_REG_1, 0),
0437     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0438     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0439     BPF_EXIT_INSN(),
0440     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
0441     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
0442     BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 0x1fffffff),
0443     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0),
0444     BPF_JMP_A(0),
0445     BPF_EXIT_INSN(),
0446     },
0447     .fixup_map_hash_8b = { 3 },
0448     .errstr = "pointer offset 1073741822",
0449     .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
0450     .result = REJECT
0451 },
0452 {
0453     "bounds check map access with off+size signed 32bit overflow. test3",
0454     .insns = {
0455     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0456     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0457     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0458     BPF_LD_MAP_FD(BPF_REG_1, 0),
0459     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0460     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0461     BPF_EXIT_INSN(),
0462     BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
0463     BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 0x1fffffff),
0464     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
0465     BPF_JMP_A(0),
0466     BPF_EXIT_INSN(),
0467     },
0468     .fixup_map_hash_8b = { 3 },
0469     .errstr = "pointer offset -1073741822",
0470     .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
0471     .result = REJECT
0472 },
0473 {
0474     "bounds check map access with off+size signed 32bit overflow. test4",
0475     .insns = {
0476     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0477     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0478     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0479     BPF_LD_MAP_FD(BPF_REG_1, 0),
0480     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0481     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0482     BPF_EXIT_INSN(),
0483     BPF_MOV64_IMM(BPF_REG_1, 1000000),
0484     BPF_ALU64_IMM(BPF_MUL, BPF_REG_1, 1000000),
0485     BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
0486     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 2),
0487     BPF_JMP_A(0),
0488     BPF_EXIT_INSN(),
0489     },
0490     .fixup_map_hash_8b = { 3 },
0491     .errstr = "map_value pointer and 1000000000000",
0492     .result = REJECT
0493 },
0494 {
0495     "bounds check mixed 32bit and 64bit arithmetic. test1",
0496     .insns = {
0497     BPF_MOV64_IMM(BPF_REG_0, 0),
0498     BPF_MOV64_IMM(BPF_REG_1, -1),
0499     BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
0500     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
0501     /* r1 = 0xffffFFFF00000001 */
0502     BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 1, 3),
0503     /* check ALU64 op keeps 32bit bounds */
0504     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
0505     BPF_JMP32_IMM(BPF_JGT, BPF_REG_1, 2, 1),
0506     BPF_JMP_A(1),
0507     /* invalid ldx if bounds are lost above */
0508     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
0509     BPF_EXIT_INSN(),
0510     },
0511     .errstr_unpriv = "R0 invalid mem access 'scalar'",
0512     .result_unpriv = REJECT,
0513     .result = ACCEPT
0514 },
0515 {
0516     "bounds check mixed 32bit and 64bit arithmetic. test2",
0517     .insns = {
0518     BPF_MOV64_IMM(BPF_REG_0, 0),
0519     BPF_MOV64_IMM(BPF_REG_1, -1),
0520     BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
0521     BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 1),
0522     /* r1 = 0xffffFFFF00000001 */
0523     BPF_MOV64_IMM(BPF_REG_2, 3),
0524     /* r1 = 0x2 */
0525     BPF_ALU32_IMM(BPF_ADD, BPF_REG_1, 1),
0526     /* check ALU32 op zero extends 64bit bounds */
0527     BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_2, 1),
0528     BPF_JMP_A(1),
0529     /* invalid ldx if bounds are lost above */
0530     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, -1),
0531     BPF_EXIT_INSN(),
0532     },
0533     .errstr_unpriv = "R0 invalid mem access 'scalar'",
0534     .result_unpriv = REJECT,
0535     .result = ACCEPT
0536 },
0537 {
0538     "assigning 32bit bounds to 64bit for wA = 0, wB = wA",
0539     .insns = {
0540     BPF_LDX_MEM(BPF_W, BPF_REG_8, BPF_REG_1,
0541             offsetof(struct __sk_buff, data_end)),
0542     BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
0543             offsetof(struct __sk_buff, data)),
0544     BPF_MOV32_IMM(BPF_REG_9, 0),
0545     BPF_MOV32_REG(BPF_REG_2, BPF_REG_9),
0546     BPF_MOV64_REG(BPF_REG_6, BPF_REG_7),
0547     BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_2),
0548     BPF_MOV64_REG(BPF_REG_3, BPF_REG_6),
0549     BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 8),
0550     BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_8, 1),
0551     BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_6, 0),
0552     BPF_MOV64_IMM(BPF_REG_0, 0),
0553     BPF_EXIT_INSN(),
0554     },
0555     .prog_type = BPF_PROG_TYPE_SCHED_CLS,
0556     .result = ACCEPT,
0557     .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
0558 },
0559 {
0560     "bounds check for reg = 0, reg xor 1",
0561     .insns = {
0562     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0563     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0564     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0565     BPF_LD_MAP_FD(BPF_REG_1, 0),
0566     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0567     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0568     BPF_EXIT_INSN(),
0569     BPF_MOV64_IMM(BPF_REG_1, 0),
0570     BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 1),
0571     BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
0572     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0573     BPF_MOV64_IMM(BPF_REG_0, 0),
0574     BPF_EXIT_INSN(),
0575     },
0576     .errstr_unpriv = "R0 min value is outside of the allowed memory range",
0577     .result_unpriv = REJECT,
0578     .fixup_map_hash_8b = { 3 },
0579     .result = ACCEPT,
0580 },
0581 {
0582     "bounds check for reg32 = 0, reg32 xor 1",
0583     .insns = {
0584     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0585     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0586     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0587     BPF_LD_MAP_FD(BPF_REG_1, 0),
0588     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0589     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0590     BPF_EXIT_INSN(),
0591     BPF_MOV32_IMM(BPF_REG_1, 0),
0592     BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 1),
0593     BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
0594     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0595     BPF_MOV64_IMM(BPF_REG_0, 0),
0596     BPF_EXIT_INSN(),
0597     },
0598     .errstr_unpriv = "R0 min value is outside of the allowed memory range",
0599     .result_unpriv = REJECT,
0600     .fixup_map_hash_8b = { 3 },
0601     .result = ACCEPT,
0602 },
0603 {
0604     "bounds check for reg = 2, reg xor 3",
0605     .insns = {
0606     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0607     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0608     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0609     BPF_LD_MAP_FD(BPF_REG_1, 0),
0610     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0611     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0612     BPF_EXIT_INSN(),
0613     BPF_MOV64_IMM(BPF_REG_1, 2),
0614     BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
0615     BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0, 1),
0616     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0617     BPF_MOV64_IMM(BPF_REG_0, 0),
0618     BPF_EXIT_INSN(),
0619     },
0620     .errstr_unpriv = "R0 min value is outside of the allowed memory range",
0621     .result_unpriv = REJECT,
0622     .fixup_map_hash_8b = { 3 },
0623     .result = ACCEPT,
0624 },
0625 {
0626     "bounds check for reg = any, reg xor 3",
0627     .insns = {
0628     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0629     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0630     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0631     BPF_LD_MAP_FD(BPF_REG_1, 0),
0632     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0633     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0634     BPF_EXIT_INSN(),
0635     BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
0636     BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
0637     BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
0638     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0639     BPF_MOV64_IMM(BPF_REG_0, 0),
0640     BPF_EXIT_INSN(),
0641     },
0642     .fixup_map_hash_8b = { 3 },
0643     .result = REJECT,
0644     .errstr = "invalid access to map value",
0645     .errstr_unpriv = "invalid access to map value",
0646 },
0647 {
0648     "bounds check for reg32 = any, reg32 xor 3",
0649     .insns = {
0650     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0651     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0652     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0653     BPF_LD_MAP_FD(BPF_REG_1, 0),
0654     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0655     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0656     BPF_EXIT_INSN(),
0657     BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
0658     BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
0659     BPF_JMP32_IMM(BPF_JNE, BPF_REG_1, 0, 1),
0660     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0661     BPF_MOV64_IMM(BPF_REG_0, 0),
0662     BPF_EXIT_INSN(),
0663     },
0664     .fixup_map_hash_8b = { 3 },
0665     .result = REJECT,
0666     .errstr = "invalid access to map value",
0667     .errstr_unpriv = "invalid access to map value",
0668 },
0669 {
0670     "bounds check for reg > 0, reg xor 3",
0671     .insns = {
0672     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0673     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0674     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0675     BPF_LD_MAP_FD(BPF_REG_1, 0),
0676     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0677     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0678     BPF_EXIT_INSN(),
0679     BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
0680     BPF_JMP_IMM(BPF_JLE, BPF_REG_1, 0, 3),
0681     BPF_ALU64_IMM(BPF_XOR, BPF_REG_1, 3),
0682     BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 1),
0683     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0684     BPF_MOV64_IMM(BPF_REG_0, 0),
0685     BPF_EXIT_INSN(),
0686     },
0687     .errstr_unpriv = "R0 min value is outside of the allowed memory range",
0688     .result_unpriv = REJECT,
0689     .fixup_map_hash_8b = { 3 },
0690     .result = ACCEPT,
0691 },
0692 {
0693     "bounds check for reg32 > 0, reg32 xor 3",
0694     .insns = {
0695     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0696     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0697     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0698     BPF_LD_MAP_FD(BPF_REG_1, 0),
0699     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0700     BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
0701     BPF_EXIT_INSN(),
0702     BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
0703     BPF_JMP32_IMM(BPF_JLE, BPF_REG_1, 0, 3),
0704     BPF_ALU32_IMM(BPF_XOR, BPF_REG_1, 3),
0705     BPF_JMP32_IMM(BPF_JGE, BPF_REG_1, 0, 1),
0706     BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 8),
0707     BPF_MOV64_IMM(BPF_REG_0, 0),
0708     BPF_EXIT_INSN(),
0709     },
0710     .errstr_unpriv = "R0 min value is outside of the allowed memory range",
0711     .result_unpriv = REJECT,
0712     .fixup_map_hash_8b = { 3 },
0713     .result = ACCEPT,
0714 },
0715 {
0716     "bounds checks after 32-bit truncation. test 1",
0717     .insns = {
0718     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0719     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0720     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0721     BPF_LD_MAP_FD(BPF_REG_1, 0),
0722     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0723     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0724     BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
0725     /* This used to reduce the max bound to 0x7fffffff */
0726     BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
0727     BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 0x7fffffff, 1),
0728     BPF_MOV64_IMM(BPF_REG_0, 0),
0729     BPF_EXIT_INSN(),
0730     },
0731     .fixup_map_hash_8b = { 3 },
0732     .errstr_unpriv = "R0 leaks addr",
0733     .result_unpriv = REJECT,
0734     .result = ACCEPT,
0735 },
0736 {
0737     "bounds checks after 32-bit truncation. test 2",
0738     .insns = {
0739     BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
0740     BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0741     BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
0742     BPF_LD_MAP_FD(BPF_REG_1, 0),
0743     BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0744     BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
0745     BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
0746     BPF_JMP_IMM(BPF_JSLT, BPF_REG_1, 1, 1),
0747     BPF_JMP32_IMM(BPF_JSLT, BPF_REG_1, 0, 1),
0748     BPF_MOV64_IMM(BPF_REG_0, 0),
0749     BPF_EXIT_INSN(),
0750     },
0751     .fixup_map_hash_8b = { 3 },
0752     .errstr_unpriv = "R0 leaks addr",
0753     .result_unpriv = REJECT,
0754     .result = ACCEPT,
0755 },