···497497 {16, "R6=pkt(id=1,off=0,r=0,umin_value=2,umax_value=9223372036854775806,var_off=(0x2; 0x7ffffffffffffffc))"},498498 }499499 },500500+ {501501+ .descr = "variable subtraction",502502+ .insns = {503503+ /* Create an unknown offset, (4n+2)-aligned */504504+ LOAD_UNKNOWN(BPF_REG_6),505505+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),506506+ BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),507507+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),508508+ /* Create another unknown, (4n)-aligned, and subtract509509+ * it from the first one510510+ */511511+ BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),512512+ BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_7),513513+ /* Bounds-check the result */514514+ BPF_JMP_IMM(BPF_JSGE, BPF_REG_6, 0, 1),515515+ BPF_EXIT_INSN(),516516+ /* Add it to the packet pointer */517517+ BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),518518+ BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),519519+ /* Check bounds and perform a read */520520+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),521521+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),522522+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),523523+ BPF_EXIT_INSN(),524524+ BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),525525+ BPF_EXIT_INSN(),526526+ },527527+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,528528+ .matches = {529529+ /* Calculated offset in R6 has unknown value, but known530530+ * alignment of 4.531531+ */532532+ {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},533533+ {9, "R6=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},534534+ /* Adding 14 makes R6 be (4n+2) */535535+ {10, "R6=inv(id=0,umin_value=14,umax_value=1034,var_off=(0x2; 0x7fc))"},536536+ /* New unknown value in R7 is (4n) */537537+ {11, "R7=inv(id=0,umax_value=1020,var_off=(0x0; 0x3fc))"},538538+ /* Subtracting it from R6 blows our unsigned bounds */539539+ {12, "R6=inv(id=0,smin_value=-1006,smax_value=1034,var_off=(0x2; 0xfffffffffffffffc))"},540540+ /* Checked s>= 0 */541541+ {14, "R6=inv(id=0,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},542542+ /* At the time the word size load is performed from R5,543543+ * its total fixed offset is NET_IP_ALIGN + reg->off (0)544544+ * which is 2. Then the variable offset is (4n+2), so545545+ * the total offset is 4-byte aligned and meets the546546+ * load's requirements.547547+ */548548+ {20, "R5=pkt(id=1,off=0,r=4,umin_value=2,umax_value=1034,var_off=(0x2; 0x7fc))"},549549+ },550550+ },551551+ {552552+ .descr = "pointer variable subtraction",553553+ .insns = {554554+ /* Create an unknown offset, (4n+2)-aligned and bounded555555+ * to [14,74]556556+ */557557+ LOAD_UNKNOWN(BPF_REG_6),558558+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_6),559559+ BPF_ALU64_IMM(BPF_AND, BPF_REG_6, 0xf),560560+ BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),561561+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 14),562562+ /* Subtract it from the packet pointer */563563+ BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),564564+ BPF_ALU64_REG(BPF_SUB, BPF_REG_5, BPF_REG_6),565565+ /* Create another unknown, (4n)-aligned and >= 74.566566+ * That in fact means >= 76, since 74 % 4 == 2567567+ */568568+ BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 2),569569+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 76),570570+ /* Add it to the packet pointer */571571+ BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_7),572572+ /* Check bounds and perform a read */573573+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),574574+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),575575+ BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),576576+ BPF_EXIT_INSN(),577577+ BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_5, 0),578578+ BPF_EXIT_INSN(),579579+ },580580+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,581581+ .matches = {582582+ /* Calculated offset in R6 has unknown value, but known583583+ * alignment of 4.584584+ */585585+ {7, "R2=pkt(id=0,off=0,r=8,imm=0)"},586586+ {10, "R6=inv(id=0,umax_value=60,var_off=(0x0; 0x3c))"},587587+ /* Adding 14 makes R6 be (4n+2) */588588+ {11, "R6=inv(id=0,umin_value=14,umax_value=74,var_off=(0x2; 0x7c))"},589589+ /* Subtracting from packet pointer overflows ubounds */590590+ {13, "R5=pkt(id=1,off=0,r=8,umin_value=18446744073709551542,umax_value=18446744073709551602,var_off=(0xffffffffffffff82; 0x7c))"},591591+ /* New unknown value in R7 is (4n), >= 76 */592592+ {15, "R7=inv(id=0,umin_value=76,umax_value=1096,var_off=(0x0; 0x7fc))"},593593+ /* Adding it to packet pointer gives nice bounds again */594594+ {16, "R5=pkt(id=2,off=0,r=0,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},595595+ /* At the time the word size load is performed from R5,596596+ * its total fixed offset is NET_IP_ALIGN + reg->off (0)597597+ * which is 2. Then the variable offset is (4n+2), so598598+ * the total offset is 4-byte aligned and meets the599599+ * load's requirements.600600+ */601601+ {20, "R5=pkt(id=2,off=0,r=4,umin_value=2,umax_value=1082,var_off=(0x2; 0x7fc))"},602602+ },603603+ },500604};501605502606static int probe_filter_length(const struct bpf_insn *fp)