diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-25 22:54:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-05-25 22:54:42 -0400 |
commit | 03250e1028057173b212341015d5fbf53327042c (patch) | |
tree | 1d43ff6bc664227f8ac42ba0a7e897dc51986095 /kernel/bpf | |
parent | 62d18ecfa64137349fac9c5817784fbd48b54f48 (diff) | |
parent | eb110410b9f6477726026669f3f0c0567e8241e6 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
"Let's begin the holiday weekend with some networking fixes:
1) Whoops need to restrict cfg80211 wiphy names even more to 64
bytes. From Eric Biggers.
2) Fix flags being ignored when using kernel_connect() with SCTP,
from Xin Long.
3) Use after free in DCCP, from Alexey Kodanev.
4) Need to check rhltable_init() return value in ipmr code, from Eric
Dumazet.
5) XDP handling fixes in virtio_net from Jason Wang.
6) Missing RTA_TABLE in rtm_ipv4_policy[], from Roopa Prabhu.
7) Need to use IRQ disabling spinlocks in mlx4_qp_lookup(), from Jack
Morgenstein.
8) Prevent out-of-bounds speculation using indexes in BPF, from
Daniel Borkmann.
9) Fix regression added by AF_PACKET link layer cure, from Willem de
Bruijn.
10) Correct ENIC dma mask, from Govindarajulu Varadarajan.
11) Missing config options for PMTU tests, from Stefano Brivio"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (48 commits)
ibmvnic: Fix partial success login retries
selftests/net: Add missing config options for PMTU tests
mlx4_core: allocate ICM memory in page size chunks
enic: set DMA mask to 47 bit
ppp: remove the PPPIOCDETACH ioctl
ipv4: remove warning in ip_recv_error
net : sched: cls_api: deal with egdev path only if needed
vhost: synchronize IOTLB message with dev cleanup
packet: fix reserve calculation
net/mlx5: IPSec, Fix a race between concurrent sandbox QP commands
net/mlx5e: When RXFCS is set, add FCS data into checksum calculation
bpf: properly enforce index mask to prevent out-of-bounds speculation
net/mlx4: Fix irq-unsafe spinlock usage
net: phy: broadcom: Fix bcm_write_exp()
net: phy: broadcom: Fix auxiliary control register reads
net: ipv4: add missing RTA_TABLE to rtm_ipv4_policy
net/mlx4: fix spelling mistake: "Inrerface" -> "Interface" and rephrase message
ibmvnic: Only do H_EOI for mobility events
tuntap: correctly set SOCKWQ_ASYNC_NOSPACE
virtio-net: fix leaking page for gso packet during mergeable XDP
...
Diffstat (limited to 'kernel/bpf')
-rw-r--r-- | kernel/bpf/verifier.c | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2ce967a63ede..1904e814f282 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -156,7 +156,29 @@ struct bpf_verifier_stack_elem { | |||
156 | #define BPF_COMPLEXITY_LIMIT_INSNS 131072 | 156 | #define BPF_COMPLEXITY_LIMIT_INSNS 131072 |
157 | #define BPF_COMPLEXITY_LIMIT_STACK 1024 | 157 | #define BPF_COMPLEXITY_LIMIT_STACK 1024 |
158 | 158 | ||
159 | #define BPF_MAP_PTR_POISON ((void *)0xeB9F + POISON_POINTER_DELTA) | 159 | #define BPF_MAP_PTR_UNPRIV 1UL |
160 | #define BPF_MAP_PTR_POISON ((void *)((0xeB9FUL << 1) + \ | ||
161 | POISON_POINTER_DELTA)) | ||
162 | #define BPF_MAP_PTR(X) ((struct bpf_map *)((X) & ~BPF_MAP_PTR_UNPRIV)) | ||
163 | |||
164 | static bool bpf_map_ptr_poisoned(const struct bpf_insn_aux_data *aux) | ||
165 | { | ||
166 | return BPF_MAP_PTR(aux->map_state) == BPF_MAP_PTR_POISON; | ||
167 | } | ||
168 | |||
169 | static bool bpf_map_ptr_unpriv(const struct bpf_insn_aux_data *aux) | ||
170 | { | ||
171 | return aux->map_state & BPF_MAP_PTR_UNPRIV; | ||
172 | } | ||
173 | |||
174 | static void bpf_map_ptr_store(struct bpf_insn_aux_data *aux, | ||
175 | const struct bpf_map *map, bool unpriv) | ||
176 | { | ||
177 | BUILD_BUG_ON((unsigned long)BPF_MAP_PTR_POISON & BPF_MAP_PTR_UNPRIV); | ||
178 | unpriv |= bpf_map_ptr_unpriv(aux); | ||
179 | aux->map_state = (unsigned long)map | | ||
180 | (unpriv ? BPF_MAP_PTR_UNPRIV : 0UL); | ||
181 | } | ||
160 | 182 | ||
161 | struct bpf_call_arg_meta { | 183 | struct bpf_call_arg_meta { |
162 | struct bpf_map *map_ptr; | 184 | struct bpf_map *map_ptr; |
@@ -2358,6 +2380,29 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) | |||
2358 | return 0; | 2380 | return 0; |
2359 | } | 2381 | } |
2360 | 2382 | ||
2383 | static int | ||
2384 | record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta, | ||
2385 | int func_id, int insn_idx) | ||
2386 | { | ||
2387 | struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx]; | ||
2388 | |||
2389 | if (func_id != BPF_FUNC_tail_call && | ||
2390 | func_id != BPF_FUNC_map_lookup_elem) | ||
2391 | return 0; | ||
2392 | if (meta->map_ptr == NULL) { | ||
2393 | verbose(env, "kernel subsystem misconfigured verifier\n"); | ||
2394 | return -EINVAL; | ||
2395 | } | ||
2396 | |||
2397 | if (!BPF_MAP_PTR(aux->map_state)) | ||
2398 | bpf_map_ptr_store(aux, meta->map_ptr, | ||
2399 | meta->map_ptr->unpriv_array); | ||
2400 | else if (BPF_MAP_PTR(aux->map_state) != meta->map_ptr) | ||
2401 | bpf_map_ptr_store(aux, BPF_MAP_PTR_POISON, | ||
2402 | meta->map_ptr->unpriv_array); | ||
2403 | return 0; | ||
2404 | } | ||
2405 | |||
2361 | static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn_idx) | 2406 | static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn_idx) |
2362 | { | 2407 | { |
2363 | const struct bpf_func_proto *fn = NULL; | 2408 | const struct bpf_func_proto *fn = NULL; |
@@ -2412,13 +2457,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2412 | err = check_func_arg(env, BPF_REG_2, fn->arg2_type, &meta); | 2457 | err = check_func_arg(env, BPF_REG_2, fn->arg2_type, &meta); |
2413 | if (err) | 2458 | if (err) |
2414 | return err; | 2459 | return err; |
2415 | if (func_id == BPF_FUNC_tail_call) { | ||
2416 | if (meta.map_ptr == NULL) { | ||
2417 | verbose(env, "verifier bug\n"); | ||
2418 | return -EINVAL; | ||
2419 | } | ||
2420 | env->insn_aux_data[insn_idx].map_ptr = meta.map_ptr; | ||
2421 | } | ||
2422 | err = check_func_arg(env, BPF_REG_3, fn->arg3_type, &meta); | 2460 | err = check_func_arg(env, BPF_REG_3, fn->arg3_type, &meta); |
2423 | if (err) | 2461 | if (err) |
2424 | return err; | 2462 | return err; |
@@ -2429,6 +2467,10 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2429 | if (err) | 2467 | if (err) |
2430 | return err; | 2468 | return err; |
2431 | 2469 | ||
2470 | err = record_func_map(env, &meta, func_id, insn_idx); | ||
2471 | if (err) | ||
2472 | return err; | ||
2473 | |||
2432 | /* Mark slots with STACK_MISC in case of raw mode, stack offset | 2474 | /* Mark slots with STACK_MISC in case of raw mode, stack offset |
2433 | * is inferred from register state. | 2475 | * is inferred from register state. |
2434 | */ | 2476 | */ |
@@ -2453,8 +2495,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2453 | } else if (fn->ret_type == RET_VOID) { | 2495 | } else if (fn->ret_type == RET_VOID) { |
2454 | regs[BPF_REG_0].type = NOT_INIT; | 2496 | regs[BPF_REG_0].type = NOT_INIT; |
2455 | } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL) { | 2497 | } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL) { |
2456 | struct bpf_insn_aux_data *insn_aux; | ||
2457 | |||
2458 | regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; | 2498 | regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; |
2459 | /* There is no offset yet applied, variable or fixed */ | 2499 | /* There is no offset yet applied, variable or fixed */ |
2460 | mark_reg_known_zero(env, regs, BPF_REG_0); | 2500 | mark_reg_known_zero(env, regs, BPF_REG_0); |
@@ -2470,11 +2510,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2470 | } | 2510 | } |
2471 | regs[BPF_REG_0].map_ptr = meta.map_ptr; | 2511 | regs[BPF_REG_0].map_ptr = meta.map_ptr; |
2472 | regs[BPF_REG_0].id = ++env->id_gen; | 2512 | regs[BPF_REG_0].id = ++env->id_gen; |
2473 | insn_aux = &env->insn_aux_data[insn_idx]; | ||
2474 | if (!insn_aux->map_ptr) | ||
2475 | insn_aux->map_ptr = meta.map_ptr; | ||
2476 | else if (insn_aux->map_ptr != meta.map_ptr) | ||
2477 | insn_aux->map_ptr = BPF_MAP_PTR_POISON; | ||
2478 | } else { | 2513 | } else { |
2479 | verbose(env, "unknown return type %d of func %s#%d\n", | 2514 | verbose(env, "unknown return type %d of func %s#%d\n", |
2480 | fn->ret_type, func_id_name(func_id), func_id); | 2515 | fn->ret_type, func_id_name(func_id), func_id); |
@@ -5470,6 +5505,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) | |||
5470 | struct bpf_insn *insn = prog->insnsi; | 5505 | struct bpf_insn *insn = prog->insnsi; |
5471 | const struct bpf_func_proto *fn; | 5506 | const struct bpf_func_proto *fn; |
5472 | const int insn_cnt = prog->len; | 5507 | const int insn_cnt = prog->len; |
5508 | struct bpf_insn_aux_data *aux; | ||
5473 | struct bpf_insn insn_buf[16]; | 5509 | struct bpf_insn insn_buf[16]; |
5474 | struct bpf_prog *new_prog; | 5510 | struct bpf_prog *new_prog; |
5475 | struct bpf_map *map_ptr; | 5511 | struct bpf_map *map_ptr; |
@@ -5544,19 +5580,22 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) | |||
5544 | insn->imm = 0; | 5580 | insn->imm = 0; |
5545 | insn->code = BPF_JMP | BPF_TAIL_CALL; | 5581 | insn->code = BPF_JMP | BPF_TAIL_CALL; |
5546 | 5582 | ||
5583 | aux = &env->insn_aux_data[i + delta]; | ||
5584 | if (!bpf_map_ptr_unpriv(aux)) | ||
5585 | continue; | ||
5586 | |||
5547 | /* instead of changing every JIT dealing with tail_call | 5587 | /* instead of changing every JIT dealing with tail_call |
5548 | * emit two extra insns: | 5588 | * emit two extra insns: |
5549 | * if (index >= max_entries) goto out; | 5589 | * if (index >= max_entries) goto out; |
5550 | * index &= array->index_mask; | 5590 | * index &= array->index_mask; |
5551 | * to avoid out-of-bounds cpu speculation | 5591 | * to avoid out-of-bounds cpu speculation |
5552 | */ | 5592 | */ |
5553 | map_ptr = env->insn_aux_data[i + delta].map_ptr; | 5593 | if (bpf_map_ptr_poisoned(aux)) { |
5554 | if (map_ptr == BPF_MAP_PTR_POISON) { | ||
5555 | verbose(env, "tail_call abusing map_ptr\n"); | 5594 | verbose(env, "tail_call abusing map_ptr\n"); |
5556 | return -EINVAL; | 5595 | return -EINVAL; |
5557 | } | 5596 | } |
5558 | if (!map_ptr->unpriv_array) | 5597 | |
5559 | continue; | 5598 | map_ptr = BPF_MAP_PTR(aux->map_state); |
5560 | insn_buf[0] = BPF_JMP_IMM(BPF_JGE, BPF_REG_3, | 5599 | insn_buf[0] = BPF_JMP_IMM(BPF_JGE, BPF_REG_3, |
5561 | map_ptr->max_entries, 2); | 5600 | map_ptr->max_entries, 2); |
5562 | insn_buf[1] = BPF_ALU32_IMM(BPF_AND, BPF_REG_3, | 5601 | insn_buf[1] = BPF_ALU32_IMM(BPF_AND, BPF_REG_3, |
@@ -5580,9 +5619,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) | |||
5580 | */ | 5619 | */ |
5581 | if (prog->jit_requested && BITS_PER_LONG == 64 && | 5620 | if (prog->jit_requested && BITS_PER_LONG == 64 && |
5582 | insn->imm == BPF_FUNC_map_lookup_elem) { | 5621 | insn->imm == BPF_FUNC_map_lookup_elem) { |
5583 | map_ptr = env->insn_aux_data[i + delta].map_ptr; | 5622 | aux = &env->insn_aux_data[i + delta]; |
5584 | if (map_ptr == BPF_MAP_PTR_POISON || | 5623 | if (bpf_map_ptr_poisoned(aux)) |
5585 | !map_ptr->ops->map_gen_lookup) | 5624 | goto patch_call_imm; |
5625 | |||
5626 | map_ptr = BPF_MAP_PTR(aux->map_state); | ||
5627 | if (!map_ptr->ops->map_gen_lookup) | ||
5586 | goto patch_call_imm; | 5628 | goto patch_call_imm; |
5587 | 5629 | ||
5588 | cnt = map_ptr->ops->map_gen_lookup(map_ptr, insn_buf); | 5630 | cnt = map_ptr->ops->map_gen_lookup(map_ptr, insn_buf); |