Received: by 10.223.185.116 with SMTP id b49csp824109wrg; Sat, 10 Feb 2018 21:15:16 -0800 (PST) X-Google-Smtp-Source: AH8x2254wimj121d48+wY7J6eX93guUf9MNRQ48gn1XFOJN8+L+hzIXnOEHXjobfbNkBZa0apv+J X-Received: by 10.99.63.11 with SMTP id m11mr6590650pga.422.1518326116386; Sat, 10 Feb 2018 21:15:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518326116; cv=none; d=google.com; s=arc-20160816; b=pE5g3XrnKNOdIWv/yxV4h/PYwMp6K88d4EJM1tGiBY5LVwGgDSeya5kndTRwBglPfq nNyp5+E7gtEe2yKxTK+wnKgOvK9eP4Sn+oh2APmwNDehRW/Ztt1FBXI7p0qxUxpk7+Ma ns5olpiHS9CjrIUNhibcrJyhRUQzO2MrGR0I1lTw5/kTYMTKbEMezvHsTjqtgFgZUSRF GZ/8MqX1kv4gKk/CABGDSlHrApgkQPUKrQkW/vuhC+BVKdlZA8ji6Sptqu544kE+pJfT dbNb/GVT/zc2BxZ8rW4Wk0eaBJZq7ccKJV3sn43wH/25rmdln9RAvWdHuC3xhrDNKOqR +ZbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=NVXhryb3ilm0Av8hUvV/cUuG8WA8zafD6ixgVmrF22A=; b=UauIm5P6jO50lADP22V87lZMn+vGCe6pmyK32Gb1BkDl6l2p4p1k1uOBJzCzxupBGj 0MfQgjqGdyIExUbL4RUqUsIH864px69DM5TcWuFW6OqMu3z7HE80OpfCPUqSTncR6M9+ occLFEJGn3w1Xx2zhMw0AhIFi5z+yTr79EaRjKQI+EFD+fXM5BdRhfHnTe/zGDmNtBRb p1gzZlnv5FO2Ne0qfzpuaPHvwGU2Rv/Rr+GrwDp6NklTpuJ+b1uLR0jbfhcc++ku1ezq swAvVqU3pLPTT8xedhABGmO+yPOHkTaAbDlIeiqq0SuEAL2Y53i27TXlBLEsSI4rzE1N pZYQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y12si2774339pgv.267.2018.02.10.21.15.02; Sat, 10 Feb 2018 21:15:16 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754090AbeBKFOc (ORCPT + 99 others); Sun, 11 Feb 2018 00:14:32 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:41358 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752566AbeBKEdl (ORCPT ); Sat, 10 Feb 2018 23:33:41 -0500 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1ekjKc-0002hS-Qy; Sun, 11 Feb 2018 04:33:38 +0000 Received: from ben by deadeye with local (Exim 4.90) (envelope-from ) id 1ekjKX-0004Ss-FM; Sun, 11 Feb 2018 04:33:33 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "David S. Miller" , "Guillaume Nault" Date: Sun, 11 Feb 2018 04:20:06 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.2 18/79] l2tp: don't register sessions in l2tp_session_create() In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.2.99-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Guillaume Nault commit 3953ae7b218df4d1e544b98a393666f9ae58a78c upstream. Sessions created by l2tp_session_create() aren't fully initialised: some pseudo-wire specific operations need to be done before making the session usable. Therefore the PPP and Ethernet pseudo-wires continue working on the returned l2tp session while it's already been exposed to the rest of the system. This can lead to various issues. In particular, the session may enter the deletion process before having been fully initialised, which will confuse the session removal code. This patch moves session registration out of l2tp_session_create(), so that callers can control when the session is exposed to the rest of the system. This is done by the new l2tp_session_register() function. Only pppol2tp_session_create() can be easily converted to avoid modifying its session after registration (the debug message is dropped in order to avoid the need for holding a reference on the session). For pppol2tp_connect() and l2tp_eth_create()), more work is needed. That'll be done in followup patches. For now, let's just register the session right after its creation, like it was done before. The only difference is that we can easily take a reference on the session before registering it, so, at least, we're sure it's not going to be freed while we're working on it. Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller [bwh: Backported to 3.2: adjust context] Signed-off-by: Ben Hutchings --- net/l2tp/l2tp_core.c | 21 +++++++-------------- net/l2tp/l2tp_core.h | 3 +++ net/l2tp/l2tp_eth.c | 9 +++++++++ net/l2tp/l2tp_ppp.c | 23 +++++++++++++++++------ 4 files changed, 36 insertions(+), 20 deletions(-) --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -327,8 +327,8 @@ struct l2tp_session *l2tp_session_get_by } EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname); -static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel, - struct l2tp_session *session) +int l2tp_session_register(struct l2tp_session *session, + struct l2tp_tunnel *tunnel) { struct l2tp_session *session_walk; struct hlist_head *g_head; @@ -377,6 +377,10 @@ static int l2tp_session_add_to_tunnel(st hlist_add_head(&session->hlist, head); write_unlock_bh(&tunnel->hlist_lock); + /* Ignore management session in session count value */ + if (session->session_id != 0) + atomic_inc(&l2tp_session_count); + return 0; err_tlock_pnlock: @@ -386,6 +390,7 @@ err_tlock: return err; } +EXPORT_SYMBOL_GPL(l2tp_session_register); /* Lookup a tunnel by id */ @@ -1703,7 +1708,6 @@ static void l2tp_session_set_header_len( struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) { struct l2tp_session *session; - int err; session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL); if (session != NULL) { @@ -1752,17 +1756,6 @@ struct l2tp_session *l2tp_session_create l2tp_session_inc_refcount(session); - err = l2tp_session_add_to_tunnel(tunnel, session); - if (err) { - kfree(session); - - return ERR_PTR(err); - } - - /* Ignore management session in session count value */ - if (session->session_id != 0) - atomic_inc(&l2tp_session_count); - return session; } --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -246,6 +246,8 @@ extern struct l2tp_tunnel *l2tp_tunnel_f extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp); extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); +int l2tp_session_register(struct l2tp_session *session, + struct l2tp_tunnel *tunnel); extern int l2tp_session_delete(struct l2tp_session *session); extern void l2tp_session_free(struct l2tp_session *session); extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -194,6 +194,13 @@ static int l2tp_eth_create(struct net *n goto out; } + l2tp_session_inc_refcount(session); + rc = l2tp_session_register(session, tunnel); + if (rc < 0) { + kfree(session); + goto out; + } + dev = alloc_netdev(sizeof(*priv), name, l2tp_eth_dev_setup); if (!dev) { rc = -ENOMEM; @@ -227,6 +234,7 @@ static int l2tp_eth_create(struct net *n __module_get(THIS_MODULE); /* Must be done after register_netdev() */ strlcpy(session->ifname, dev->name, IFNAMSIZ); + l2tp_session_dec_refcount(session); dev_hold(dev); @@ -237,6 +245,7 @@ out_del_dev: spriv->dev = NULL; out_del_session: l2tp_session_delete(session); + l2tp_session_dec_refcount(session); out: return rc; } --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -734,6 +734,14 @@ static int pppol2tp_connect(struct socke error = PTR_ERR(session); goto end; } + + l2tp_session_inc_refcount(session); + error = l2tp_session_register(session, tunnel); + if (error < 0) { + kfree(session); + goto end; + } + drop_refcnt = true; } /* Associate session with its PPPoL2TP socket */ @@ -821,7 +829,7 @@ static int pppol2tp_session_create(struc /* Error if tunnel socket is not prepped */ if (!tunnel->sock) { error = -ENOENT; - goto out; + goto err; } /* Default MTU values. */ @@ -836,18 +844,21 @@ static int pppol2tp_session_create(struc peer_session_id, cfg); if (IS_ERR(session)) { error = PTR_ERR(session); - goto out; + goto err; } ps = l2tp_session_priv(session); ps->tunnel_sock = tunnel->sock; - PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO, - "%s: created\n", session->name); - - error = 0; - -out: + error = l2tp_session_register(session, tunnel); + if (error < 0) + goto err_sess; + + return 0; + +err_sess: + kfree(session); +err: return error; }