From: Kyle Zeng <kylebot@openai.com>
To: netdev@vger.kernel.org
Cc: David Ahern <dsahern@kernel.org>,
Ido Schimmel <idosch@nvidia.com>,
linux-kernel@vger.kernel.org, outbounddisclosures@openai.com
Subject: [PATCH] ip6mr: Serialize multicast router socket ownership
Date: Thu, 29 Oct 2026 21:22:21 -0700 [thread overview]
Message-ID: <20261030042221.73996-1-kylebot@openai.com> (raw)
MRT6_TABLE checks whether the socket owns its current table before
acquiring RTNL. MRT6_INIT also looks up its table before taking RTNL.
Consequently, concurrent TABLE and INIT calls can initialize the old
table and then change the socket's selected table. Another INIT can
register the same socket in the new table.
rawv6_close() calls ip6mr_sk_done(), which clears only the first table
owned by the socket. After the socket's RCU-delayed free, the other
table retains a dangling mroute_sk pointer. A subsequent multicast cache
report passes that pointer to sock_queue_rcv_skb_reason(). This produces
a KASAN slab-use-after-free in sk_filter_trim_cap().
Look up the selected table in ip6mr_sk_init() after acquiring RTNL.
Likewise, re-read the current table and check its owner under RTNL in
MRT6_TABLE before updating the selection. This preserves the single-table
ownership invariant shared with ip6mr_sk_done(), without changing the
locking of the other multicast socket options.
Fixes: d1db275dd3f6 ("ipv6: ip6mr: support multiple tables")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
---
I have a reproducer for this issue and can share via DM
net/ipv6/ip6mr.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index af968a2c2a78..01a1087bc7c8 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1623,12 +1623,20 @@ static void mroute_clean_tables(struct mr_table *mrt, int flags,
}
}
-static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
+static int ip6mr_sk_init(struct sock *sk)
{
- int err = 0;
struct net *net = sock_net(sk);
+ struct mr_table *mrt;
+ int err = 0;
rtnl_lock();
+ mrt = __ip6mr_get_table(net,
+ raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
+ if (!mrt) {
+ err = -ENOENT;
+ goto out_unlock;
+ }
+
spin_lock(&mrt_lock);
if (rtnl_dereference(mrt->mroute_sk)) {
err = -EADDRINUSE;
@@ -1644,6 +1652,7 @@ static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
NETCONFA_MC_FORWARDING,
NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all);
+out_unlock:
rtnl_unlock();
return err;
@@ -1745,7 +1754,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
if (optlen < sizeof(int))
return -EINVAL;
- return ip6mr_sk_init(mrt, sk);
+ return ip6mr_sk_init(sk);
case MRT6_DONE:
return ip6mr_sk_done(sk);
@@ -1872,16 +1881,21 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
/* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
if (v != RT_TABLE_DEFAULT && v >= 100000000)
return -EINVAL;
- if (sk == rcu_access_pointer(mrt->mroute_sk))
- return -EBUSY;
-
rtnl_lock();
ret = 0;
- mrt = ip6mr_new_table(net, v);
- if (IS_ERR(mrt))
- ret = PTR_ERR(mrt);
- else
- raw6_sk(sk)->ip6mr_table = v;
+ mrt = __ip6mr_get_table(net,
+ raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
+ if (!mrt) {
+ ret = -ENOENT;
+ } else if (sk == rtnl_dereference(mrt->mroute_sk)) {
+ ret = -EBUSY;
+ } else {
+ mrt = ip6mr_new_table(net, v);
+ if (IS_ERR(mrt))
+ ret = PTR_ERR(mrt);
+ else
+ raw6_sk(sk)->ip6mr_table = v;
+ }
rtnl_unlock();
return ret;
}
base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3
--
2.56.0
next reply other threads:[~2026-10-30 4:22 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 4:22 Kyle Zeng [this message]
2026-10-30 4:24 ` [PATCH] ip6mr: Serialize multicast router socket ownership netdev-bot+sinfo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261030042221.73996-1-kylebot@openai.com \
--to=kylebot@openai.com \
--cc=dsahern@kernel.org \
--cc=idosch@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=outbounddisclosures@openai.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox