On Wednesday, 3 June 2026 06:51:17 CEST [email protected] wrote: > [Severity: High] > This isn't a bug introduced by this patch, but while looking at the > rhashtable usage in this file, I noticed that rhashtable_lookup_fast() is > called without rcu_read_lock() in batadv_wifi_net_device_update(): > > net/batman-adv/hard-interface.c:batadv_wifi_net_device_update() { > ... > wifi_flags = batadv_wifi_flags_evaluate(net_dev); > device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices, > &net_dev, > batadv_wifi_net_devices_params); > ... > } > > And similarly in batadv_wifi_net_device_unregister(): > > net/batman-adv/hard-interface.c:batadv_wifi_net_device_unregister() { > ... > device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices, > &net_dev, > batadv_wifi_net_devices_params); > ... > } > > Can this lead to a use-after-free on the bucket array? > > Since batadv_wifi_net_devices is initialized with automatic_shrinking = true, > it can be asynchronously resized by a background worker at any time. This > worker frees the old bucket array via kfree_rcu(). Without an active RCU > read-side critical section, couldn't the RCU grace period end while > rhashtable_lookup_fast() is still iterating?
Would be nice if someone else can double check this. But this doesn't seem to
be valid:
static __always_inline void *rhashtable_lookup_fast(
struct rhashtable *ht, const void *key,
const struct rhashtable_params params)
{
void *obj;
rcu_read_lock();
obj = rhashtable_lookup(ht, key, params);
rcu_read_unlock();
return obj;
}
So, rhashtable_lookup_fast() takes rcu_read_lock() itself. And the returned obj
cannot be freed because all functions mentioned here are protected by the
rtnl_lock().
We are therefore also fulfilling the requirement from the
rhashtable_lookup_fast comment:
* Only use this function when you have other mechanisms guaranteeing
* that the object won't go away after the RCU read lock is released.
Regards,
Sven
signature.asc
Description: This is a digitally signed message part.
