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>
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 */
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)