Commit 016576d5 authored by David S. Miller's avatar David S. Miller

Merge branch 'l2tp-fix-some-races-in-session-deletion'

Guillaume Nault says:

====================
l2tp: fix some races in session deletion

L2TP provides several interfaces for deleting sessions. Using two of
them concurrently can lead to use-after-free bugs.

Patch #2 uses a flag to prevent double removal of L2TP sessions.
Patch #1 fixes a bug found in the way. Fixing this bug is also
necessary for patch #2 to handle all cases.

This issue is similar to the tunnel deletion bug being worked on by
Sabrina: https://patchwork.ozlabs.org/patch/814173/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5c346525 b228a940
...@@ -1314,6 +1314,9 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) ...@@ -1314,6 +1314,9 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
hlist_del_init(&session->hlist); hlist_del_init(&session->hlist);
if (test_and_set_bit(0, &session->dead))
goto again;
if (session->ref != NULL) if (session->ref != NULL)
(*session->ref)(session); (*session->ref)(session);
...@@ -1750,6 +1753,9 @@ EXPORT_SYMBOL_GPL(__l2tp_session_unhash); ...@@ -1750,6 +1753,9 @@ EXPORT_SYMBOL_GPL(__l2tp_session_unhash);
*/ */
int l2tp_session_delete(struct l2tp_session *session) int l2tp_session_delete(struct l2tp_session *session)
{ {
if (test_and_set_bit(0, &session->dead))
return 0;
if (session->ref) if (session->ref)
(*session->ref)(session); (*session->ref)(session);
__l2tp_session_unhash(session); __l2tp_session_unhash(session);
......
...@@ -76,6 +76,7 @@ struct l2tp_session_cfg { ...@@ -76,6 +76,7 @@ struct l2tp_session_cfg {
struct l2tp_session { struct l2tp_session {
int magic; /* should be int magic; /* should be
* L2TP_SESSION_MAGIC */ * L2TP_SESSION_MAGIC */
long dead;
struct l2tp_tunnel *tunnel; /* back pointer to tunnel struct l2tp_tunnel *tunnel; /* back pointer to tunnel
* context */ * context */
......
...@@ -437,11 +437,11 @@ static void pppol2tp_session_close(struct l2tp_session *session) ...@@ -437,11 +437,11 @@ static void pppol2tp_session_close(struct l2tp_session *session)
BUG_ON(session->magic != L2TP_SESSION_MAGIC); BUG_ON(session->magic != L2TP_SESSION_MAGIC);
if (sock) { if (sock)
inet_shutdown(sock, SEND_SHUTDOWN); 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 /* Really kill the session socket. (Called from sock_put() if
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment