mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
ovpn: ensure packet delivery happens with BH disabled
ovpn injects decrypted packets into the netdev RX path through
ovpn_netdev_write() which invokes gro_cells_receive() and
dev_dstats_rx_add().
ovpn_netdev_write() is normally called in softirq context,
however, in case of TCP connections it may also be invoked
process context.
When this happens gro_cells_receive() will throw a warning:
[ 230.183747][ T12] WARNING: net/core/gro_cells.c:30 at gro_cells_receive+0x708/0xaa0, CPU#1: kworker/u16:0/12
and lockdep will also report a potential inconsistent lock state:
WARNING: inconsistent lock state
7.0.0-rc4+ #246 Tainted: G W
--------------------------------
inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
because attempts to acquire gro_cells->bh_lock by both
contexts may lead to a deadlock.
At the same time, dev_dstats_rx_add() does not expect to race
with a softirq (which may happen when invoked in process context),
because the latter may access its per-cpu state and corrupt
it.
Fix all this by invoking local_bh_disable/enable() around
gro_cells_receive() and dev_dstats_rx_add() to ensure that
bottom halves are always disabled before calling both of
them.
Fixes: 11851cbd60 ("ovpn: implement TCP transport")
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
This commit is contained in:
parent
a200cdbf95
commit
c539cb30f9
|
|
@ -91,12 +91,18 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
|
|||
|
||||
/* cause packet to be "received" by the interface */
|
||||
pkt_len = skb->len;
|
||||
/* we may get here in process context in case of TCP connections,
|
||||
* therefore we have to disable BHs to ensure gro_cells_receive()
|
||||
* and dev_dstats_rx_add() do not get corrupted or enter deadlock
|
||||
*/
|
||||
local_bh_disable();
|
||||
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb);
|
||||
if (likely(ret == NET_RX_SUCCESS)) {
|
||||
/* update RX stats with the size of decrypted packet */
|
||||
ovpn_peer_stats_increment_rx(&peer->vpn_stats, pkt_len);
|
||||
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
|
||||
}
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
void ovpn_decrypt_post(void *data, int ret)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user