Patch "l2tp: fix race condition in l2tp_tunnel_delete" has been added to the 4.9-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
l2tp: fix race condition in l2tp_tunnel_delete
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Tue Oct 10 16:09:22 CEST 2017
From: Sabrina Dubroca <[email protected]>
Date: Tue, 26 Sep 2017 16:16:43 +0200
Subject: l2tp: fix race condition in l2tp_tunnel_delete
From: Sabrina Dubroca <[email protected]>
[ Upstream commit 62b982eeb4589b2e6d7c01a90590e3a4c2b2ca19 ]
If we try to delete the same tunnel twice, the first delete operation does a lookup (l2tp_tunnel_get), finds the tunnel, calls l2tp_tunnel_delete, which queues it for deletion by l2tp_tunnel_del_work.
The second delete operation also finds the tunnel and calls l2tp_tunnel_delete. If the workqueue has already fired and started running l2tp_tunnel_del_work, then l2tp_tunnel_delete will queue the same tunnel a second time, and try to free the socket again.
Add a dead flag to prevent firing the workqueue twice. Then we can remove the check of queue_work's result that was meant to prevent that race but doesn't.
Reproducer:
ip l2tp add tunnel tunnel_id 3000 peer_tunnel_id 4000 local 192.168.0.2 remote 192.168.0.1 encap udp udp_sport 5000 udp_dport 6000 ip l2tp add session name l2tp1 tunnel_id 3000 session_id 1000 peer_session_id 2000
ip link set l2tp1 up
ip l2tp del tunnel tunnel_id 3000
ip l2tp del tunnel tunnel_id 3000
--- net/l2tp/l2tp_core.c | 10 ++++------ net/l2tp/l2tp_core.h | 5 ++++- 2 files changed, 8 insertions(+), 7 deletions(-)
net/l2tp/l2tp_core.c +4 -6
@@ -1737,14 +1737,12 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);/* This function is used by the netlink TUNNEL_DELETE command. */ -int l2tp_tunnel_delete (struct l2tp_tunnel *tunnel) +void l2tp_tunnel_delete (struct l2tp_tunnel *tunnel) { -l2tp_tunnel_inc_refcount (tunnel); -if (false ==queue_work (l2tp_wq, &tunnel->del_work)) { -l2tp_tunnel_dec_refcount (tunnel); -return 1 ; +if (!test_and_set_bit (0 , &tunnel->dead)) { +l2tp_tunnel_inc_refcount (tunnel); +queue_work (l2tp_wq, &tunnel->del_work); } -return 0 ; }EXPORT_SYMBOL_GPL (l2tp_tunnel_delete);
net/l2tp/l2tp_core.h +4 -1
@@ -169,6 +169,9 @@ struct l2tp_tunnel_cfg {struct l2tp_tunnel {int magic;/* Should be L2TP_TUNNEL_MAGIC */ + +unsigned long dead; +struct rcu_head rcu;rwlock_t hlist_lock;/* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE ];
@@ -257,7 +260,7 @@ int l2tp_tunnel_create(struct net *net, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp);void l2tp_tunnel_closeall (struct l2tp_tunnel *tunnel); -int l2tp_tunnel_delete (struct l2tp_tunnel *tunnel); +void l2tp_tunnel_delete (struct l2tp_tunnel *tunnel); struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id,
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/l2tp-fix-race-condition-in-l2tp_tunnel_delete.patch