forked from TencentOS/TencentOS-kernel
bpf: sockmap: Only check ULP for TCP sockets
[upstream commit 7b70973d7edb2f005511102d5a2e0116464a46a1] The sock map code checks that a socket does not have an active upper layer protocol before inserting it into the map. This requires casting via inet_csk, which isn't valid for UDP sockets. Guard checks for ULP by checking inet_sk(sk)->is_icsk first. Signed-off-by: Lorenz Bauer <lmb@cloudflare.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20200309111243.6982-2-lmb@cloudflare.com
This commit is contained in:
parent
2c5d45a7ab
commit
c8a5faba5a
|
|
@ -367,8 +367,13 @@ static inline void sk_psock_restore_proto(struct sock *sk,
|
|||
* unhash handler.
|
||||
*/
|
||||
WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash);
|
||||
tcp_update_ulp(sk, psock->sk_proto,
|
||||
psock->saved_write_space);
|
||||
if (inet_csk_has_ulp(sk)) {
|
||||
tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space);
|
||||
} else {
|
||||
sk->sk_write_space = psock->saved_write_space;
|
||||
/* Pairs with lockless read in sk_clone_lock() */
|
||||
WRITE_ONCE(sk->sk_prot, psock->sk_proto);
|
||||
}
|
||||
} else {
|
||||
sk->sk_prot = psock->sk_proto;
|
||||
sk->sk_write_space = psock->saved_write_space;
|
||||
|
|
|
|||
|
|
@ -342,4 +342,10 @@ static inline void inet_csk_inc_pingpong_cnt(struct sock *sk)
|
|||
if (icsk->icsk_ack.pingpong < U8_MAX)
|
||||
icsk->icsk_ack.pingpong++;
|
||||
}
|
||||
|
||||
static inline bool inet_csk_has_ulp(struct sock *sk)
|
||||
{
|
||||
return inet_sk(sk)->is_icsk && !!inet_csk(sk)->icsk_ulp_ops;
|
||||
}
|
||||
|
||||
#endif /* _INET_CONNECTION_SOCK_H */
|
||||
|
|
|
|||
|
|
@ -428,7 +428,6 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
|
|||
struct sock *sk, u64 flags)
|
||||
{
|
||||
struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct sk_psock_link *link;
|
||||
struct sk_psock *psock;
|
||||
struct sock *osk;
|
||||
|
|
@ -439,7 +438,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx,
|
|||
return -EINVAL;
|
||||
if (unlikely(idx >= map->max_entries))
|
||||
return -E2BIG;
|
||||
if (unlikely(rcu_access_pointer(icsk->icsk_ulp_data)))
|
||||
if (inet_csk_has_ulp(sk))
|
||||
return -EINVAL;
|
||||
|
||||
link = sk_psock_init_link();
|
||||
|
|
@ -782,7 +781,6 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
|
|||
struct sock *sk, u64 flags)
|
||||
{
|
||||
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
u32 key_size = map->key_size, hash;
|
||||
struct bpf_htab_elem *elem, *elem_new;
|
||||
struct bpf_htab_bucket *bucket;
|
||||
|
|
@ -793,7 +791,7 @@ static int sock_hash_update_common(struct bpf_map *map, void *key,
|
|||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
if (unlikely(flags > BPF_EXIST))
|
||||
return -EINVAL;
|
||||
if (unlikely(icsk->icsk_ulp_data))
|
||||
if (inet_csk_has_ulp(sk))
|
||||
return -EINVAL;
|
||||
|
||||
link = sk_psock_init_link();
|
||||
|
|
|
|||
|
|
@ -101,13 +101,6 @@ void tcp_update_ulp(struct sock *sk, struct proto *proto,
|
|||
{
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
|
||||
if (!icsk->icsk_ulp_ops) {
|
||||
sk->sk_write_space = write_space;
|
||||
/* Pairs with lockless read in sk_clone_lock() */
|
||||
WRITE_ONCE(sk->sk_prot, proto);
|
||||
return;
|
||||
}
|
||||
|
||||
if (icsk->icsk_ulp_ops->update)
|
||||
icsk->icsk_ulp_ops->update(sk, proto, write_space);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue