diff options
author | John Fastabend <john.fastabend@gmail.com> | 2018-09-18 12:01:44 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-09-21 20:46:41 -0400 |
commit | 5607fff303636d48b88414c6be353d9fed700af2 (patch) | |
tree | be7338b7007ecd330061ccbe9b00e339575c6f60 /kernel | |
parent | 080220b687147fd9376878534aba7194f17f6ef5 (diff) |
bpf: sockmap only allow ESTABLISHED sock state
After this patch we only allow socks that are in ESTABLISHED state or
are being added via a sock_ops event that is transitioning into an
ESTABLISHED state. By allowing sock_ops events we allow users to
manage sockmaps directly from sock ops programs. The two supported
sock_ops ops are BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB and
BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB.
Similar to TLS ULP this ensures sk_user_data is correct.
Reported-by: Eric Dumazet <edumazet@google.com>
Fixes: 1aa12bdf1bfb ("bpf: sockmap, add sock close() hook to remove socks")
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/bpf/sockmap.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 488ef9663c01..1f97b559892a 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c | |||
@@ -2097,8 +2097,12 @@ static int sock_map_update_elem(struct bpf_map *map, | |||
2097 | return -EINVAL; | 2097 | return -EINVAL; |
2098 | } | 2098 | } |
2099 | 2099 | ||
2100 | /* ULPs are currently supported only for TCP sockets in ESTABLISHED | ||
2101 | * state. | ||
2102 | */ | ||
2100 | if (skops.sk->sk_type != SOCK_STREAM || | 2103 | if (skops.sk->sk_type != SOCK_STREAM || |
2101 | skops.sk->sk_protocol != IPPROTO_TCP) { | 2104 | skops.sk->sk_protocol != IPPROTO_TCP || |
2105 | skops.sk->sk_state != TCP_ESTABLISHED) { | ||
2102 | fput(socket->file); | 2106 | fput(socket->file); |
2103 | return -EOPNOTSUPP; | 2107 | return -EOPNOTSUPP; |
2104 | } | 2108 | } |
@@ -2453,6 +2457,16 @@ static int sock_hash_update_elem(struct bpf_map *map, | |||
2453 | return -EINVAL; | 2457 | return -EINVAL; |
2454 | } | 2458 | } |
2455 | 2459 | ||
2460 | /* ULPs are currently supported only for TCP sockets in ESTABLISHED | ||
2461 | * state. | ||
2462 | */ | ||
2463 | if (skops.sk->sk_type != SOCK_STREAM || | ||
2464 | skops.sk->sk_protocol != IPPROTO_TCP || | ||
2465 | skops.sk->sk_state != TCP_ESTABLISHED) { | ||
2466 | fput(socket->file); | ||
2467 | return -EOPNOTSUPP; | ||
2468 | } | ||
2469 | |||
2456 | lock_sock(skops.sk); | 2470 | lock_sock(skops.sk); |
2457 | preempt_disable(); | 2471 | preempt_disable(); |
2458 | rcu_read_lock(); | 2472 | rcu_read_lock(); |
@@ -2543,10 +2557,22 @@ const struct bpf_map_ops sock_hash_ops = { | |||
2543 | .map_check_btf = map_check_no_btf, | 2557 | .map_check_btf = map_check_no_btf, |
2544 | }; | 2558 | }; |
2545 | 2559 | ||
2560 | static bool bpf_is_valid_sock_op(struct bpf_sock_ops_kern *ops) | ||
2561 | { | ||
2562 | return ops->op == BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB || | ||
2563 | ops->op == BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB; | ||
2564 | } | ||
2546 | BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock, | 2565 | BPF_CALL_4(bpf_sock_map_update, struct bpf_sock_ops_kern *, bpf_sock, |
2547 | struct bpf_map *, map, void *, key, u64, flags) | 2566 | struct bpf_map *, map, void *, key, u64, flags) |
2548 | { | 2567 | { |
2549 | WARN_ON_ONCE(!rcu_read_lock_held()); | 2568 | WARN_ON_ONCE(!rcu_read_lock_held()); |
2569 | |||
2570 | /* ULPs are currently supported only for TCP sockets in ESTABLISHED | ||
2571 | * state. This checks that the sock ops triggering the update is | ||
2572 | * one indicating we are (or will be soon) in an ESTABLISHED state. | ||
2573 | */ | ||
2574 | if (!bpf_is_valid_sock_op(bpf_sock)) | ||
2575 | return -EOPNOTSUPP; | ||
2550 | return sock_map_ctx_update_elem(bpf_sock, map, key, flags); | 2576 | return sock_map_ctx_update_elem(bpf_sock, map, key, flags); |
2551 | } | 2577 | } |
2552 | 2578 | ||
@@ -2565,6 +2591,9 @@ BPF_CALL_4(bpf_sock_hash_update, struct bpf_sock_ops_kern *, bpf_sock, | |||
2565 | struct bpf_map *, map, void *, key, u64, flags) | 2591 | struct bpf_map *, map, void *, key, u64, flags) |
2566 | { | 2592 | { |
2567 | WARN_ON_ONCE(!rcu_read_lock_held()); | 2593 | WARN_ON_ONCE(!rcu_read_lock_held()); |
2594 | |||
2595 | if (!bpf_is_valid_sock_op(bpf_sock)) | ||
2596 | return -EOPNOTSUPP; | ||
2568 | return sock_hash_ctx_update_elem(bpf_sock, map, key, flags); | 2597 | return sock_hash_ctx_update_elem(bpf_sock, map, key, flags); |
2569 | } | 2598 | } |
2570 | 2599 | ||