This is a note to let you know that I've just added the patch titled bpf, sockmap: Use stricter sk state checks in sk_lookup_assign to the 5.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: bpf-sockmap-use-stricter-sk-state-checks-in-sk_looku.patch and it can be found in the queue-5.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 73f99197b24d6a978a0abe975f0239f3c20c13ca Author: John Fastabend <john.fastabend@xxxxxxxxx> Date: Wed Nov 3 13:47:32 2021 -0700 bpf, sockmap: Use stricter sk state checks in sk_lookup_assign [ Upstream commit 40a34121ac1dc52ed9cd34a8f4e48e32517a52fd ] In order to fix an issue with sockets in TCP sockmap redirect cases we plan to allow CLOSE state sockets to exist in the sockmap. However, the check in bpf_sk_lookup_assign() currently only invalidates sockets in the TCP_ESTABLISHED case relying on the checks on sockmap insert to ensure we never SOCK_CLOSE state sockets in the map. To prepare for this change we flip the logic in bpf_sk_lookup_assign() to explicitly test for the accepted cases. Namely, a tcp socket in TCP_LISTEN or a udp socket in TCP_CLOSE state. This also makes the code more resilent to future changes. Suggested-by: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx> Signed-off-by: John Fastabend <john.fastabend@xxxxxxxxx> Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> Reviewed-by: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx> Link: https://lore.kernel.org/bpf/20211103204736.248403-2-john.fastabend@xxxxxxxxx Stable-dep-of: 448a5ce1120c ("udp6: Fix race condition in udp6_sendmsg & connect") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 6e18ca234f812..fe2fbf1685494 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -505,6 +505,18 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) return !!psock->saved_data_ready; } +static inline bool sk_is_tcp(const struct sock *sk) +{ + return sk->sk_type == SOCK_STREAM && + sk->sk_protocol == IPPROTO_TCP; +} + +static inline bool sk_is_udp(const struct sock *sk) +{ + return sk->sk_type == SOCK_DGRAM && + sk->sk_protocol == IPPROTO_UDP; +} + #if IS_ENABLED(CONFIG_NET_SOCK_MSG) #define BPF_F_STRPARSER (1UL << 1) diff --git a/net/core/filter.c b/net/core/filter.c index 519315a1acf3a..a28c51f4ab232 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -10508,8 +10508,10 @@ BPF_CALL_3(bpf_sk_lookup_assign, struct bpf_sk_lookup_kern *, ctx, return -EINVAL; if (unlikely(sk && sk_is_refcounted(sk))) return -ESOCKTNOSUPPORT; /* reject non-RCU freed sockets */ - if (unlikely(sk && sk->sk_state == TCP_ESTABLISHED)) - return -ESOCKTNOSUPPORT; /* reject connected sockets */ + if (unlikely(sk && sk_is_tcp(sk) && sk->sk_state != TCP_LISTEN)) + return -ESOCKTNOSUPPORT; /* only accept TCP socket in LISTEN */ + if (unlikely(sk && sk_is_udp(sk) && sk->sk_state != TCP_CLOSE)) + return -ESOCKTNOSUPPORT; /* only accept UDP socket in CLOSE */ /* Check if socket is suitable for packet L3/L4 protocol */ if (sk && sk->sk_protocol != ctx->protocol) diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 86b4e8909ad1e..60774b79f2e3a 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -523,12 +523,6 @@ static bool sock_map_op_okay(const struct bpf_sock_ops_kern *ops) ops->op == BPF_SOCK_OPS_TCP_LISTEN_CB; } -static bool sk_is_tcp(const struct sock *sk) -{ - return sk->sk_type == SOCK_STREAM && - sk->sk_protocol == IPPROTO_TCP; -} - static bool sock_map_redirect_allowed(const struct sock *sk) { if (sk_is_tcp(sk))