CVE-2025-21823
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
27/02/2025
Last modified:
13/03/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
batman-adv: Drop unmanaged ELP metric worker<br />
<br />
The ELP worker needs to calculate new metric values for all neighbors<br />
"reachable" over an interface. Some of the used metric sources require<br />
locks which might need to sleep. This sleep is incompatible with the RCU<br />
list iterator used for the recorded neighbors. The initial approach to work<br />
around of this problem was to queue another work item per neighbor and then<br />
run this in a new context.<br />
<br />
Even when this solved the RCU vs might_sleep() conflict, it has a major<br />
problems: Nothing was stopping the work item in case it is not needed<br />
anymore - for example because one of the related interfaces was removed or<br />
the batman-adv module was unloaded - resulting in potential invalid memory<br />
accesses.<br />
<br />
Directly canceling the metric worker also has various problems:<br />
<br />
* cancel_work_sync for a to-be-deactivated interface is called with<br />
rtnl_lock held. But the code in the ELP metric worker also tries to use<br />
rtnl_lock() - which will never return in this case. This also means that<br />
cancel_work_sync would never return because it is waiting for the worker<br />
to finish.<br />
* iterating over the neighbor list for the to-be-deactivated interface is<br />
currently done using the RCU specific methods. Which means that it is<br />
possible to miss items when iterating over it without the associated<br />
spinlock - a behaviour which is acceptable for a periodic metric check<br />
but not for a cleanup routine (which must "stop" all still running<br />
workers)<br />
<br />
The better approch is to get rid of the per interface neighbor metric<br />
worker and handle everything in the interface worker. The original problems<br />
are solved by:<br />
<br />
* creating a list of neighbors which require new metric information inside<br />
the RCU protected context, gathering the metric according to the new list<br />
outside the RCU protected context<br />
* only use rcu_trylock inside metric gathering code to avoid a deadlock<br />
when the cancel_delayed_work_sync is called in the interface removal code<br />
(which is called with the rtnl_lock held)
Impact
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/0fdc3c166ac17b26014313fa2b93696354511b24
- https://git.kernel.org/stable/c/1c334629176c2d644befc31a20d4bf75542f7631
- https://git.kernel.org/stable/c/3c0e0aecb78cb2a2ca1dc701982d08fedb088dc6
- https://git.kernel.org/stable/c/781a06fd265a8151f7601122d9c2e985663828ff
- https://git.kernel.org/stable/c/8c8ecc98f5c65947b0070a24bac11e12e47cc65d
- https://git.kernel.org/stable/c/a0019971f340ae02ba54cf1861f72da7e03e6b66
- https://git.kernel.org/stable/c/a7aa2317285806640c844acd4cd2cd768e395264
- https://git.kernel.org/stable/c/af264c2a9adc37f4bdf88ca7f3affa15d8c7de9e