1 { 2 "variable-offset ctx access", 3 .insns = { 4 /* Get an unknown value */ 5 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 6 /* Make it small and 4-byte aligned */ 7 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 8 /* add it to skb. We now have either &skb->len or 9 * &skb->pkt_type, but we don't know which 10 */ 11 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2), 12 /* dereference it */ 13 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0), 14 BPF_EXIT_INSN(), 15 }, 16 .errstr = "variable ctx access var_off=(0x0; 0x4)", 17 .result = REJECT, 18 .prog_type = BPF_PROG_TYPE_LWT_IN, 19 }, 20 { 21 "variable-offset stack access", 22 .insns = { 23 /* Fill the top 8 bytes of the stack */ 24 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 25 /* Get an unknown value */ 26 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 27 /* Make it small and 4-byte aligned */ 28 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 29 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8), 30 /* add it to fp. We now have either fp-4 or fp-8, but 31 * we don't know which 32 */ 33 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 34 /* dereference it */ 35 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0), 36 BPF_EXIT_INSN(), 37 }, 38 .errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)", 39 .result = REJECT, 40 .prog_type = BPF_PROG_TYPE_LWT_IN, 41 }, 42 { 43 "indirect variable-offset stack access, unbounded", 44 .insns = { 45 BPF_MOV64_IMM(BPF_REG_2, 6), 46 BPF_MOV64_IMM(BPF_REG_3, 28), 47 /* Fill the top 16 bytes of the stack. */ 48 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 49 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 50 /* Get an unknown value. */ 51 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_1, offsetof(struct bpf_sock_ops, 52 bytes_received)), 53 /* Check the lower bound but don't check the upper one. */ 54 BPF_JMP_IMM(BPF_JSLT, BPF_REG_4, 0, 4), 55 /* Point the lower bound to initialized stack. Offset is now in range 56 * from fp-16 to fp+0x7fffffffffffffef, i.e. max value is unbounded. 57 */ 58 BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16), 59 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10), 60 BPF_MOV64_IMM(BPF_REG_5, 8), 61 /* Dereference it indirectly. */ 62 BPF_EMIT_CALL(BPF_FUNC_getsockopt), 63 BPF_MOV64_IMM(BPF_REG_0, 0), 64 BPF_EXIT_INSN(), 65 }, 66 .errstr = "R4 unbounded indirect variable offset stack access", 67 .result = REJECT, 68 .prog_type = BPF_PROG_TYPE_SOCK_OPS, 69 }, 70 { 71 "indirect variable-offset stack access, max out of bound", 72 .insns = { 73 /* Fill the top 8 bytes of the stack */ 74 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 75 /* Get an unknown value */ 76 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 77 /* Make it small and 4-byte aligned */ 78 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 79 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8), 80 /* add it to fp. We now have either fp-4 or fp-8, but 81 * we don't know which 82 */ 83 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 84 /* dereference it indirectly */ 85 BPF_LD_MAP_FD(BPF_REG_1, 0), 86 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 87 BPF_MOV64_IMM(BPF_REG_0, 0), 88 BPF_EXIT_INSN(), 89 }, 90 .fixup_map_hash_8b = { 5 }, 91 .errstr = "R2 max value is outside of stack bound", 92 .result = REJECT, 93 .prog_type = BPF_PROG_TYPE_LWT_IN, 94 }, 95 { 96 "indirect variable-offset stack access, min out of bound", 97 .insns = { 98 /* Fill the top 8 bytes of the stack */ 99 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 100 /* Get an unknown value */ 101 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 102 /* Make it small and 4-byte aligned */ 103 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 104 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 516), 105 /* add it to fp. We now have either fp-516 or fp-512, but 106 * we don't know which 107 */ 108 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 109 /* dereference it indirectly */ 110 BPF_LD_MAP_FD(BPF_REG_1, 0), 111 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 112 BPF_MOV64_IMM(BPF_REG_0, 0), 113 BPF_EXIT_INSN(), 114 }, 115 .fixup_map_hash_8b = { 5 }, 116 .errstr = "R2 min value is outside of stack bound", 117 .result = REJECT, 118 .prog_type = BPF_PROG_TYPE_LWT_IN, 119 }, 120 { 121 "indirect variable-offset stack access, max_off+size > max_initialized", 122 .insns = { 123 /* Fill only the second from top 8 bytes of the stack. */ 124 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 125 /* Get an unknown value. */ 126 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 127 /* Make it small and 4-byte aligned. */ 128 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 129 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 130 /* Add it to fp. We now have either fp-12 or fp-16, but we don't know 131 * which. fp-12 size 8 is partially uninitialized stack. 132 */ 133 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 134 /* Dereference it indirectly. */ 135 BPF_LD_MAP_FD(BPF_REG_1, 0), 136 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 137 BPF_MOV64_IMM(BPF_REG_0, 0), 138 BPF_EXIT_INSN(), 139 }, 140 .fixup_map_hash_8b = { 5 }, 141 .errstr = "invalid indirect read from stack var_off", 142 .result = REJECT, 143 .prog_type = BPF_PROG_TYPE_LWT_IN, 144 }, 145 { 146 "indirect variable-offset stack access, min_off < min_initialized", 147 .insns = { 148 /* Fill only the top 8 bytes of the stack. */ 149 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 150 /* Get an unknown value */ 151 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 152 /* Make it small and 4-byte aligned. */ 153 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 154 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 155 /* Add it to fp. We now have either fp-12 or fp-16, but we don't know 156 * which. fp-16 size 8 is partially uninitialized stack. 157 */ 158 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 159 /* Dereference it indirectly. */ 160 BPF_LD_MAP_FD(BPF_REG_1, 0), 161 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 162 BPF_MOV64_IMM(BPF_REG_0, 0), 163 BPF_EXIT_INSN(), 164 }, 165 .fixup_map_hash_8b = { 5 }, 166 .errstr = "invalid indirect read from stack var_off", 167 .result = REJECT, 168 .prog_type = BPF_PROG_TYPE_LWT_IN, 169 }, 170 { 171 "indirect variable-offset stack access, priv vs unpriv", 172 .insns = { 173 /* Fill the top 16 bytes of the stack. */ 174 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 175 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 176 /* Get an unknown value. */ 177 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 178 /* Make it small and 4-byte aligned. */ 179 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 180 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 181 /* Add it to fp. We now have either fp-12 or fp-16, we don't know 182 * which, but either way it points to initialized stack. 183 */ 184 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 185 /* Dereference it indirectly. */ 186 BPF_LD_MAP_FD(BPF_REG_1, 0), 187 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 188 BPF_MOV64_IMM(BPF_REG_0, 0), 189 BPF_EXIT_INSN(), 190 }, 191 .fixup_map_hash_8b = { 6 }, 192 .errstr_unpriv = "R2 stack pointer arithmetic goes out of range, prohibited for !root", 193 .result_unpriv = REJECT, 194 .result = ACCEPT, 195 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 196 }, 197 { 198 "indirect variable-offset stack access, uninitialized", 199 .insns = { 200 BPF_MOV64_IMM(BPF_REG_2, 6), 201 BPF_MOV64_IMM(BPF_REG_3, 28), 202 /* Fill the top 16 bytes of the stack. */ 203 BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0), 204 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 205 /* Get an unknown value. */ 206 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0), 207 /* Make it small and 4-byte aligned. */ 208 BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4), 209 BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16), 210 /* Add it to fp. We now have either fp-12 or fp-16, we don't know 211 * which, but either way it points to initialized stack. 212 */ 213 BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10), 214 BPF_MOV64_IMM(BPF_REG_5, 8), 215 /* Dereference it indirectly. */ 216 BPF_EMIT_CALL(BPF_FUNC_getsockopt), 217 BPF_MOV64_IMM(BPF_REG_0, 0), 218 BPF_EXIT_INSN(), 219 }, 220 .errstr = "invalid indirect read from stack var_off", 221 .result = REJECT, 222 .prog_type = BPF_PROG_TYPE_SOCK_OPS, 223 }, 224 { 225 "indirect variable-offset stack access, ok", 226 .insns = { 227 /* Fill the top 16 bytes of the stack. */ 228 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 229 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 230 /* Get an unknown value. */ 231 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 232 /* Make it small and 4-byte aligned. */ 233 BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 234 BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 235 /* Add it to fp. We now have either fp-12 or fp-16, we don't know 236 * which, but either way it points to initialized stack. 237 */ 238 BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 239 /* Dereference it indirectly. */ 240 BPF_LD_MAP_FD(BPF_REG_1, 0), 241 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 242 BPF_MOV64_IMM(BPF_REG_0, 0), 243 BPF_EXIT_INSN(), 244 }, 245 .fixup_map_hash_8b = { 6 }, 246 .result = ACCEPT, 247 .prog_type = BPF_PROG_TYPE_LWT_IN, 248 }, 249