1 { 2 "reference tracking: leak potential reference", 3 .insns = { 4 BPF_SK_LOOKUP(sk_lookup_tcp), 5 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), /* leak reference */ 6 BPF_EXIT_INSN(), 7 }, 8 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 9 .errstr = "Unreleased reference", 10 .result = REJECT, 11 }, 12 { 13 "reference tracking: leak potential reference to sock_common", 14 .insns = { 15 BPF_SK_LOOKUP(skc_lookup_tcp), 16 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), /* leak reference */ 17 BPF_EXIT_INSN(), 18 }, 19 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 20 .errstr = "Unreleased reference", 21 .result = REJECT, 22 }, 23 { 24 "reference tracking: leak potential reference on stack", 25 .insns = { 26 BPF_SK_LOOKUP(sk_lookup_tcp), 27 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 28 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 29 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0), 30 BPF_MOV64_IMM(BPF_REG_0, 0), 31 BPF_EXIT_INSN(), 32 }, 33 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 34 .errstr = "Unreleased reference", 35 .result = REJECT, 36 }, 37 { 38 "reference tracking: leak potential reference on stack 2", 39 .insns = { 40 BPF_SK_LOOKUP(sk_lookup_tcp), 41 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 42 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 43 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0), 44 BPF_MOV64_IMM(BPF_REG_0, 0), 45 BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0), 46 BPF_EXIT_INSN(), 47 }, 48 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 49 .errstr = "Unreleased reference", 50 .result = REJECT, 51 }, 52 { 53 "reference tracking: zero potential reference", 54 .insns = { 55 BPF_SK_LOOKUP(sk_lookup_tcp), 56 BPF_MOV64_IMM(BPF_REG_0, 0), /* leak reference */ 57 BPF_EXIT_INSN(), 58 }, 59 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 60 .errstr = "Unreleased reference", 61 .result = REJECT, 62 }, 63 { 64 "reference tracking: zero potential reference to sock_common", 65 .insns = { 66 BPF_SK_LOOKUP(skc_lookup_tcp), 67 BPF_MOV64_IMM(BPF_REG_0, 0), /* leak reference */ 68 BPF_EXIT_INSN(), 69 }, 70 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 71 .errstr = "Unreleased reference", 72 .result = REJECT, 73 }, 74 { 75 "reference tracking: copy and zero potential references", 76 .insns = { 77 BPF_SK_LOOKUP(sk_lookup_tcp), 78 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 79 BPF_MOV64_IMM(BPF_REG_0, 0), 80 BPF_MOV64_IMM(BPF_REG_7, 0), /* leak reference */ 81 BPF_EXIT_INSN(), 82 }, 83 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 84 .errstr = "Unreleased reference", 85 .result = REJECT, 86 }, 87 { 88 "reference tracking: acquire/release user key reference", 89 .insns = { 90 BPF_MOV64_IMM(BPF_REG_1, -3), 91 BPF_MOV64_IMM(BPF_REG_2, 0), 92 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 93 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 94 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 95 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 96 BPF_MOV64_IMM(BPF_REG_0, 0), 97 BPF_EXIT_INSN(), 98 }, 99 .prog_type = BPF_PROG_TYPE_LSM, 100 .kfunc = "bpf", 101 .expected_attach_type = BPF_LSM_MAC, 102 .flags = BPF_F_SLEEPABLE, 103 .fixup_kfunc_btf_id = { 104 { "bpf_lookup_user_key", 2 }, 105 { "bpf_key_put", 5 }, 106 }, 107 .result = ACCEPT, 108 }, 109 { 110 "reference tracking: acquire/release system key reference", 111 .insns = { 112 BPF_MOV64_IMM(BPF_REG_1, 1), 113 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 114 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 115 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 116 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 117 BPF_MOV64_IMM(BPF_REG_0, 0), 118 BPF_EXIT_INSN(), 119 }, 120 .prog_type = BPF_PROG_TYPE_LSM, 121 .kfunc = "bpf", 122 .expected_attach_type = BPF_LSM_MAC, 123 .flags = BPF_F_SLEEPABLE, 124 .fixup_kfunc_btf_id = { 125 { "bpf_lookup_system_key", 1 }, 126 { "bpf_key_put", 4 }, 127 }, 128 .result = ACCEPT, 129 }, 130 { 131 "reference tracking: release user key reference without check", 132 .insns = { 133 BPF_MOV64_IMM(BPF_REG_1, -3), 134 BPF_MOV64_IMM(BPF_REG_2, 0), 135 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 136 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 137 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 138 BPF_MOV64_IMM(BPF_REG_0, 0), 139 BPF_EXIT_INSN(), 140 }, 141 .prog_type = BPF_PROG_TYPE_LSM, 142 .kfunc = "bpf", 143 .expected_attach_type = BPF_LSM_MAC, 144 .flags = BPF_F_SLEEPABLE, 145 .errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar", 146 .fixup_kfunc_btf_id = { 147 { "bpf_lookup_user_key", 2 }, 148 { "bpf_key_put", 4 }, 149 }, 150 .result = REJECT, 151 }, 152 { 153 "reference tracking: release system key reference without check", 154 .insns = { 155 BPF_MOV64_IMM(BPF_REG_1, 1), 156 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 157 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 158 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 159 BPF_MOV64_IMM(BPF_REG_0, 0), 160 BPF_EXIT_INSN(), 161 }, 162 .prog_type = BPF_PROG_TYPE_LSM, 163 .kfunc = "bpf", 164 .expected_attach_type = BPF_LSM_MAC, 165 .flags = BPF_F_SLEEPABLE, 166 .errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar", 167 .fixup_kfunc_btf_id = { 168 { "bpf_lookup_system_key", 1 }, 169 { "bpf_key_put", 3 }, 170 }, 171 .result = REJECT, 172 }, 173 { 174 "reference tracking: release with NULL key pointer", 175 .insns = { 176 BPF_MOV64_IMM(BPF_REG_1, 0), 177 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 178 BPF_MOV64_IMM(BPF_REG_0, 0), 179 BPF_EXIT_INSN(), 180 }, 181 .prog_type = BPF_PROG_TYPE_LSM, 182 .kfunc = "bpf", 183 .expected_attach_type = BPF_LSM_MAC, 184 .flags = BPF_F_SLEEPABLE, 185 .errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar", 186 .fixup_kfunc_btf_id = { 187 { "bpf_key_put", 1 }, 188 }, 189 .result = REJECT, 190 }, 191 { 192 "reference tracking: leak potential reference to user key", 193 .insns = { 194 BPF_MOV64_IMM(BPF_REG_1, -3), 195 BPF_MOV64_IMM(BPF_REG_2, 0), 196 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 197 BPF_EXIT_INSN(), 198 }, 199 .prog_type = BPF_PROG_TYPE_LSM, 200 .kfunc = "bpf", 201 .expected_attach_type = BPF_LSM_MAC, 202 .flags = BPF_F_SLEEPABLE, 203 .errstr = "Unreleased reference", 204 .fixup_kfunc_btf_id = { 205 { "bpf_lookup_user_key", 2 }, 206 }, 207 .result = REJECT, 208 }, 209 { 210 "reference tracking: leak potential reference to system key", 211 .insns = { 212 BPF_MOV64_IMM(BPF_REG_1, 1), 213 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0), 214 BPF_EXIT_INSN(), 215 }, 216 .prog_type = BPF_PROG_TYPE_LSM, 217 .kfunc = "bpf", 218 .expected_attach_type = BPF_LSM_MAC, 219 .flags = BPF_F_SLEEPABLE, 220 .errstr = "Unreleased reference", 221 .fixup_kfunc_btf_id = { 222 { "bpf_lookup_system_key", 1 }, 223 }, 224 .result = REJECT, 225 }, 226 { 227 "reference tracking: release reference without check", 228 .insns = { 229 BPF_SK_LOOKUP(sk_lookup_tcp), 230 /* reference in r0 may be NULL */ 231 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 232 BPF_MOV64_IMM(BPF_REG_2, 0), 233 BPF_EMIT_CALL(BPF_FUNC_sk_release), 234 BPF_EXIT_INSN(), 235 }, 236 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 237 .errstr = "type=sock_or_null expected=sock", 238 .result = REJECT, 239 }, 240 { 241 "reference tracking: release reference to sock_common without check", 242 .insns = { 243 BPF_SK_LOOKUP(skc_lookup_tcp), 244 /* reference in r0 may be NULL */ 245 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 246 BPF_MOV64_IMM(BPF_REG_2, 0), 247 BPF_EMIT_CALL(BPF_FUNC_sk_release), 248 BPF_EXIT_INSN(), 249 }, 250 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 251 .errstr = "type=sock_common_or_null expected=sock", 252 .result = REJECT, 253 }, 254 { 255 "reference tracking: release reference", 256 .insns = { 257 BPF_SK_LOOKUP(sk_lookup_tcp), 258 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 259 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 260 BPF_EMIT_CALL(BPF_FUNC_sk_release), 261 BPF_EXIT_INSN(), 262 }, 263 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 264 .result = ACCEPT, 265 }, 266 { 267 "reference tracking: release reference to sock_common", 268 .insns = { 269 BPF_SK_LOOKUP(skc_lookup_tcp), 270 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 271 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 272 BPF_EMIT_CALL(BPF_FUNC_sk_release), 273 BPF_EXIT_INSN(), 274 }, 275 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 276 .result = ACCEPT, 277 }, 278 { 279 "reference tracking: release reference 2", 280 .insns = { 281 BPF_SK_LOOKUP(sk_lookup_tcp), 282 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 283 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 284 BPF_EXIT_INSN(), 285 BPF_EMIT_CALL(BPF_FUNC_sk_release), 286 BPF_EXIT_INSN(), 287 }, 288 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 289 .result = ACCEPT, 290 }, 291 { 292 "reference tracking: release reference twice", 293 .insns = { 294 BPF_SK_LOOKUP(sk_lookup_tcp), 295 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 296 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 297 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 298 BPF_EMIT_CALL(BPF_FUNC_sk_release), 299 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 300 BPF_EMIT_CALL(BPF_FUNC_sk_release), 301 BPF_EXIT_INSN(), 302 }, 303 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 304 .errstr = "type=scalar expected=sock", 305 .result = REJECT, 306 }, 307 { 308 "reference tracking: release reference twice inside branch", 309 .insns = { 310 BPF_SK_LOOKUP(sk_lookup_tcp), 311 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 312 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 313 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), /* goto end */ 314 BPF_EMIT_CALL(BPF_FUNC_sk_release), 315 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 316 BPF_EMIT_CALL(BPF_FUNC_sk_release), 317 BPF_EXIT_INSN(), 318 }, 319 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 320 .errstr = "type=scalar expected=sock", 321 .result = REJECT, 322 }, 323 { 324 "reference tracking: alloc, check, free in one subbranch", 325 .insns = { 326 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 327 offsetof(struct __sk_buff, data)), 328 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 329 offsetof(struct __sk_buff, data_end)), 330 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 331 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16), 332 /* if (offsetof(skb, mark) > data_len) exit; */ 333 BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1), 334 BPF_EXIT_INSN(), 335 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2, 336 offsetof(struct __sk_buff, mark)), 337 BPF_SK_LOOKUP(sk_lookup_tcp), 338 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 1), /* mark == 0? */ 339 /* Leak reference in R0 */ 340 BPF_EXIT_INSN(), 341 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */ 342 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 343 BPF_EMIT_CALL(BPF_FUNC_sk_release), 344 BPF_EXIT_INSN(), 345 }, 346 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 347 .errstr = "Unreleased reference", 348 .result = REJECT, 349 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 350 }, 351 { 352 "reference tracking: alloc, check, free in both subbranches", 353 .insns = { 354 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 355 offsetof(struct __sk_buff, data)), 356 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 357 offsetof(struct __sk_buff, data_end)), 358 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 359 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16), 360 /* if (offsetof(skb, mark) > data_len) exit; */ 361 BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1), 362 BPF_EXIT_INSN(), 363 BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2, 364 offsetof(struct __sk_buff, mark)), 365 BPF_SK_LOOKUP(sk_lookup_tcp), 366 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4), /* mark == 0? */ 367 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */ 368 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 369 BPF_EMIT_CALL(BPF_FUNC_sk_release), 370 BPF_EXIT_INSN(), 371 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */ 372 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 373 BPF_EMIT_CALL(BPF_FUNC_sk_release), 374 BPF_EXIT_INSN(), 375 }, 376 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 377 .result = ACCEPT, 378 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 379 }, 380 { 381 "reference tracking in call: free reference in subprog", 382 .insns = { 383 BPF_SK_LOOKUP(sk_lookup_tcp), 384 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */ 385 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 386 BPF_MOV64_IMM(BPF_REG_0, 0), 387 BPF_EXIT_INSN(), 388 389 /* subprog 1 */ 390 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 391 BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1), 392 BPF_EMIT_CALL(BPF_FUNC_sk_release), 393 BPF_EXIT_INSN(), 394 }, 395 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 396 .result = ACCEPT, 397 }, 398 { 399 "reference tracking in call: free reference in subprog and outside", 400 .insns = { 401 BPF_SK_LOOKUP(sk_lookup_tcp), 402 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */ 403 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 404 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 405 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 406 BPF_EMIT_CALL(BPF_FUNC_sk_release), 407 BPF_EXIT_INSN(), 408 409 /* subprog 1 */ 410 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 411 BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1), 412 BPF_EMIT_CALL(BPF_FUNC_sk_release), 413 BPF_EXIT_INSN(), 414 }, 415 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 416 .errstr = "type=scalar expected=sock", 417 .result = REJECT, 418 }, 419 { 420 "reference tracking in call: alloc & leak reference in subprog", 421 .insns = { 422 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 423 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 424 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3), 425 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 426 BPF_MOV64_IMM(BPF_REG_0, 0), 427 BPF_EXIT_INSN(), 428 429 /* subprog 1 */ 430 BPF_MOV64_REG(BPF_REG_6, BPF_REG_4), 431 BPF_SK_LOOKUP(sk_lookup_tcp), 432 /* spill unchecked sk_ptr into stack of caller */ 433 BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), 434 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 435 BPF_EXIT_INSN(), 436 }, 437 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 438 .errstr = "Unreleased reference", 439 .result = REJECT, 440 }, 441 { 442 "reference tracking in call: alloc in subprog, release outside", 443 .insns = { 444 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 445 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4), 446 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 447 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 448 BPF_EMIT_CALL(BPF_FUNC_sk_release), 449 BPF_EXIT_INSN(), 450 451 /* subprog 1 */ 452 BPF_SK_LOOKUP(sk_lookup_tcp), 453 BPF_EXIT_INSN(), /* return sk */ 454 }, 455 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 456 .retval = POINTER_VALUE, 457 .result = ACCEPT, 458 }, 459 { 460 "reference tracking in call: sk_ptr leak into caller stack", 461 .insns = { 462 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 463 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 464 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 465 BPF_MOV64_IMM(BPF_REG_0, 0), 466 BPF_EXIT_INSN(), 467 468 /* subprog 1 */ 469 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), 470 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8), 471 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 472 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5), 473 /* spill unchecked sk_ptr into stack of caller */ 474 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), 475 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8), 476 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0), 477 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0), 478 BPF_EXIT_INSN(), 479 480 /* subprog 2 */ 481 BPF_SK_LOOKUP(sk_lookup_tcp), 482 BPF_EXIT_INSN(), 483 }, 484 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 485 .errstr = "Unreleased reference", 486 .result = REJECT, 487 }, 488 { 489 "reference tracking in call: sk_ptr spill into caller stack", 490 .insns = { 491 BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), 492 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), 493 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2), 494 BPF_MOV64_IMM(BPF_REG_0, 0), 495 BPF_EXIT_INSN(), 496 497 /* subprog 1 */ 498 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), 499 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8), 500 BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0), 501 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 8), 502 /* spill unchecked sk_ptr into stack of caller */ 503 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10), 504 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8), 505 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0), 506 BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0), 507 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 508 /* now the sk_ptr is verified, free the reference */ 509 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_4, 0), 510 BPF_EMIT_CALL(BPF_FUNC_sk_release), 511 BPF_EXIT_INSN(), 512 513 /* subprog 2 */ 514 BPF_SK_LOOKUP(sk_lookup_tcp), 515 BPF_EXIT_INSN(), 516 }, 517 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 518 .result = ACCEPT, 519 }, 520 { 521 "reference tracking: allow LD_ABS", 522 .insns = { 523 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 524 BPF_SK_LOOKUP(sk_lookup_tcp), 525 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 526 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 527 BPF_EMIT_CALL(BPF_FUNC_sk_release), 528 BPF_LD_ABS(BPF_B, 0), 529 BPF_LD_ABS(BPF_H, 0), 530 BPF_LD_ABS(BPF_W, 0), 531 BPF_EXIT_INSN(), 532 }, 533 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 534 .result = ACCEPT, 535 }, 536 { 537 "reference tracking: forbid LD_ABS while holding reference", 538 .insns = { 539 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 540 BPF_SK_LOOKUP(sk_lookup_tcp), 541 BPF_LD_ABS(BPF_B, 0), 542 BPF_LD_ABS(BPF_H, 0), 543 BPF_LD_ABS(BPF_W, 0), 544 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 545 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 546 BPF_EMIT_CALL(BPF_FUNC_sk_release), 547 BPF_EXIT_INSN(), 548 }, 549 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 550 .errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references", 551 .result = REJECT, 552 }, 553 { 554 "reference tracking: allow LD_IND", 555 .insns = { 556 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 557 BPF_SK_LOOKUP(sk_lookup_tcp), 558 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 559 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 560 BPF_EMIT_CALL(BPF_FUNC_sk_release), 561 BPF_MOV64_IMM(BPF_REG_7, 1), 562 BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000), 563 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 564 BPF_EXIT_INSN(), 565 }, 566 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 567 .result = ACCEPT, 568 .retval = 1, 569 }, 570 { 571 "reference tracking: forbid LD_IND while holding reference", 572 .insns = { 573 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 574 BPF_SK_LOOKUP(sk_lookup_tcp), 575 BPF_MOV64_REG(BPF_REG_4, BPF_REG_0), 576 BPF_MOV64_IMM(BPF_REG_7, 1), 577 BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000), 578 BPF_MOV64_REG(BPF_REG_0, BPF_REG_7), 579 BPF_MOV64_REG(BPF_REG_1, BPF_REG_4), 580 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 581 BPF_EMIT_CALL(BPF_FUNC_sk_release), 582 BPF_EXIT_INSN(), 583 }, 584 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 585 .errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references", 586 .result = REJECT, 587 }, 588 { 589 "reference tracking: check reference or tail call", 590 .insns = { 591 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1), 592 BPF_SK_LOOKUP(sk_lookup_tcp), 593 /* if (sk) bpf_sk_release() */ 594 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 595 BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7), 596 /* bpf_tail_call() */ 597 BPF_MOV64_IMM(BPF_REG_3, 3), 598 BPF_LD_MAP_FD(BPF_REG_2, 0), 599 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 600 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), 601 BPF_MOV64_IMM(BPF_REG_0, 0), 602 BPF_EXIT_INSN(), 603 BPF_EMIT_CALL(BPF_FUNC_sk_release), 604 BPF_EXIT_INSN(), 605 }, 606 .fixup_prog1 = { 17 }, 607 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 608 .result = ACCEPT, 609 }, 610 { 611 "reference tracking: release reference then tail call", 612 .insns = { 613 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1), 614 BPF_SK_LOOKUP(sk_lookup_tcp), 615 /* if (sk) bpf_sk_release() */ 616 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 617 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 618 BPF_EMIT_CALL(BPF_FUNC_sk_release), 619 /* bpf_tail_call() */ 620 BPF_MOV64_IMM(BPF_REG_3, 3), 621 BPF_LD_MAP_FD(BPF_REG_2, 0), 622 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 623 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), 624 BPF_MOV64_IMM(BPF_REG_0, 0), 625 BPF_EXIT_INSN(), 626 }, 627 .fixup_prog1 = { 18 }, 628 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 629 .result = ACCEPT, 630 }, 631 { 632 "reference tracking: leak possible reference over tail call", 633 .insns = { 634 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1), 635 /* Look up socket and store in REG_6 */ 636 BPF_SK_LOOKUP(sk_lookup_tcp), 637 /* bpf_tail_call() */ 638 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 639 BPF_MOV64_IMM(BPF_REG_3, 3), 640 BPF_LD_MAP_FD(BPF_REG_2, 0), 641 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 642 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), 643 BPF_MOV64_IMM(BPF_REG_0, 0), 644 /* if (sk) bpf_sk_release() */ 645 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 646 BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), 647 BPF_EMIT_CALL(BPF_FUNC_sk_release), 648 BPF_EXIT_INSN(), 649 }, 650 .fixup_prog1 = { 16 }, 651 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 652 .errstr = "tail_call would lead to reference leak", 653 .result = REJECT, 654 }, 655 { 656 "reference tracking: leak checked reference over tail call", 657 .insns = { 658 BPF_MOV64_REG(BPF_REG_7, BPF_REG_1), 659 /* Look up socket and store in REG_6 */ 660 BPF_SK_LOOKUP(sk_lookup_tcp), 661 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 662 /* if (!sk) goto end */ 663 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), 664 /* bpf_tail_call() */ 665 BPF_MOV64_IMM(BPF_REG_3, 0), 666 BPF_LD_MAP_FD(BPF_REG_2, 0), 667 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), 668 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), 669 BPF_MOV64_IMM(BPF_REG_0, 0), 670 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 671 BPF_EMIT_CALL(BPF_FUNC_sk_release), 672 BPF_EXIT_INSN(), 673 }, 674 .fixup_prog1 = { 17 }, 675 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 676 .errstr = "tail_call would lead to reference leak", 677 .result = REJECT, 678 }, 679 { 680 "reference tracking: mangle and release sock_or_null", 681 .insns = { 682 BPF_SK_LOOKUP(sk_lookup_tcp), 683 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 684 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5), 685 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), 686 BPF_EMIT_CALL(BPF_FUNC_sk_release), 687 BPF_EXIT_INSN(), 688 }, 689 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 690 .errstr = "R1 pointer arithmetic on sock_or_null prohibited", 691 .result = REJECT, 692 }, 693 { 694 "reference tracking: mangle and release sock", 695 .insns = { 696 BPF_SK_LOOKUP(sk_lookup_tcp), 697 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 698 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 699 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5), 700 BPF_EMIT_CALL(BPF_FUNC_sk_release), 701 BPF_EXIT_INSN(), 702 }, 703 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 704 .errstr = "R1 pointer arithmetic on sock prohibited", 705 .result = REJECT, 706 }, 707 { 708 "reference tracking: access member", 709 .insns = { 710 BPF_SK_LOOKUP(sk_lookup_tcp), 711 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 712 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), 713 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4), 714 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 715 BPF_EMIT_CALL(BPF_FUNC_sk_release), 716 BPF_EXIT_INSN(), 717 }, 718 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 719 .result = ACCEPT, 720 }, 721 { 722 "reference tracking: write to member", 723 .insns = { 724 BPF_SK_LOOKUP(sk_lookup_tcp), 725 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 726 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), 727 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 728 BPF_LD_IMM64(BPF_REG_2, 42), 729 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_2, 730 offsetof(struct bpf_sock, mark)), 731 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 732 BPF_EMIT_CALL(BPF_FUNC_sk_release), 733 BPF_LD_IMM64(BPF_REG_0, 0), 734 BPF_EXIT_INSN(), 735 }, 736 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 737 .errstr = "cannot write into sock", 738 .result = REJECT, 739 }, 740 { 741 "reference tracking: invalid 64-bit access of member", 742 .insns = { 743 BPF_SK_LOOKUP(sk_lookup_tcp), 744 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 745 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), 746 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0), 747 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 748 BPF_EMIT_CALL(BPF_FUNC_sk_release), 749 BPF_EXIT_INSN(), 750 }, 751 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 752 .errstr = "invalid sock access off=0 size=8", 753 .result = REJECT, 754 }, 755 { 756 "reference tracking: access after release", 757 .insns = { 758 BPF_SK_LOOKUP(sk_lookup_tcp), 759 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 760 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), 761 BPF_EMIT_CALL(BPF_FUNC_sk_release), 762 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 763 BPF_EXIT_INSN(), 764 }, 765 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 766 .errstr = "!read_ok", 767 .result = REJECT, 768 }, 769 { 770 "reference tracking: direct access for lookup", 771 .insns = { 772 /* Check that the packet is at least 64B long */ 773 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 774 offsetof(struct __sk_buff, data)), 775 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 776 offsetof(struct __sk_buff, data_end)), 777 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), 778 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 64), 779 BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 9), 780 /* sk = sk_lookup_tcp(ctx, skb->data, ...) */ 781 BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)), 782 BPF_MOV64_IMM(BPF_REG_4, 0), 783 BPF_MOV64_IMM(BPF_REG_5, 0), 784 BPF_EMIT_CALL(BPF_FUNC_sk_lookup_tcp), 785 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 786 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), 787 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4), 788 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 789 BPF_EMIT_CALL(BPF_FUNC_sk_release), 790 BPF_EXIT_INSN(), 791 }, 792 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 793 .result = ACCEPT, 794 }, 795 { 796 "reference tracking: use ptr from bpf_tcp_sock() after release", 797 .insns = { 798 BPF_SK_LOOKUP(sk_lookup_tcp), 799 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 800 BPF_EXIT_INSN(), 801 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 802 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 803 BPF_EMIT_CALL(BPF_FUNC_tcp_sock), 804 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 805 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 806 BPF_EMIT_CALL(BPF_FUNC_sk_release), 807 BPF_EXIT_INSN(), 808 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 809 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 810 BPF_EMIT_CALL(BPF_FUNC_sk_release), 811 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)), 812 BPF_EXIT_INSN(), 813 }, 814 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 815 .result = REJECT, 816 .errstr = "invalid mem access", 817 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 818 }, 819 { 820 "reference tracking: use ptr from bpf_sk_fullsock() after release", 821 .insns = { 822 BPF_SK_LOOKUP(sk_lookup_tcp), 823 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 824 BPF_EXIT_INSN(), 825 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 826 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 827 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), 828 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 829 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 830 BPF_EMIT_CALL(BPF_FUNC_sk_release), 831 BPF_EXIT_INSN(), 832 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 833 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 834 BPF_EMIT_CALL(BPF_FUNC_sk_release), 835 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)), 836 BPF_EXIT_INSN(), 837 }, 838 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 839 .result = REJECT, 840 .errstr = "invalid mem access", 841 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 842 }, 843 { 844 "reference tracking: use ptr from bpf_sk_fullsock(tp) after release", 845 .insns = { 846 BPF_SK_LOOKUP(sk_lookup_tcp), 847 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 848 BPF_EXIT_INSN(), 849 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 850 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 851 BPF_EMIT_CALL(BPF_FUNC_tcp_sock), 852 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 853 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 854 BPF_EMIT_CALL(BPF_FUNC_sk_release), 855 BPF_EXIT_INSN(), 856 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 857 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), 858 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 859 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 860 BPF_EMIT_CALL(BPF_FUNC_sk_release), 861 BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1), 862 BPF_EXIT_INSN(), 863 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), 864 BPF_EXIT_INSN(), 865 }, 866 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 867 .result = REJECT, 868 .errstr = "invalid mem access", 869 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 870 }, 871 { 872 "reference tracking: use sk after bpf_sk_release(tp)", 873 .insns = { 874 BPF_SK_LOOKUP(sk_lookup_tcp), 875 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 876 BPF_EXIT_INSN(), 877 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 878 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 879 BPF_EMIT_CALL(BPF_FUNC_tcp_sock), 880 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 881 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 882 BPF_EMIT_CALL(BPF_FUNC_sk_release), 883 BPF_EXIT_INSN(), 884 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 885 BPF_EMIT_CALL(BPF_FUNC_sk_release), 886 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), 887 BPF_EXIT_INSN(), 888 }, 889 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 890 .result = REJECT, 891 .errstr = "invalid mem access", 892 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 893 }, 894 { 895 "reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)", 896 .insns = { 897 BPF_SK_LOOKUP(sk_lookup_tcp), 898 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 899 BPF_EXIT_INSN(), 900 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 901 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 902 BPF_EMIT_CALL(BPF_FUNC_get_listener_sock), 903 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 904 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 905 BPF_EMIT_CALL(BPF_FUNC_sk_release), 906 BPF_EXIT_INSN(), 907 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 908 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 909 BPF_EMIT_CALL(BPF_FUNC_sk_release), 910 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)), 911 BPF_EXIT_INSN(), 912 }, 913 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 914 .result = ACCEPT, 915 }, 916 { 917 "reference tracking: bpf_sk_release(listen_sk)", 918 .insns = { 919 BPF_SK_LOOKUP(sk_lookup_tcp), 920 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 921 BPF_EXIT_INSN(), 922 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 923 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 924 BPF_EMIT_CALL(BPF_FUNC_get_listener_sock), 925 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 926 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 927 BPF_EMIT_CALL(BPF_FUNC_sk_release), 928 BPF_EXIT_INSN(), 929 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 930 BPF_EMIT_CALL(BPF_FUNC_sk_release), 931 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)), 932 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 933 BPF_EMIT_CALL(BPF_FUNC_sk_release), 934 BPF_EXIT_INSN(), 935 }, 936 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 937 .result = REJECT, 938 .errstr = "R1 must be referenced when passed to release function", 939 }, 940 { 941 /* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */ 942 "reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)", 943 .insns = { 944 BPF_SK_LOOKUP(sk_lookup_tcp), 945 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 946 BPF_EXIT_INSN(), 947 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 948 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 949 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), 950 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 951 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 952 BPF_EMIT_CALL(BPF_FUNC_tcp_sock), 953 BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), 954 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3), 955 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 956 BPF_EMIT_CALL(BPF_FUNC_sk_release), 957 BPF_EXIT_INSN(), 958 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)), 959 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 960 BPF_EMIT_CALL(BPF_FUNC_sk_release), 961 BPF_EXIT_INSN(), 962 }, 963 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 964 .result = REJECT, 965 .errstr = "invalid mem access", 966 }, 967 { 968 "reference tracking: branch tracking valid pointer null comparison", 969 .insns = { 970 BPF_SK_LOOKUP(sk_lookup_tcp), 971 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 972 BPF_MOV64_IMM(BPF_REG_3, 1), 973 BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1), 974 BPF_MOV64_IMM(BPF_REG_3, 0), 975 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 2), 976 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 977 BPF_EMIT_CALL(BPF_FUNC_sk_release), 978 BPF_EXIT_INSN(), 979 }, 980 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 981 .result = ACCEPT, 982 }, 983 { 984 "reference tracking: branch tracking valid pointer value comparison", 985 .insns = { 986 BPF_SK_LOOKUP(sk_lookup_tcp), 987 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 988 BPF_MOV64_IMM(BPF_REG_3, 1), 989 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4), 990 BPF_MOV64_IMM(BPF_REG_3, 0), 991 BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 1234, 2), 992 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 993 BPF_EMIT_CALL(BPF_FUNC_sk_release), 994 BPF_EXIT_INSN(), 995 }, 996 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 997 .errstr = "Unreleased reference", 998 .result = REJECT, 999 }, 1000 { 1001 "reference tracking: bpf_sk_release(btf_tcp_sock)", 1002 .insns = { 1003 BPF_SK_LOOKUP(sk_lookup_tcp), 1004 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 1005 BPF_EXIT_INSN(), 1006 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 1007 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 1008 BPF_EMIT_CALL(BPF_FUNC_skc_to_tcp_sock), 1009 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 1010 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 1011 BPF_EMIT_CALL(BPF_FUNC_sk_release), 1012 BPF_EXIT_INSN(), 1013 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 1014 BPF_EMIT_CALL(BPF_FUNC_sk_release), 1015 BPF_EXIT_INSN(), 1016 }, 1017 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 1018 .result = ACCEPT, 1019 .result_unpriv = REJECT, 1020 .errstr_unpriv = "unknown func", 1021 }, 1022 { 1023 "reference tracking: use ptr from bpf_skc_to_tcp_sock() after release", 1024 .insns = { 1025 BPF_SK_LOOKUP(sk_lookup_tcp), 1026 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 1027 BPF_EXIT_INSN(), 1028 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), 1029 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), 1030 BPF_EMIT_CALL(BPF_FUNC_skc_to_tcp_sock), 1031 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3), 1032 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 1033 BPF_EMIT_CALL(BPF_FUNC_sk_release), 1034 BPF_EXIT_INSN(), 1035 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), 1036 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), 1037 BPF_EMIT_CALL(BPF_FUNC_sk_release), 1038 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_7, 0), 1039 BPF_EXIT_INSN(), 1040 }, 1041 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 1042 .result = REJECT, 1043 .errstr = "invalid mem access", 1044 .result_unpriv = REJECT, 1045 .errstr_unpriv = "unknown func", 1046 }, 1047 { 1048 "reference tracking: try to leak released ptr reg", 1049 .insns = { 1050 BPF_MOV64_IMM(BPF_REG_0, 0), 1051 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), 1052 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 1053 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), 1054 BPF_LD_MAP_FD(BPF_REG_1, 0), 1055 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 1056 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 1057 BPF_EXIT_INSN(), 1058 BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), 1059 1060 BPF_MOV64_IMM(BPF_REG_0, 0), 1061 BPF_LD_MAP_FD(BPF_REG_1, 0), 1062 BPF_MOV64_IMM(BPF_REG_2, 8), 1063 BPF_MOV64_IMM(BPF_REG_3, 0), 1064 BPF_EMIT_CALL(BPF_FUNC_ringbuf_reserve), 1065 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), 1066 BPF_EXIT_INSN(), 1067 BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), 1068 1069 BPF_MOV64_REG(BPF_REG_1, BPF_REG_8), 1070 BPF_MOV64_IMM(BPF_REG_2, 0), 1071 BPF_EMIT_CALL(BPF_FUNC_ringbuf_discard), 1072 BPF_MOV64_IMM(BPF_REG_0, 0), 1073 1074 BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_8, 0), 1075 BPF_EXIT_INSN() 1076 }, 1077 .fixup_map_array_48b = { 4 }, 1078 .fixup_map_ringbuf = { 11 }, 1079 .result = ACCEPT, 1080 .result_unpriv = REJECT, 1081 .errstr_unpriv = "R8 !read_ok" 1082 }, 1083