ovpn_peer_release can run from ovpn module execution context. For
example, ovpn_peer_keepalive_send passes its peer reference to
ovpn_xmit_special, which may drop the final peer reference before the
worker returns.
The peer reference owns a netdev reference. Releasing that netdev
reference synchronously in ovpn_peer_release can unblock netdev
unregistration and module removal while the caller is still executing
ovpn text.
Keep the netdev reference until the peer RCU release callback. That
callback already performs the final peer cleanup after active users have
left their RCU read-side sections, and dropping the netdev reference
there prevents module teardown from passing the netdev-ref boundary
while the final peer-put caller is still running.
Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object")
Signed-off-by: Ralf Lici <[email protected]>
---
New patch added in v3.
drivers/net/ovpn/peer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
index a09d61296425..d274e901cba1 100644
--- a/drivers/net/ovpn/peer.c
+++ b/drivers/net/ovpn/peer.c
@@ -347,6 +347,7 @@ static void ovpn_peer_release_rcu(struct rcu_head *head)
* perform it in the RCU callback, when all contexts are done
*/
dst_cache_destroy(&peer->dst_cache);
+ netdev_put(peer->ovpn->dev, &peer->dev_tracker);
kfree(peer);
}
@@ -361,7 +362,6 @@ static void ovpn_peer_release(struct ovpn_peer *peer)
ovpn_bind_reset(peer, NULL);
spin_unlock_bh(&peer->lock);
call_rcu(&peer->rcu, ovpn_peer_release_rcu);
- netdev_put(peer->ovpn->dev, &peer->dev_tracker);
}
/**
--
2.54.0
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel