<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/net/ipv6/ip6mr.c, branch master</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master</id>
<link rel='self' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2026-09-10T15:48:44+00:00</updated>
<entry>
<title>ipmr: account multicast table and route memory</title>
<updated>2026-09-10T15:48:44+00:00</updated>
<author>
<name>Zihan Xi</name>
<email>zihanx@nebusec.ai</email>
</author>
<published>2026-09-08T11:58:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b7ee18725f2292ab554aa96a101ae42d45f008bd'/>
<id>urn:sha1:b7ee18725f2292ab554aa96a101ae42d45f008bd</id>
<content type='text'>
A netadmin in a user+net namespace can create many IPv4 and IPv6
multicast routing tables with MRT_TABLE and MRT6_TABLE. Each unseen
id allocates an mr_table via the shared mr_table_alloc(), links it
into the per-net list, and leaves it until netns teardown. Those
objects were not charged to memcg, so the host unreclaimable slab
grows with the table count.

Account mr_table allocations with GFP_KERNEL_ACCOUNT and mark the
IPv4/IPv6 MFC caches SLAB_ACCOUNT. This matches the established
handling of IP addresses, routes and alternate interface names.

Unresolved MFC entries are still allocated from softIRQ with
GFP_ATOMIC and are not charged. They expire after 10 seconds and are
bounded by the socket receive queue; see commit 0079ad8e8dc3
("ipmr: remove hard code cache_resolve_queue_len limit").

Fixes: f0ad0860d01e ("ipv4: ipmr: support multiple tables")
Fixes: d1db275dd3f6 ("ipv6: ip6mr: support multiple tables")
Cc: stable@vger.kernel.org
Reported-by: Vega &lt;vega@nebusec.ai&gt;
Signed-off-by: Zihan Xi &lt;zihanx@nebusec.ai&gt;
Reviewed-by: Ido Schimmel &lt;idosch@nvidia.com&gt;
Link: https://patch.msgid.link/050b58f7fc6b45da0fb12768ebb62d18fa46133d.1788784801.git.zihanx@nebusec.ai
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: do not clone dst in ip6mr_cache_report()</title>
<updated>2026-08-20T19:54:29+00:00</updated>
<author>
<name>Eric Dumazet</name>
<email>edumazet@google.com</email>
</author>
<published>2026-08-18T17:27:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=235b42b5860189eb8c27c36435ad932cae65a734'/>
<id>urn:sha1:235b42b5860189eb8c27c36435ad932cae65a734</id>
<content type='text'>
IPv6 input attaches a non-refcounted (NOREF) dst to skbs under RCU.
When an ingress multicast packet misses MFC lookup,
ip6mr_cache_unresolved() places the skb onto the unresolved queue,
escaping the receive-side RCU grace period.

If the underlying route is deleted and freed, and the MFC queue is later
resolved with a wrong parent interface, ip6_mr_forward() invokes
ip6mr_cache_report(..., MRT6MSG_WRONGMIF), which executes
dst_clone(skb_dst(pkt)) on the freed dst entry, triggering a slab
use-after-free.

Report packets queued to mroute6_sk (a raw socket) and netlink
notifications do not require an attached dst entry.

Fix this by:
1. Removing dst_clone() in ip6mr_cache_report() and ensuring report skbs
   do not hold a dst.
2. Dropping skb_dst before queuing unresolved skbs in
   ip6mr_cache_unresolved(), matching the fact that multicast
   forwarding resolves outgoing routes anew via ip6_route_output().

Fixes: 67f415dd2906 ("ipv6: convert rx data path to not take refcnt on dst")
Reported-by: Zero Day Initiative &lt;zdi-disclosures@trendmicro.com&gt;
Signed-off-by: Eric Dumazet &lt;edumazet@google.com&gt;
Reviewed-by: Hangbin Liu &lt;liuhangbin@kylinos.cn&gt;
Link: https://patch.msgid.link/20260818172755.4083692-1-edumazet@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ipmr: Convert mr_table.cache_resolve_queue_len to u32.</title>
<updated>2026-06-11T22:17:30+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-09T22:20:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=65440a8ce42d89caaee26f70bd0ee09b92ec2c03'/>
<id>urn:sha1:65440a8ce42d89caaee26f70bd0ee09b92ec2c03</id>
<content type='text'>
mr_table.cache_resolve_queue_len is always updated under
spin_lock_bh(&amp;mfc_unres_lock).

Let's convert it to u32.

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Reviewed-by: Ido Schimmel &lt;idosch@nvidia.com&gt;
Link: https://patch.msgid.link/20260609222013.1550355-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Replace RTNL with a dedicated mutex for MFC.</title>
<updated>2026-06-09T00:06:24+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a4c98421720a79587ad6c528f81fe7976a45976b'/>
<id>urn:sha1:a4c98421720a79587ad6c528f81fe7976a45976b</id>
<content type='text'>
ip6mr does not have rtnetlink interface for MFC unlike ipmr,
which uses dev_get_by_index_rcu() to set struct mfcctl.mfcc_parent.

ip6mr_mfc_add() and ip6mr_mfc_delete() are called under RTNL
from ip6_mroute_setsockopt() only.

There are no RTNL dependant, but ip6_mroute_setsockopt() reuses
RTNL just for mrt-&gt;mfc_hash and mrt-&gt;mfc_cache_list.

Let's replace RTNL with a new per-netns mutex.

