Re: [PATCH] ipv4: Serialize netconf GET requests with RTNL

From: Ido Schimmel

Date: Thu Oct 08 2026 - 03:31:01 EST


On Thu, Oct 08, 2026 at 02:32:18PM +0800, Cen Zhang wrote:
> An in_device returned by in_dev_get() must stay alive until
> inet_netconf_get_devconf() finishes reading its cnf. However, the helper
> samples dev->ip_ptr under RCU and unconditionally increments refcnt,
> then returns the pointer outside RCU without checking whether the count
> was already zero. The net_device reference held by the request does not
> retain the separately allocated in_device.
>
> A down interface without IPv4 addresses or multicast owners can have
> only the ip_ptr publication reference. Lowering its MTU below
> IPV4_MIN_MTU invokes inetdev_destroy() through the RTNL-held
> NETDEV_CHANGEMTU notifier. RTM_GETNETCONF runs without RTNL, allowing
> the final put to follow its pointer sample but precede its increment:
>
> RTM_GETNETCONF MTU change (RTNL held)
> in_dev_get():
> rcu_read_lock()
> sample dev->ip_ptr
> inetdev_destroy():
> clear dev->ip_ptr
> in_dev_put(): refcnt -> 0
> call_rcu(in_dev_free_rcu)
> refcount_inc() from zero
> rcu_read_unlock()
> in_dev_free_rcu(): kfree()
> inet_netconf_fill_devconf():
> read in_dev->cnf
>
> The zero-count increment warns and saturates the refcount, but cannot
> cancel the queued free. Once the request leaves RCU, the callback can
> free the attachment before the configuration read, causing a
> use-after-free. Restoring a valid MTU can publish a new attachment on
> the same device while the request still holds the old pointer.
>
> Drop RTNL_FLAG_DOIT_UNLOCKED so rtnetlink holds RTNL from lookup through
> reply construction and reference release. This serializes the request
> with inetdev_destroy(), preventing the publication reference from being
> dropped during acquisition or use. The dump handler already holds RCU
> through its configuration reads and keeps RTNL_FLAG_DUMP_UNLOCKED.
>
> KASAN report as below:

[...]

>
> Fixes: bbcf91053bb6 ("inet: do not use RTNL in inet_netconf_get_devconf()")
> Assisted-by: LLM
> Signed-off-by: Cen Zhang <zzzccc427@xxxxxxxxx>

The correct fix is to use refcount_inc_not_zero() in in_dev_get(), in a
similar fashion to commit 0e243671bc7b ("ipv6: prevent in6_dev_get()
from resurrecting inet6_dev"). Please base your v2 on the following
submission and the feedback I provided:

https://lore.kernel.org/netdev/20260815172032.79740-1-baul.lee@xxxxxxxx/

And please read:

https://docs.kernel.org/next/process/maintainer-netdev.html

Notably:

1. "designate your patch to a tree - [PATCH net] or [PATCH net-next]"
2. "don’t repost your patches within one 24h period"

Also, trim the traces (preferably decoded) to what is actually useful:

https://docs.kernel.org/next/process/submitting-patches.html#backtraces-in-commit-messages