aboutsummaryrefslogtreecommitdiffstats
path: root/net/l2tp/l2tp_ppp.c
diff options
context:
space:
mode:
authorTom Parkin <tparkin@katalix.com>2013-03-19 02:11:23 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-20 12:10:39 -0400
commitf6e16b299bacaa71c6604a784f2d088a966f8c23 (patch)
tree115d199ee9cd9fb9dbc296d3daad259cd9e0d682 /net/l2tp/l2tp_ppp.c
parent7b7c0719cd7afee725b920d75ec6a500b76107e6 (diff)
l2tp: unhash l2tp sessions on delete, not on free
If we postpone unhashing of l2tp sessions until the structure is freed, we risk: 1. further packets arriving and getting queued while the pseudowire is being closed down 2. the recv path hitting "scheduling while atomic" errors in the case that recv drops the last reference to a session and calls l2tp_session_free while in atomic context As such, l2tp sessions should be unhashed from l2tp_core data structures early in the teardown process prior to calling pseudowire close. For pseudowires like l2tp_ppp which have multiple shutdown codepaths, provide an unhash hook. Signed-off-by: Tom Parkin <tparkin@katalix.com> Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp/l2tp_ppp.c')
-rw-r--r--net/l2tp/l2tp_ppp.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 9d0eb8c13530..637a341c1e2d 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -466,19 +466,12 @@ static void pppol2tp_session_close(struct l2tp_session *session)
466 */ 466 */
467static void pppol2tp_session_destruct(struct sock *sk) 467static void pppol2tp_session_destruct(struct sock *sk)
468{ 468{
469 struct l2tp_session *session; 469 struct l2tp_session *session = sk->sk_user_data;
470 470 if (session) {
471 if (sk->sk_user_data != NULL) {
472 session = sk->sk_user_data;
473 if (session == NULL)
474 goto out;
475
476 sk->sk_user_data = NULL; 471 sk->sk_user_data = NULL;
477 BUG_ON(session->magic != L2TP_SESSION_MAGIC); 472 BUG_ON(session->magic != L2TP_SESSION_MAGIC);
478 l2tp_session_dec_refcount(session); 473 l2tp_session_dec_refcount(session);
479 } 474 }
480
481out:
482 return; 475 return;
483} 476}
484 477
@@ -509,6 +502,7 @@ static int pppol2tp_release(struct socket *sock)
509 502
510 /* Purge any queued data */ 503 /* Purge any queued data */
511 if (session != NULL) { 504 if (session != NULL) {
505 __l2tp_session_unhash(session);
512 l2tp_session_queue_purge(session); 506 l2tp_session_queue_purge(session);
513 sock_put(sk); 507 sock_put(sk);
514 } 508 }