Later, ip6mr_notifier_ops and ipmr_seq will be moved under
CONFIG_IPV6_MROUTE.

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-15-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Remove RTNL in ip6mr_rules_init() and ip6mr_net_init().</title>
<updated>2026-06-09T00:06:24+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2290727b2fdb9f56f6fa2e06b4c5061c4f28e2df'/>
<id>urn:sha1:2290727b2fdb9f56f6fa2e06b4c5061c4f28e2df</id>
<content type='text'>
When ip6mr_free_table() is called from ip6mr_rules_init() or
ip6mr_net_init(), the netns is not yet published.

Thus, no device should have been registered, and
mroute_clean_tables() will not call mif6_delete(), so
unregister_netdevice_many() is unnecessary.

unregister_netdevice_many() does nothing if the list is empty,
but it requires RTNL due to the unconditional ASSERT_RTNL()
at the entry of unregister_netdevice_many_notify().

Let's remove unnecessary RTNL and ASSERT_RTNL() and instead
add WARN_ON_ONCE() in ip6mr_free_table().

Note that we use a local list for the new WARN_ON_ONCE() because
dev_kill_list passed from ip6mr_rules_exit_rtnl() may have some
devices when other ops-&gt;init() fails after ipmr durnig setup_net().

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-14-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Convert ip6mr_net_exit_batch() to -&gt;exit_rtnl().</title>
<updated>2026-06-09T00:06:24+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2a798e8c71b569b3adca009ceb558ff2a936c4d9'/>
<id>urn:sha1:2a798e8c71b569b3adca009ceb558ff2a936c4d9</id>
<content type='text'>
ip6mr_net_ops uses -&gt;exit_batch() to acquire RTNL only once
for dying network namespaces.

ip6mr does not depend on the ordering of -&gt;exit_rtnl() and
-&gt;exit_batch() of other pernet_operations (unlike fib_net_ops).

Once ip6mr_free_table() is called and all devices are
queued for destruction in -&gt;exit_rtnl(), later during
NETDEV_UNREGISTER, ip6mr_device_event() will not see anything
in vif table and just do nothing.

Let's convert ip6mr_net_exit_batch() to -&gt;exit_rtnl().

We will remove RTNL and unregister_netdevice_many() in
ip6mr_rules_init().

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-13-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Move unregister_netdevice_many() out of ip6mr_free_table().</title>
<updated>2026-06-09T00:06:24+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=33e6984fe5d49eecba404141b0ef0f305ad0a3b3'/>
<id>urn:sha1:33e6984fe5d49eecba404141b0ef0f305ad0a3b3</id>
<content type='text'>
This is a prep commit to convert ip6mr_net_exit_batch() to
-&gt;exit_rtnl().

Let's move unregister_netdevice_many() in ip6mr_free_table()
to its callers.

Now ip6mr_rules_exit() can do batching all tables per netns.

Note that later we will remove RTNL and unregister_netdevice_many()
in ip6mr_rules_init().

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-12-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Move unregister_netdevice_many() out of mroute_clean_tables().</title>
<updated>2026-06-09T00:06:24+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7395fccf6b4c2a351f2d29ff905ae71bf644cc60'/>
<id>urn:sha1:7395fccf6b4c2a351f2d29ff905ae71bf644cc60</id>
<content type='text'>
This is a prep commit to convert ip6mr_net_exit_batch() to
-&gt;exit_rtnl().

Let's move unregister_netdevice_many() in mroute_clean_tables()
to its callers.

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-11-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Call fib_rules_unregister() without RTNL.</title>
<updated>2026-06-09T00:06:23+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=4becf012467511e9f3e21b641054f85711f4e187'/>
<id>urn:sha1:4becf012467511e9f3e21b641054f85711f4e187</id>
<content type='text'>
fib_rules_unregister() removes ops from net-&gt;rules_ops under
spinlock, calls ops-&gt;delete() for each rule, and frees the ops.

ip6mr_rules_ops_template does not have -&gt;delete(), and any
operation does not require RTNL there.

Let's move fib_rules_unregister() from ip6mr_rules_exit() to
ip6mr_net_exit().

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-10-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>ip6mr: Free mr_table after RCU grace period.</title>
<updated>2026-06-09T00:06:23+00:00</updated>
<author>
<name>Kuniyuki Iwashima</name>
<email>kuniyu@google.com</email>
</author>
<published>2026-06-04T22:46:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.landau.one/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2c309a863dd6e609b10caa55a362dc48d2e04564'/>
<id>urn:sha1:2c309a863dd6e609b10caa55a362dc48d2e04564</id>
<content type='text'>
Since default_device_exit_batch() is called after -&gt;exit_rtnl(),
idev-&gt;mc_ifc_work could finally call mroute6_is_socket() under RCU
while -&gt;exit_rtnl() is running. [0]

With CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=n, ip6mr_fib_lookup() does
not check if net-&gt;ipv6.mrt6 is NULL.  If ip6mr_net_exit_batch()
set net-&gt;ipv6.mrt6 to NULL and freed it, the mrt-&gt;mroute_sk access
could result in null-ptr-deref or use-after-free.

Let's prepare for that situation by applying RCU rule to ip6mr
table similarly.

!check_net(net) is added in ip6mr_cache_unresolved() and
mroute_clean_tables() to synchronise the two by mfc_unres_lock
so that ip6mr_cache_unresolved() will not queue skb after
mroute_clean_tables() purged &amp;mrt-&gt;mfc_unres_queue.

rcu_read_lock() in reg_vif_xmit() is moved up to cover
ip6mr_fib_lookup() as with ipmr.

Link: https://lore.kernel.org/netdev/20260407184202.34cfe2d6@kernel.org/ #[0]
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@google.com&gt;
Link: https://patch.msgid.link/20260604224712.3209821-9-kuniyu@google.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
</feed>
