Re: [PATCH net] ipv4: Fix in_device refcount resurrection in in_dev_get()
Ido Schimmel <[email protected]>
| Newsgroups | org.kernel.vger.netdev,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260817160058.GA484389@shredder> |
On Sun, Aug 16, 2026 at 02:20:32AM +0900, Baul Lee wrote: > in_dev_get() reads dev->ip_ptr under RCU and then unconditionally > increments its refcount. inetdev_destroy() clears the pointer and drops > the last reference under RTNL, with no grace period in between, so a > reader that fetched the pointer before the store can increment a > refcount that has already reached zero. That resurrects an object whose > RCU free is queued: This part is fine. > dropping the resurrected reference re-enters in_dev_finish_destroy() > for a second netdev_put() and a second call_rcu() on the same > rcu_head, and if the grace period elapses first the drop itself is a > use-after-free. Are you sure about this part? The reference count is set to REFCOUNT_SATURATED when you increment from zero, so I don't think you re-enter in_dev_finish_destroy(). > > inet_netconf_get_devconf() is registered RTNL_FLAG_DOIT_UNLOCKED, and > rtnetlink_rcv_msg() exempts RTNL_KIND_GET from the CAP_NET_ADMIN check, > so an unprivileged user can drive the reader side. Reproduced as UID > 65534 on v7.2-rc7: > > refcount_t: addition on 0; use-after-free. > WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x14c/0x180 > CPU: 0 UID: 65534 PID: 655 Comm: j1_poc > refcount_warn_saturate+0x14c/0x180 (P) > inet_netconf_get_devconf+0x4b0/0x4c4 > rtnetlink_rcv_msg+0x434/0x4d0 > > followed by the matching underflow when the reference is dropped. > > Use refcount_inc_not_zero() and return NULL for an in_device that has > already reached zero. All callers already handle a NULL return, which > in_dev_get() gives today whenever dev->ip_ptr is NULL. Callers under > RTNL see no change: ip_ptr is cleared before the last put, so a non-NULL > ip_ptr there implies a non-zero refcount. > > Discovered by XBOW, triaged by Baul Lee <[email protected]> FYI, it was actually mentioned a few times already: https://lore.kernel.org/netdev/20260802115639.GA270646@shredder/ https://sashiko.dev/#/patchset/20260731135202.566337-1-david.lee%40trailofbits.com > > Fixes: bbcf91053bb6 ("inet: do not use RTNL in inet_netconf_get_devconf()") I think you should blame commit 9d40c84cf5bc ("net: devinet: Reduce refcount before grace period") instead: 1. in_dev_get() was called w/o RTNL even before bbcf91053bb6. 2. Calling in_dev_get() w/o RTNL only became unsafe after 9d40c84cf5bc. Before that, inetdev_destroy() dropped the reference after an RCU grace period. The diff itself looks OK.