]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ovpn: finish crypto callback cleanup before peer release
authorRalf Lici <ralf@mandelbit.com>
Wed, 29 Jul 2026 10:21:44 +0000 (12:21 +0200)
committerAntonio Quartulli <antonio@openvpn.net>
Fri, 7 Aug 2026 00:12:13 +0000 (02:12 +0200)
Crypto completion callbacks hold both key-slot and peer references. The
peer reference pins the netdev, and dropping the last peer reference can
let netdev unregistration and module removal make progress.

Do not release that peer reference before the callback has finished its
own cleanup. If ovpn_crypto_key_slot_put runs after ovpn_peer_put, it can
schedule an RCU callback backed by module text after ovpn_cleanup
rcu_barrier has already run. The TX error path also freed the remaining
skb after ovpn_peer_put, leaving callback cleanup outside the peer/netdev
lifetime window.

Release the key slot and free any remaining skb first, then drop the peer
reference as the last callback action.

Fixes: 8534731dbf2d ("ovpn: implement packet processing")
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
drivers/net/ovpn/io.c

index 9a66d693039a3cf07a82037f98bd4beb0b9fe9dc..9526f8096da604ec06164e6aa04472f93dfbafcd 100644 (file)
@@ -204,10 +204,10 @@ drop:
                ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
        kfree_skb(skb);
 drop_nocount:
-       if (likely(peer))
-               ovpn_peer_put(peer);
        if (likely(ks))
                ovpn_crypto_key_slot_put(ks);
+       if (likely(peer))
+               ovpn_peer_put(peer);
 }
 
 /* RX path entry point: decrypt packet and forward it to the device */
@@ -302,11 +302,11 @@ err_unlock:
 err:
        if (unlikely(skb))
                ovpn_dev_dstats_tx_dropped(peer->ovpn->dev);
-       if (likely(peer))
-               ovpn_peer_put(peer);
+       kfree_skb(skb);
        if (likely(ks))
                ovpn_crypto_key_slot_put(ks);
-       kfree_skb(skb);
+       if (likely(peer))
+               ovpn_peer_put(peer);
 }
 
 static bool ovpn_encrypt_one(struct ovpn_peer *peer, struct sk_buff *skb)