aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2017-08-25 10:51:46 -0400
committerDavid S. Miller <davem@davemloft.net>2017-08-28 14:34:58 -0400
commite702c1204eb57788ef189c839c8c779368267d70 (patch)
treeef7cfae25bf1b386f03c5dfb8c44266083d0c53b
parent4e4b21da3acc68a7ea55f850cacc13706b7480e9 (diff)
l2tp: hold tunnel used while creating sessions with netlink
Use l2tp_tunnel_get() to retrieve tunnel, so that it can't go away on us. Otherwise l2tp_tunnel_destruct() might release the last reference count concurrently, thus freeing the tunnel while we're using it. Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/l2tp/l2tp_netlink.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index ae5170e26281..57427d430f10 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -518,8 +518,9 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
518 ret = -EINVAL; 518 ret = -EINVAL;
519 goto out; 519 goto out;
520 } 520 }
521
521 tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]); 522 tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
522 tunnel = l2tp_tunnel_find(net, tunnel_id); 523 tunnel = l2tp_tunnel_get(net, tunnel_id);
523 if (!tunnel) { 524 if (!tunnel) {
524 ret = -ENODEV; 525 ret = -ENODEV;
525 goto out; 526 goto out;
@@ -527,24 +528,24 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
527 528
528 if (!info->attrs[L2TP_ATTR_SESSION_ID]) { 529 if (!info->attrs[L2TP_ATTR_SESSION_ID]) {
529 ret = -EINVAL; 530 ret = -EINVAL;
530 goto out; 531 goto out_tunnel;
531 } 532 }
532 session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]); 533 session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
533 534
534 if (!info->attrs[L2TP_ATTR_PEER_SESSION_ID]) { 535 if (!info->attrs[L2TP_ATTR_PEER_SESSION_ID]) {
535 ret = -EINVAL; 536 ret = -EINVAL;
536 goto out; 537 goto out_tunnel;
537 } 538 }
538 peer_session_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_SESSION_ID]); 539 peer_session_id = nla_get_u32(info->attrs[L2TP_ATTR_PEER_SESSION_ID]);
539 540
540 if (!info->attrs[L2TP_ATTR_PW_TYPE]) { 541 if (!info->attrs[L2TP_ATTR_PW_TYPE]) {
541 ret = -EINVAL; 542 ret = -EINVAL;
542 goto out; 543 goto out_tunnel;
543 } 544 }
544 cfg.pw_type = nla_get_u16(info->attrs[L2TP_ATTR_PW_TYPE]); 545 cfg.pw_type = nla_get_u16(info->attrs[L2TP_ATTR_PW_TYPE]);
545 if (cfg.pw_type >= __L2TP_PWTYPE_MAX) { 546 if (cfg.pw_type >= __L2TP_PWTYPE_MAX) {
546 ret = -EINVAL; 547 ret = -EINVAL;
547 goto out; 548 goto out_tunnel;
548 } 549 }
549 550
550 if (tunnel->version > 2) { 551 if (tunnel->version > 2) {
@@ -566,7 +567,7 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
566 u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]); 567 u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]);
567 if (len > 8) { 568 if (len > 8) {
568 ret = -EINVAL; 569 ret = -EINVAL;
569 goto out; 570 goto out_tunnel;
570 } 571 }
571 cfg.cookie_len = len; 572 cfg.cookie_len = len;
572 memcpy(&cfg.cookie[0], nla_data(info->attrs[L2TP_ATTR_COOKIE]), len); 573 memcpy(&cfg.cookie[0], nla_data(info->attrs[L2TP_ATTR_COOKIE]), len);
@@ -575,7 +576,7 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
575 u16 len = nla_len(info->attrs[L2TP_ATTR_PEER_COOKIE]); 576 u16 len = nla_len(info->attrs[L2TP_ATTR_PEER_COOKIE]);
576 if (len > 8) { 577 if (len > 8) {
577 ret = -EINVAL; 578 ret = -EINVAL;
578 goto out; 579 goto out_tunnel;
579 } 580 }
580 cfg.peer_cookie_len = len; 581 cfg.peer_cookie_len = len;
581 memcpy(&cfg.peer_cookie[0], nla_data(info->attrs[L2TP_ATTR_PEER_COOKIE]), len); 582 memcpy(&cfg.peer_cookie[0], nla_data(info->attrs[L2TP_ATTR_PEER_COOKIE]), len);
@@ -618,7 +619,7 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
618 if ((l2tp_nl_cmd_ops[cfg.pw_type] == NULL) || 619 if ((l2tp_nl_cmd_ops[cfg.pw_type] == NULL) ||
619 (l2tp_nl_cmd_ops[cfg.pw_type]->session_create == NULL)) { 620 (l2tp_nl_cmd_ops[cfg.pw_type]->session_create == NULL)) {
620 ret = -EPROTONOSUPPORT; 621 ret = -EPROTONOSUPPORT;
621 goto out; 622 goto out_tunnel;
622 } 623 }
623 624
624 /* Check that pseudowire-specific params are present */ 625 /* Check that pseudowire-specific params are present */
@@ -628,7 +629,7 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
628 case L2TP_PWTYPE_ETH_VLAN: 629 case L2TP_PWTYPE_ETH_VLAN:
629 if (!info->attrs[L2TP_ATTR_VLAN_ID]) { 630 if (!info->attrs[L2TP_ATTR_VLAN_ID]) {
630 ret = -EINVAL; 631 ret = -EINVAL;
631 goto out; 632 goto out_tunnel;
632 } 633 }
633 break; 634 break;
634 case L2TP_PWTYPE_ETH: 635 case L2TP_PWTYPE_ETH:
@@ -656,6 +657,8 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
656 } 657 }
657 } 658 }
658 659
660out_tunnel:
661 l2tp_tunnel_dec_refcount(tunnel);
659out: 662out:
660 return ret; 663 return ret;
661} 664}