[PATCH OLK-5.10 v2 0/4] fix CVE-2025-40080
Changes in v2: Add pre patch ("bpf, sockmap: Use stricter sk state checks in sk_lookup_assign"). Eric Dumazet (2): net: use sk_is_tcp() in more places nbd: restrict sockets to TCP and UDP John Fastabend (2): bpf, sockmap: Use stricter sk state checks in sk_lookup_assign bpf: syzkaller found null ptr deref in unix_bpf proto add drivers/block/nbd.c | 8 ++++++++ include/linux/skmsg.h | 6 ++++++ include/net/sock.h | 10 ++++++++++ net/core/filter.c | 6 ++++-- net/core/skbuff.c | 6 ++---- net/core/sock.c | 6 ++---- net/core/sock_map.c | 12 ------------ 7 files changed, 32 insertions(+), 22 deletions(-) -- 2.39.2
From: John Fastabend <john.fastabend@gmail.com> mainline inclusion from mainline-v5.16-rc1 commit 40a34121ac1dc52ed9cd34a8f4e48e32517a52fd category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID3WIC CVE: CVE-2025-40080 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ 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@cloudflare.com> Signed-off-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com> Link: https://lore.kernel.org/bpf/20211103204736.248403-2-john.fastabend@gmail.com Conflicts: include/linux/skmsg.h net/core/sock_map.c [Due to not merging commit 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets").] Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- include/linux/skmsg.h | 12 ++++++++++++ net/core/filter.c | 6 ++++-- net/core/sock_map.c | 12 ------------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index f9d8e8b1a4e8..91ba0da57d0c 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -521,4 +521,16 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) return false; return psock->parser.enabled; } + +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; +} #endif /* _LINUX_SKMSG_H */ diff --git a/net/core/filter.c b/net/core/filter.c index d3e64273b3c4..8a2406ab4821 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -10556,8 +10556,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 beb8768a9285..7b0c3d4d45a5 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -550,18 +550,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 sk_is_udp(const struct sock *sk) -{ - return sk->sk_type == SOCK_DGRAM && - sk->sk_protocol == IPPROTO_UDP; -} - static bool sock_map_redirect_allowed(const struct sock *sk) { return sk_is_tcp(sk) && sk->sk_state != TCP_LISTEN; -- 2.39.2
From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v5.17-rc1 commit 42f67eea3ba36cef2dce2e853de6ddcb2e89eb39 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID3WIC CVE: CVE-2025-40080 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ Move sk_is_tcp() to include/net/sock.h and use it where we can. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Conflicts: include/linux/skmsg.h include/net/sock.h net/core/skbuff.c net/core/sock_map.c [Context conflicts.] Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- include/linux/skmsg.h | 6 ------ include/net/sock.h | 5 +++++ net/core/skbuff.c | 6 ++---- net/core/sock.c | 6 ++---- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 91ba0da57d0c..86672847aa0a 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -522,12 +522,6 @@ static inline bool sk_psock_strp_enabled(struct sk_psock *psock) return psock->parser.enabled; } -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 && diff --git a/include/net/sock.h b/include/net/sock.h index b81e870a9fcc..7861559f3ce7 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2678,6 +2678,11 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags) &skb_shinfo(skb)->tskey); } +static inline bool sk_is_tcp(const struct sock *sk) +{ + return sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP; +} + DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key); /** * sk_eat_skb - Release a skb if it is no longer needed diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c5d13c3fd0d2..47ed4de1edf4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4930,8 +4930,7 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb, serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0; if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { serr->ee.ee_data = skb_shinfo(skb)->tskey; - if (sk->sk_protocol == IPPROTO_TCP && - sk->sk_type == SOCK_STREAM) + if (sk_is_tcp(sk)) serr->ee.ee_data -= sk->sk_tskey; } @@ -4999,8 +4998,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, if (tsonly) { #ifdef CONFIG_INET if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && - sk->sk_protocol == IPPROTO_TCP && - sk->sk_type == SOCK_STREAM) { + sk_is_tcp(sk)) { skb = tcp_get_timestamping_opt_stats(sk, orig_skb); opt_stats = true; } else diff --git a/net/core/sock.c b/net/core/sock.c index 0e4ba9d63542..88bb667aebdc 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1012,8 +1012,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, if (val & SOF_TIMESTAMPING_OPT_ID && !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { - if (sk->sk_protocol == IPPROTO_TCP && - sk->sk_type == SOCK_STREAM) { + if (sk_is_tcp(sk)) { if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) { ret = -EINVAL; @@ -1202,8 +1201,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_ZEROCOPY: if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6) { - if (!((sk->sk_type == SOCK_STREAM && - sk->sk_protocol == IPPROTO_TCP) || + if (!(sk_is_tcp(sk) || (sk->sk_type == SOCK_DGRAM && sk->sk_protocol == IPPROTO_UDP))) ret = -ENOTSUPP; -- 2.39.2
From: John Fastabend <john.fastabend@gmail.com> mainline inclusion from mainline-v6.7-rc7 commit 8d6650646ce49e9a5b8c5c23eb94f74b1749f70f category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID3WIC CVE: CVE-2025-40080 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ I added logic to track the sock pair for stream_unix sockets so that we ensure lifetime of the sock matches the time a sockmap could reference the sock (see fixes tag). I forgot though that we allow af_unix unconnected sockets into a sock{map|hash} map. This is problematic because previous fixed expected sk_pair() to exist and did not NULL check it. Because unconnected sockets have a NULL sk_pair this resulted in the NULL ptr dereference found by syzkaller. BUG: KASAN: null-ptr-deref in unix_stream_bpf_update_proto+0x72/0x430 net/unix/unix_bpf.c:171 Write of size 4 at addr 0000000000000080 by task syz-executor360/5073 Call Trace: <TASK> ... sock_hold include/net/sock.h:777 [inline] unix_stream_bpf_update_proto+0x72/0x430 net/unix/unix_bpf.c:171 sock_map_init_proto net/core/sock_map.c:190 [inline] sock_map_link+0xb87/0x1100 net/core/sock_map.c:294 sock_map_update_common+0xf6/0x870 net/core/sock_map.c:483 sock_map_update_elem_sys+0x5b6/0x640 net/core/sock_map.c:577 bpf_map_update_value+0x3af/0x820 kernel/bpf/syscall.c:167 We considered just checking for the null ptr and skipping taking a ref on the NULL peer sock. But, if the socket is then connected() after being added to the sockmap we can cause the original issue again. So instead this patch blocks adding af_unix sockets that are not in the ESTABLISHED state. Reported-by: Eric Dumazet <edumazet@google.com> Reported-by: syzbot+e8030702aefd3444fb9e@syzkaller.appspotmail.com Fixes: 8866730aed51 ("bpf, sockmap: af_unix stream sockets need to hold ref for pair sock") Acked-by: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/r/20231201180139.328529-2-john.fastabend@gmail.com Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Conflicts: include/net/sock.h [Context conflicts.] net/core/sock_map.c [Due to the fix tag is not merged.] Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- include/net/sock.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index 7861559f3ce7..095b429231a2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2683,6 +2683,11 @@ 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_stream_unix(const struct sock *sk) +{ + return sk->sk_family == AF_UNIX && sk->sk_type == SOCK_STREAM; +} + DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key); /** * sk_eat_skb - Release a skb if it is no longer needed -- 2.39.2
From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v6.18-rc1 commit 9f7c02e031570e8291a63162c6c046dc15ff85b0 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID3WIC CVE: CVE-2025-40080 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ------------------ Recently, syzbot started to abuse NBD with all kinds of sockets. Commit cf1b2326b734 ("nbd: verify socket is supported during setup") made sure the socket supported a shutdown() method. Explicitely accept TCP and UNIX stream sockets. Fixes: cf1b2326b734 ("nbd: verify socket is supported during setup") Reported-by: syzbot+e1cd6bd8493060bd701d@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/CANn89iJ+76eE3A_8S_zTpSyW5hvPRn6V57458hCZGY5h... Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Mike Christie <mchristi@redhat.com> Cc: Richard W.M. Jones <rjones@redhat.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Yu Kuai <yukuai1@huaweicloud.com> Cc: linux-block@vger.kernel.org Cc: nbd@other.debian.org Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Zheng Qixing <zhengqixing@huawei.com> --- drivers/block/nbd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index fa111ed7cdae..85eba9dcba3e 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1121,6 +1121,14 @@ static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd, if (!sock) return NULL; + if (!sk_is_tcp(sock->sk) && + !sk_is_stream_unix(sock->sk)) { + dev_err(disk_to_dev(nbd->disk), "Unsupported socket: should be TCP or UNIX.\n"); + *err = -EINVAL; + sockfd_put(sock); + return NULL; + } + if (sock->ops->shutdown == sock_no_shutdown) { dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n"); *err = -EINVAL; -- 2.39.2
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/18846 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6BB... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/18846 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6BB...
participants (2)
-
patchwork bot -
Zheng Qixing