[PATCH OLK-5.10 0/4] Fix CVE-2026-52917
Fix CVE-2026-52917. Stefan Wiehler (1): sctp: Hold sock lock while iterating over address list Xin Long (1): sctp: hold endpoint before calling cb in sctp_transport_lookup_process Yajun Deng (1): net: Use nlmsg_unicast() instead of netlink_unicast() Zhao Zhang (1): sctp: diag: reject stale associations in dump_one path include/net/sctp/sctp.h | 3 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/inet_diag.c | 5 +--- net/ipv4/raw_diag.c | 7 ++--- net/ipv4/udp_diag.c | 6 ++-- net/mptcp/mptcp_diag.c | 6 ++-- net/netlink/af_netlink.c | 2 +- net/sctp/diag.c | 65 ++++++++++++++++++++-------------------- net/sctp/socket.c | 22 +++++++++----- net/unix/diag.c | 6 ++-- 10 files changed, 59 insertions(+), 65 deletions(-) -- 2.25.1
From: Yajun Deng <yajun.deng@linux.dev> stable inclusion from stable-v5.10.247 commit b0dd049bd67acefecf2bad7bd70c2609d1687ecd category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15622 CVE: CVE-2026-52917 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 01757f536ac825e3614d583fee9acb48c64ed084 ] It has 'if (err >0 )' statement in nlmsg_unicast(), so use nlmsg_unicast() instead of netlink_unicast(), this looks more concise. v2: remove the change in netfilter. Signed-off-by: Yajun Deng <yajun.deng@linux.dev> Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> Stable-dep-of: f1fc201148c7 ("sctp: Hold sock lock while iterating over address list") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Ze Zuo <zuoze1@huawei.com> --- net/ipv4/fib_frontend.c | 2 +- net/ipv4/inet_diag.c | 5 +---- net/ipv4/raw_diag.c | 7 ++----- net/ipv4/udp_diag.c | 6 ++---- net/mptcp/mptcp_diag.c | 6 ++---- net/netlink/af_netlink.c | 2 +- net/sctp/diag.c | 6 ++---- net/unix/diag.c | 6 ++---- 8 files changed, 13 insertions(+), 27 deletions(-) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index efe143885995..0576fe47f623 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1385,7 +1385,7 @@ static void nl_fib_input(struct sk_buff *skb) portid = NETLINK_CB(skb).portid; /* netlink portid */ NETLINK_CB(skb).portid = 0; /* from kernel */ NETLINK_CB(skb).dst_group = 0; /* unicast */ - netlink_unicast(net->ipv4.fibnl, skb, portid, MSG_DONTWAIT); + nlmsg_unicast(net->ipv4.fibnl, skb, portid); } static int __net_init nl_fib_lookup_init(struct net *net) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 87209a7fb28c..334529e106b3 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -572,10 +572,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, nlmsg_free(rep); goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); out: if (sk) diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c index 70981c6d67ef..e525b8e869f3 100644 --- a/net/ipv4/raw_diag.c +++ b/net/ipv4/raw_diag.c @@ -119,11 +119,8 @@ static int raw_diag_dump_one(struct netlink_callback *cb, return err; } - err = netlink_unicast(net->diag_nlsk, rep, - NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + return err; } diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 1dbece34496e..ed69d1edfd09 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -77,10 +77,8 @@ static int udp_dump_one(struct udp_table *tbl, kfree_skb(rep); goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + out: if (sk) sock_put(sk); diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c index f1af3f44875e..7f900b58c71d 100644 --- a/net/mptcp/mptcp_diag.c +++ b/net/mptcp/mptcp_diag.c @@ -57,10 +57,8 @@ static int mptcp_diag_dump_one(struct netlink_callback *cb, kfree_skb(rep); goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + out: sock_put(sk); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1d76e96f57cf..9c4e2ecd60b2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2486,7 +2486,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, nlmsg_end(skb, rep); - netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT); + nlmsg_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid); } EXPORT_SYMBOL(netlink_ack); diff --git a/net/sctp/diag.c b/net/sctp/diag.c index 07d0ada23bfd..c2d13a6c3012 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -281,10 +281,8 @@ static int sctp_tsp_dump_one(struct sctp_transport *tsp, void *p) goto out; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + out: return err; } diff --git a/net/unix/diag.c b/net/unix/diag.c index 594ee27c9655..2a7407daa738 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -305,10 +305,8 @@ static int unix_diag_get_exact(struct sk_buff *in_skb, goto again; } - err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, - MSG_DONTWAIT); - if (err > 0) - err = 0; + err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + out: if (sk) sock_put(sk); -- 2.25.1
From: Xin Long <lucien.xin@gmail.com> stable inclusion from stable-v5.10.247 commit 80af0466a9e6713522e849c007e410e6cf5b2941 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15622 CVE: CVE-2026-52917 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit f9d31c4cf4c11ff10317f038b9c6f7c3bda6cdd4 ] The same fix in commit 5ec7d18d1813 ("sctp: use call_rcu to free endpoint") is also needed for dumping one asoc and sock after the lookup. Fixes: 86fdb3448cc1 ("sctp: ensure ep is not destroyed before doing the dump") Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Stable-dep-of: f1fc201148c7 ("sctp: Hold sock lock while iterating over address list") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Ze Zuo <zuoze1@huawei.com> --- include/net/sctp/sctp.h | 3 +-- net/sctp/diag.c | 46 +++++++++++++++++++---------------------- net/sctp/socket.c | 22 +++++++++++++------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 6d89a7f3f6a4..775fde82c657 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -110,8 +110,7 @@ struct sctp_transport *sctp_transport_get_next(struct net *net, struct rhashtable_iter *iter); struct sctp_transport *sctp_transport_get_idx(struct net *net, struct rhashtable_iter *iter, int pos); -int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), - struct net *net, +int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, const union sctp_addr *laddr, const union sctp_addr *paddr, void *p); int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, diff --git a/net/sctp/diag.c b/net/sctp/diag.c index c2d13a6c3012..b0ce1080842d 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -242,48 +242,44 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc) + 64; } -static int sctp_tsp_dump_one(struct sctp_transport *tsp, void *p) +static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) { struct sctp_association *assoc = tsp->asoc; - struct sock *sk = tsp->asoc->base.sk; struct sctp_comm_param *commp = p; - struct sk_buff *in_skb = commp->skb; + struct sock *sk = ep->base.sk; const struct inet_diag_req_v2 *req = commp->r; - const struct nlmsghdr *nlh = commp->nlh; - struct net *net = sock_net(in_skb->sk); + struct sk_buff *skb = commp->skb; struct sk_buff *rep; int err; err = sock_diag_check_cookie(sk, req->id.idiag_cookie); if (err) - goto out; + return err; - err = -ENOMEM; rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL); if (!rep) - goto out; + return -ENOMEM; lock_sock(sk); - if (sk != assoc->base.sk) { - release_sock(sk); - sk = assoc->base.sk; - lock_sock(sk); + if (ep != assoc->ep) { + err = -EAGAIN; + goto out; } - err = inet_sctp_diag_fill(sk, assoc, rep, req, - sk_user_ns(NETLINK_CB(in_skb).sk), - NETLINK_CB(in_skb).portid, - nlh->nlmsg_seq, 0, nlh, - commp->net_admin); - release_sock(sk); + + err = inet_sctp_diag_fill(sk, assoc, rep, req, sk_user_ns(NETLINK_CB(skb).sk), + NETLINK_CB(skb).portid, commp->nlh->nlmsg_seq, 0, + commp->nlh, commp->net_admin); if (err < 0) { WARN_ON(err == -EMSGSIZE); - kfree_skb(rep); goto out; } + release_sock(sk); - err = nlmsg_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid); + return nlmsg_unicast(sock_net(skb->sk)->diag_nlsk, rep, NETLINK_CB(skb).portid); out: + release_sock(sk); + kfree_skb(rep); return err; } @@ -424,15 +420,15 @@ static void sctp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, static int sctp_diag_dump_one(struct netlink_callback *cb, const struct inet_diag_req_v2 *req) { - struct sk_buff *in_skb = cb->skb; - struct net *net = sock_net(in_skb->sk); + struct sk_buff *skb = cb->skb; + struct net *net = sock_net(skb->sk); const struct nlmsghdr *nlh = cb->nlh; union sctp_addr laddr, paddr; struct sctp_comm_param commp = { - .skb = in_skb, + .skb = skb, .r = req, .nlh = nlh, - .net_admin = netlink_net_capable(in_skb, CAP_NET_ADMIN), + .net_admin = netlink_net_capable(skb, CAP_NET_ADMIN), }; if (req->sdiag_family == AF_INET) { @@ -455,7 +451,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb, paddr.v6.sin6_family = AF_INET6; } - return sctp_transport_lookup_process(sctp_tsp_dump_one, + return sctp_transport_lookup_process(sctp_sock_dump_one, net, &laddr, &paddr, &commp); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 8a18aa451e47..64f9c859420e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5221,23 +5221,31 @@ int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), } EXPORT_SYMBOL_GPL(sctp_for_each_endpoint); -int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), - struct net *net, +int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, const union sctp_addr *laddr, const union sctp_addr *paddr, void *p) { struct sctp_transport *transport; - int err; + struct sctp_endpoint *ep; + int err = -ENOENT; rcu_read_lock(); transport = sctp_addrs_lookup_transport(net, laddr, paddr); + if (!transport) { + rcu_read_unlock(); + return err; + } + ep = transport->asoc->ep; + if (!sctp_endpoint_hold(ep)) { /* asoc can be peeled off */ + sctp_transport_put(transport); + rcu_read_unlock(); + return err; + } rcu_read_unlock(); - if (!transport) - return -ENOENT; - err = cb(transport, p); + err = cb(ep, transport, p); + sctp_endpoint_put(ep); sctp_transport_put(transport); - return err; } EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); -- 2.25.1
From: Stefan Wiehler <stefan.wiehler@nokia.com> stable inclusion from stable-v5.10.247 commit 9d585109d153a8a624f9504436a3c73494fe97c0 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15622 CVE: CVE-2026-52917 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit f1fc201148c7e684c10a72b6a3375597f28d1ef6 ] Move address list traversal in inet_assoc_attr_size() under the sock lock to avoid holding the RCU read lock. Suggested-by: Xin Long <lucien.xin@gmail.com> Fixes: 8f840e47f190 ("sctp: add the sctp_diag.c file") Signed-off-by: Stefan Wiehler <stefan.wiehler@nokia.com> Acked-by: Xin Long <lucien.xin@gmail.com> Link: https://patch.msgid.link/20251028161506.3294376-4-stefan.wiehler@nokia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Ze Zuo <zuoze1@huawei.com> --- net/sctp/diag.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/sctp/diag.c b/net/sctp/diag.c index b0ce1080842d..6ae474c9466b 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -223,14 +223,15 @@ struct sctp_comm_param { bool net_admin; }; -static size_t inet_assoc_attr_size(struct sctp_association *asoc) +static size_t inet_assoc_attr_size(struct sock *sk, + struct sctp_association *asoc) { int addrlen = sizeof(struct sockaddr_storage); int addrcnt = 0; struct sctp_sockaddr_entry *laddr; list_for_each_entry_rcu(laddr, &asoc->base.bind_addr.address_list, - list) + list, lockdep_sock_is_held(sk)) addrcnt++; return nla_total_size(sizeof(struct sctp_info)) @@ -256,11 +257,14 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t if (err) return err; - rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL); - if (!rep) + lock_sock(sk); + + rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL); + if (!rep) { + release_sock(sk); return -ENOMEM; + } - lock_sock(sk); if (ep != assoc->ep) { err = -EAGAIN; goto out; -- 2.25.1
From: Zhao Zhang <zzhan461@ucr.edu> stable inclusion from stable-v5.10.259 commit 6657af827e21883ae90693e42e7f59a6aab690b5 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15622 CVE: CVE-2026-52917 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit 5eba3e48d78edd7551b992cb7ba687019b3a78da upstream. The SCTP exact sock_diag lookup can hold a transport reference, block on lock_sock(sk), and then resume after sctp_association_free() has marked the association dead and freed its bind address list. When that happens, inet_assoc_attr_size() and inet_diag_msg_sctpasoc_fill() can still dereference association state that is no longer valid for reporting. In particular, inet_diag_msg_sctpasoc_fill() may read an empty bind-address list as a real sctp_sockaddr_entry and trigger an out-of-bounds read from unrelated association memory. Reject the association after taking the socket lock if it has been reaped or detached from the endpoint, and report the lookup as stale. This keeps the exact dump-one path from formatting torn association state. Fixes: 8f840e47f190 ("sctp: add the sctp_diag.c file") Cc: stable@kernel.org Reported-by: Yuan Tan <yuantan098@gmail.com> Reported-by: Yifan Wu <yifanwucs@gmail.com> Reported-by: Juefei Pu <tomapufckgml@gmail.com> Reported-by: Zhengchuan Liang <zcliangcn@gmail.com> Reported-by: Xin Liu <bird@lzu.edu.cn> Signed-off-by: Zhao Zhang <zzhan461@ucr.edu> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn> Acked-by: Xin Long <lucien.xin@gmail.com> Link: https://patch.msgid.link/fac6043fa20a2ff68e12958c431836f692c51268.1780113823... Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Ze Zuo <zuoze1@huawei.com> --- net/sctp/diag.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/net/sctp/diag.c b/net/sctp/diag.c index 6ae474c9466b..c427e5e9e8f3 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -259,15 +259,15 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t lock_sock(sk); - rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL); - if (!rep) { - release_sock(sk); - return -ENOMEM; + if (ep != assoc->ep || assoc->base.dead) { + err = -ESTALE; + goto out_unlock; } - if (ep != assoc->ep) { - err = -EAGAIN; - goto out; + rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto out_unlock; } err = inet_sctp_diag_fill(sk, assoc, rep, req, sk_user_ns(NETLINK_CB(skb).sk), @@ -282,8 +282,9 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t return nlmsg_unicast(sock_net(skb->sk)->diag_nlsk, rep, NETLINK_CB(skb).portid); out: - release_sock(sk); kfree_skb(rep); +out_unlock: + release_sock(sk); return err; } -- 2.25.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25748 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/MVM... 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://atomgit.com/openeuler/kernel/merge_requests/25748 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/MVM...
participants (2)
-
patchwork bot -
Ze Zuo