Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1314,6 +1314,9 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)

			hlist_del_init(&session->hlist);

			if (test_and_set_bit(0, &session->dead))
				goto again;

			if (session->ref != NULL)
				(*session->ref)(session);

@@ -1750,6 +1753,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);
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,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 */
+4 −4
Original line number Diff line number Diff line
@@ -437,12 +437,12 @@ static void pppol2tp_session_close(struct l2tp_session *session)

	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);
}
}

/* Really kill the session socket. (Called from sock_put() if
 * refcnt == 0.)