From 9ef9a1009660609be05e3a72dc7f665f17d7a10a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 2 Apr 2020 20:45:24 +0200 Subject: [PATCH] 4.9-stable patches added patches: l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch --- ...re-freed-after-their-pppol2tp-socket.patch | 51 ++++++++++++ ...sion_delete-and-l2tp_tunnel_closeall.patch | 79 +++++++++++++++++++ queue-4.9/series | 2 + 3 files changed, 132 insertions(+) create mode 100644 queue-4.9/l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch create mode 100644 queue-4.9/l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch create mode 100644 queue-4.9/series diff --git a/queue-4.9/l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch b/queue-4.9/l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch new file mode 100644 index 00000000000..d20ea39dc56 --- /dev/null +++ b/queue-4.9/l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch @@ -0,0 +1,51 @@ +From cdd10c9627496ad25c87ce6394e29752253c69d3 Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Fri, 22 Sep 2017 15:39:23 +0200 +Subject: l2tp: ensure sessions are freed after their PPPOL2TP socket + +From: Guillaume Nault + +commit cdd10c9627496ad25c87ce6394e29752253c69d3 upstream. + +If l2tp_tunnel_delete() or l2tp_tunnel_closeall() deletes a session +right after pppol2tp_release() orphaned its socket, then the 'sock' +variable of the pppol2tp_session_close() callback is NULL. Yet the +session is still used by pppol2tp_release(). + +Therefore we need to take an extra reference in any case, to prevent +l2tp_tunnel_delete() or l2tp_tunnel_closeall() from freeing the session. + +Since the pppol2tp_session_close() callback is only set if the session +is associated to a PPPOL2TP socket and that both l2tp_tunnel_delete() +and l2tp_tunnel_closeall() hold the PPPOL2TP socket before calling +pppol2tp_session_close(), we're sure that pppol2tp_session_close() and +pppol2tp_session_destruct() are paired and called in the right order. +So the reference taken by the former will be released by the later. + +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + +--- + net/l2tp/l2tp_ppp.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -437,11 +437,11 @@ static void pppol2tp_session_close(struc + + BUG_ON(session->magic != L2TP_SESSION_MAGIC); + +- if (sock) { ++ if (sock) + inet_shutdown(sock, SEND_SHUTDOWN); +- /* Don't let the session go away before our socket does */ +- l2tp_session_inc_refcount(session); +- } ++ ++ /* Don't let the session go away before our socket does */ ++ l2tp_session_inc_refcount(session); + } + + /* Really kill the session socket. (Called from sock_put() if diff --git a/queue-4.9/l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch b/queue-4.9/l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch new file mode 100644 index 00000000000..d44c19028df --- /dev/null +++ b/queue-4.9/l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch @@ -0,0 +1,79 @@ +From b228a94066406b6c456321d69643b0d7ce11cfa6 Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Fri, 22 Sep 2017 15:39:24 +0200 +Subject: l2tp: fix race between l2tp_session_delete() and l2tp_tunnel_closeall() + +From: Guillaume Nault + +commit b228a94066406b6c456321d69643b0d7ce11cfa6 upstream. + +There are several ways to remove L2TP sessions: + + * deleting a session explicitly using the netlink interface (with + L2TP_CMD_SESSION_DELETE), + * deleting the session's parent tunnel (either by closing the + tunnel's file descriptor or using the netlink interface), + * closing the PPPOL2TP file descriptor of a PPP pseudo-wire. + +In some cases, when these methods are used concurrently on the same +session, the session can be removed twice, leading to use-after-free +bugs. + +This patch adds a 'dead' flag, used by l2tp_session_delete() and +l2tp_tunnel_closeall() to prevent them from stepping on each other's +toes. + +The session deletion path used when closing a PPPOL2TP file descriptor +doesn't need to be adapted. It already has to ensure that a session +remains valid for the lifetime of its PPPOL2TP file descriptor. +So it takes an extra reference on the session in the ->session_close() +callback (pppol2tp_session_close()), which is eventually dropped +in the ->sk_destruct() callback of the PPPOL2TP socket +(pppol2tp_session_destruct()). +Still, __l2tp_session_unhash() and l2tp_session_queue_purge() can be +called twice and even concurrently for a given session, but thanks to +proper locking and re-initialisation of list fields, this is not an +issue. + +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + +--- + net/l2tp/l2tp_core.c | 6 ++++++ + net/l2tp/l2tp_core.h | 1 + + 2 files changed, 7 insertions(+) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1351,6 +1351,9 @@ again: + + hlist_del_init(&session->hlist); + ++ if (test_and_set_bit(0, &session->dead)) ++ goto again; ++ + if (session->ref != NULL) + (*session->ref)(session); + +@@ -1799,6 +1802,9 @@ EXPORT_SYMBOL_GPL(__l2tp_session_unhash) + */ + int l2tp_session_delete(struct l2tp_session *session) + { ++ if (test_and_set_bit(0, &session->dead)) ++ return 0; ++ + if (session->ref) + (*session->ref)(session); + __l2tp_session_unhash(session); +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -84,6 +84,7 @@ struct l2tp_session_cfg { + struct l2tp_session { + int magic; /* should be + * L2TP_SESSION_MAGIC */ ++ long dead; + + struct l2tp_tunnel *tunnel; /* back pointer to tunnel + * context */ diff --git a/queue-4.9/series b/queue-4.9/series new file mode 100644 index 00000000000..bf515784c41 --- /dev/null +++ b/queue-4.9/series @@ -0,0 +1,2 @@ +l2tp-ensure-sessions-are-freed-after-their-pppol2tp-socket.patch +l2tp-fix-race-between-l2tp_session_delete-and-l2tp_tunnel_closeall.patch -- 2.47.3