Subject: Re: [PATCH net] rtnetlink: fix leak of SRCU struct in rtnl_link_register

From: Jakub Kicinski <[email-masked]>
Date: Thu, 19 Mar 2026 17:04:09 -0700

On Wed, 18 Mar 2026 17:15:15 +0100 Sabrina Dubroca wrote:
> Commit 6b57ff21a310 ("rtnetlink: Protect link_ops by mutex.") swapped
> the EEXIST check with the init_srcu_struct, but didn't add cleanup of
> the SRCU struct we just allocated in case of error.

FWIW AI has spotted a different bug while reviewing this:

As a related question about the srcu lifecycle for these ops structures,
is there a missing synchronize_rcu() in rtnl_link_unregister() that could
cause a use-after-free?
If rtnl_link_ops_get() traverses the link_ops list under rcu_read_lock(),
and rtnl_link_unregister() removes the ops via list_del_rcu() followed
immediately by synchronize_srcu(&ops->srcu) and cleanup_srcu_struct(),
what happens if an rcu reader finds the ops pointer but is preempted
before calling srcu_read_lock()?
Since no srcu readers are technically active yet, synchronize_srcu()
would return immediately, and cleanup_srcu_struct() would free the
per-CPU data. When the preempted reader resumes, wouldn't it execute
srcu_read_lock() on freed data?
Does rtnl_link_unregister() need a synchronize_rcu() after list_del_rcu()
and before destroying the srcu struct to ensure all rcu-side list
traversals have completed?