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