forked from Minki/linux
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
016576d531
@ -1314,6 +1314,9 @@ again:
|
|||||||
|
|
||||||
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);
|
|||||||
*/
|
*/
|
||||||
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 {
|
|||||||
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)
|
|||||||
|
|
||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user