The tunnel's closing flag is set when the tunnel is being
destroyed. Use it to reject new sessions and remove acpt_newsess which
was doing the same thing. Also prevent the tunnel being seen in
l2tp_tunnel_get lookups.
---
 net/l2tp/l2tp_core.c | 27 +++++++++++++++++++++------
 net/l2tp/l2tp_core.h |  4 ----
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 49d6e06099ec..691fe9368d91 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -163,6 +163,13 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, 
u32 tunnel_id)
        rcu_read_lock_bh();
        list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
                if (tunnel->tunnel_id == tunnel_id) {
+                       spin_lock_bh(&tunnel->lock);
+                       if (tunnel->closing) {
+                               spin_unlock_bh(&tunnel->lock);
+                               rcu_read_unlock_bh();
+                               return NULL;
+                       }
+                       spin_unlock_bh(&tunnel->lock);
                        l2tp_tunnel_inc_refcount(tunnel);
                        rcu_read_unlock_bh();
 
@@ -278,13 +285,16 @@ int l2tp_session_register(struct l2tp_session *session,
        struct l2tp_net *pn;
        int err;
 
+       spin_lock_bh(&tunnel->lock);
+       if (tunnel->closing) {
+               spin_unlock_bh(&tunnel->lock);
+               return -ENODEV;
+       }
+       spin_unlock_bh(&tunnel->lock);
+
        head = l2tp_session_id_hash(tunnel, session->session_id);
 
        write_lock_bh(&tunnel->hlist_lock);
-       if (!tunnel->acpt_newsess) {
-               err = -ENODEV;
-               goto err_tlock;
-       }
 
        hlist_for_each_entry(session_walk, head, hlist)
                if (session_walk->session_id == session->session_id) {
@@ -1220,7 +1230,6 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
                  tunnel->name);
 
        write_lock_bh(&tunnel->hlist_lock);
-       tunnel->acpt_newsess = false;
        for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
 again:
                hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) {
@@ -1506,7 +1515,6 @@ int l2tp_tunnel_create(struct net *net, int fd, int 
version, u32 tunnel_id, u32
        sprintf(&tunnel->name[0], "tunl %u", tunnel_id);
        spin_lock_init(&tunnel->lock);
        rwlock_init(&tunnel->hlist_lock);
-       tunnel->acpt_newsess = true;
 
        /* The net we belong to */
        tunnel->l2tp_net = net;
@@ -1710,6 +1718,13 @@ struct l2tp_session *l2tp_session_create(int priv_size, 
struct l2tp_tunnel *tunn
 {
        struct l2tp_session *session;
 
+       spin_lock_bh(&tunnel->lock);
+       if (tunnel->closing) {
+               spin_unlock_bh(&tunnel->lock);
+               return ERR_PTR(-ENODEV);
+       }
+       spin_unlock_bh(&tunnel->lock);
+
        session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
        if (session != NULL) {
                session->magic = L2TP_SESSION_MAGIC;
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index e88ff7895ccb..4e098c822cd1 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -160,10 +160,6 @@ struct l2tp_tunnel {
 
        struct rcu_head rcu;
        rwlock_t                hlist_lock;     /* protect session_hlist */
-       bool                    acpt_newsess;   /* Indicates whether this
-                                                * tunnel accepts new sessions.
-                                                * Protected by hlist_lock.
-                                                */
        struct hlist_head       session_hlist[L2TP_HASH_SIZE];
                                                /* hashed list of sessions,
                                                 * hashed by id */
-- 
1.9.1

Reply via email to