aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2017-09-01 11:58:51 -0400
committerDavid S. Miller <davem@davemloft.net>2017-09-03 14:04:21 -0400
commitf026bc29a8e093edfbb2a77700454b285c97e8ad (patch)
tree7dfc0aa94822a5d36f1f63f2e07fa7dae339a6c2
parentf3c66d4e144a0904ea9b95d23ed9f8eb38c11bfb (diff)
l2tp: pass tunnel pointer to ->session_create()
Using l2tp_tunnel_find() in pppol2tp_session_create() and l2tp_eth_create() is racy, because no reference is held on the returned session. These functions are only used to implement the ->session_create callback which is run by l2tp_nl_cmd_session_create(). Therefore searching for the parent tunnel isn't necessary because l2tp_nl_cmd_session_create() already has a pointer to it and holds a reference. This patch modifies ->session_create()'s prototype to directly pass the the parent tunnel as parameter, thus avoiding searching for it in pppol2tp_session_create() and l2tp_eth_create(). Since we have to touch the ->session_create() call in l2tp_nl_cmd_session_create(), let's also remove the useless conditional: we know that ->session_create isn't NULL at this point because it's already been checked earlier in this same function. Finally, one might be tempted to think that the removed l2tp_tunnel_find() calls were harmless because they would return the same tunnel as the one held by l2tp_nl_cmd_session_create() anyway. But that tunnel might be removed and a new one created with same tunnel Id before the l2tp_tunnel_find() call. In this case l2tp_tunnel_find() would return the new tunnel which wouldn't be protected by the reference held by l2tp_nl_cmd_session_create(). Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") Fixes: d9e31d17ceba ("l2tp: Add L2TP ethernet pseudowire support") Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/l2tp/l2tp_core.h4
-rw-r--r--net/l2tp/l2tp_eth.c11
-rw-r--r--net/l2tp/l2tp_netlink.c8
-rw-r--r--net/l2tp/l2tp_ppp.c19
4 files changed, 17 insertions, 25 deletions
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 4593d48df953..a305e0c5925a 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -201,7 +201,9 @@ struct l2tp_tunnel {
201}; 201};
202 202
203struct l2tp_nl_cmd_ops { 203struct l2tp_nl_cmd_ops {
204 int (*session_create)(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); 204 int (*session_create)(struct net *net, struct l2tp_tunnel *tunnel,
205 u32 session_id, u32 peer_session_id,
206 struct l2tp_session_cfg *cfg);
205 int (*session_delete)(struct l2tp_session *session); 207 int (*session_delete)(struct l2tp_session *session);
206}; 208};
207 209
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 4de2ec94b08c..87da9ef61860 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -262,24 +262,19 @@ static void l2tp_eth_adjust_mtu(struct l2tp_tunnel *tunnel,
262 dev->needed_headroom += session->hdr_len; 262 dev->needed_headroom += session->hdr_len;
263} 263}
264 264
265static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) 265static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
266 u32 session_id, u32 peer_session_id,
267 struct l2tp_session_cfg *cfg)
266{ 268{
267 unsigned char name_assign_type; 269 unsigned char name_assign_type;
268 struct net_device *dev; 270 struct net_device *dev;
269 char name[IFNAMSIZ]; 271 char name[IFNAMSIZ];
270 struct l2tp_tunnel *tunnel;
271 struct l2tp_session *session; 272 struct l2tp_session *session;
272 struct l2tp_eth *priv; 273 struct l2tp_eth *priv;
273 struct l2tp_eth_sess *spriv; 274 struct l2tp_eth_sess *spriv;
274 int rc; 275 int rc;
275 struct l2tp_eth_net *pn; 276 struct l2tp_eth_net *pn;
276 277
277 tunnel = l2tp_tunnel_find(net, tunnel_id);
278 if (!tunnel) {
279 rc = -ENODEV;
280 goto out;
281 }
282
283 if (cfg->ifname) { 278 if (cfg->ifname) {
284 strlcpy(name, cfg->ifname, IFNAMSIZ); 279 strlcpy(name, cfg->ifname, IFNAMSIZ);
285 name_assign_type = NET_NAME_USER; 280 name_assign_type = NET_NAME_USER;
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 57427d430f10..7135f4645d3a 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -643,10 +643,10 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
643 break; 643 break;
644 } 644 }
645 645
646 ret = -EPROTONOSUPPORT; 646 ret = l2tp_nl_cmd_ops[cfg.pw_type]->session_create(net, tunnel,
647 if (l2tp_nl_cmd_ops[cfg.pw_type]->session_create) 647 session_id,
648 ret = (*l2tp_nl_cmd_ops[cfg.pw_type]->session_create)(net, tunnel_id, 648 peer_session_id,
649 session_id, peer_session_id, &cfg); 649 &cfg);
650 650
651 if (ret >= 0) { 651 if (ret >= 0) {
652 session = l2tp_session_get(net, tunnel, session_id, false); 652 session = l2tp_session_get(net, tunnel, session_id, false);
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index f0edb7209079..50e3ee9a9d61 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -788,25 +788,20 @@ end:
788 788
789#ifdef CONFIG_L2TP_V3 789#ifdef CONFIG_L2TP_V3
790 790
791/* Called when creating sessions via the netlink interface. 791/* Called when creating sessions via the netlink interface. */
792 */ 792static int pppol2tp_session_create(struct net *net, struct l2tp_tunnel *tunnel,
793static int pppol2tp_session_create(struct net *net, u32 tunnel_id, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg) 793 u32 session_id, u32 peer_session_id,
794 struct l2tp_session_cfg *cfg)
794{ 795{
795 int error; 796 int error;
796 struct l2tp_tunnel *tunnel;
797 struct l2tp_session *session; 797 struct l2tp_session *session;
798 struct pppol2tp_session *ps; 798 struct pppol2tp_session *ps;
799 799
800 tunnel = l2tp_tunnel_find(net, tunnel_id);
801
802 /* Error if we can't find the tunnel */
803 error = -ENOENT;
804 if (tunnel == NULL)
805 goto out;
806
807 /* Error if tunnel socket is not prepped */ 800 /* Error if tunnel socket is not prepped */
808 if (tunnel->sock == NULL) 801 if (!tunnel->sock) {
802 error = -ENOENT;
809 goto out; 803 goto out;
804 }
810 805
811 /* Default MTU values. */ 806 /* Default MTU values. */
812 if (cfg->mtu == 0) 807 if (cfg->mtu == 0)