Skip to content

Commit c539cb3

Browse files
ralfliciordex
authored andcommitted
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: 11851cb ("ovpn: implement TCP transport") Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
1 parent a200cdb commit c539cb3

1 file changed

Lines changed: 6 additions & 0 deletions

File tree

  • drivers/net/ovpn

drivers/net/ovpn/io.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,18 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
9191

9292
/* cause packet to be "received" by the interface */
9393
pkt_len = skb->len;
94+
/* we may get here in process context in case of TCP connections,
95+
* therefore we have to disable BHs to ensure gro_cells_receive()
96+
* and dev_dstats_rx_add() do not get corrupted or enter deadlock
97+
*/
98+
local_bh_disable();
9499
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb);
95100
if (likely(ret == NET_RX_SUCCESS)) {
96101
/* update RX stats with the size of decrypted packet */
97102
ovpn_peer_stats_increment_rx(&peer->vpn_stats, pkt_len);
98103
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
99104
}
105+
local_bh_enable();
100106
}
101107

102108
void ovpn_decrypt_post(void *data, int ret)

0 commit comments

Comments
 (0)