mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
xfrm: Check netif_is_alive() in xfrm_bundle_create() and xfrm_create_dummy_bundle().
struct dst_entry passed to xfrm_bundle_create() and xfrm_create_dummy_bundle() could outlive synchronize_net() in unregister_netdevice_many_notify(). For example, ip_route_output_flow() calls __ip_route_output_key() to fetch a dst under RCU, but calls xfrm_lookup_route() outside of that RCU critical section. Thus, xfrm_fill_dst() could add a new uncached route after the first NETDEV_UNREGISTER notification and rely on the rebroadcast in netdev_wait_allrefs_any(). The following patches will move the uncached route flush for dying netdev from the NETDEV_UNREGISTER handler to netdev_run_todo(), where the rebroadcast is also skipped due to dev->dismantle, making such late additions problematic. Let's check netif_is_alive() after fetching dst_dev_rcu(dst) under RCU. This ensures that xfrm either finishes adding the uncached route before synchronize_net() or fails with -ENODEV. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Tested-by: Chris J Arges <carges@cloudflare.com> Link: https://patch.msgid.link/20261001204752.2572265-5-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
2e65372a2b
commit
4eb2e2f358
|
|
@ -2772,7 +2772,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
|
|||
err = -ENODEV;
|
||||
rcu_read_lock();
|
||||
dev = dst_dev_rcu(dst);
|
||||
if (!dev) {
|
||||
if (!dev || !netif_is_alive(dev)) {
|
||||
rcu_read_unlock();
|
||||
goto free_dst;
|
||||
}
|
||||
|
|
@ -3066,7 +3066,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
|
|||
err = -ENODEV;
|
||||
rcu_read_lock();
|
||||
dev = dst_dev_rcu(dst);
|
||||
if (!dev) {
|
||||
if (!dev || !netif_is_alive(dev)) {
|
||||
rcu_read_unlock();
|
||||
goto free_dst;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user