summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2018-04-10 15:01:12 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-11 17:41:27 -0400
commit6b9f34239b00e6956a267abed2bc559ede556ad6 (patch)
tree1ac284e76f987efb38fb511ede5df4ad044053f5 /net
parent83c1f36f9880814b24cdf6c2f91f66f61db65326 (diff)
l2tp: fix races in tunnel creation
l2tp_tunnel_create() inserts the new tunnel into the namespace's tunnel list and sets the socket's ->sk_user_data field, before returning it to the caller. Therefore, there are two ways the tunnel can be accessed and freed, before the caller even had the opportunity to take a reference. In practice, syzbot could crash the module by closing the socket right after a new tunnel was returned to pppol2tp_create(). This patch moves tunnel registration out of l2tp_tunnel_create(), so that the caller can safely hold a reference before publishing the tunnel. This second step is done with the new l2tp_tunnel_register() function, which is now responsible for associating the tunnel to its socket and for inserting it into the namespace's list. While moving the code to l2tp_tunnel_register(), a few modifications have been done. First, the socket validation tests are done in a helper function, for clarity. Also, modifying the socket is now done after having inserted the tunnel to the namespace's tunnels list. This will allow insertion to fail, without having to revert theses modifications in the error path (a followup patch will check for duplicate tunnels before insertion). Either the socket is a kernel socket which we control, or it is a user-space socket for which we have a reference on the file descriptor. In any case, the socket isn't going to be closed from under us. Reported-by: syzbot+fbeeb5c3b538e8545644@syzkaller.appspotmail.com Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/l2tp/l2tp_core.c192
-rw-r--r--net/l2tp/l2tp_core.h3
-rw-r--r--net/l2tp/l2tp_netlink.c16
-rw-r--r--net/l2tp/l2tp_ppp.c9
4 files changed, 110 insertions, 110 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 14b67dfacc4b..afb42d142807 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1436,74 +1436,11 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1436{ 1436{
1437 struct l2tp_tunnel *tunnel = NULL; 1437 struct l2tp_tunnel *tunnel = NULL;
1438 int err; 1438 int err;
1439 struct socket *sock = NULL;
1440 struct sock *sk = NULL;
1441 struct l2tp_net *pn;
1442 enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; 1439 enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
1443 1440
1444 /* Get the tunnel socket from the fd, which was opened by
1445 * the userspace L2TP daemon. If not specified, create a
1446 * kernel socket.
1447 */
1448 if (fd < 0) {
1449 err = l2tp_tunnel_sock_create(net, tunnel_id, peer_tunnel_id,
1450 cfg, &sock);
1451 if (err < 0)
1452 goto err;
1453 } else {
1454 sock = sockfd_lookup(fd, &err);
1455 if (!sock) {
1456 pr_err("tunl %u: sockfd_lookup(fd=%d) returned %d\n",
1457 tunnel_id, fd, err);
1458 err = -EBADF;
1459 goto err;
1460 }
1461
1462 /* Reject namespace mismatches */
1463 if (!net_eq(sock_net(sock->sk), net)) {
1464 pr_err("tunl %u: netns mismatch\n", tunnel_id);
1465 err = -EINVAL;
1466 goto err;
1467 }
1468 }
1469
1470 sk = sock->sk;
1471
1472 if (cfg != NULL) 1441 if (cfg != NULL)
1473 encap = cfg->encap; 1442 encap = cfg->encap;
1474 1443
1475 /* Quick sanity checks */
1476 err = -EPROTONOSUPPORT;
1477 if (sk->sk_type != SOCK_DGRAM) {
1478 pr_debug("tunl %hu: fd %d wrong socket type\n",
1479 tunnel_id, fd);
1480 goto err;
1481 }
1482 switch (encap) {
1483 case L2TP_ENCAPTYPE_UDP:
1484 if (sk->sk_protocol != IPPROTO_UDP) {
1485 pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
1486 tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP);
1487 goto err;
1488 }
1489 break;
1490 case L2TP_ENCAPTYPE_IP:
1491 if (sk->sk_protocol != IPPROTO_L2TP) {
1492 pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
1493 tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP);
1494 goto err;
1495 }
1496 break;
1497 }
1498
1499 /* Check if this socket has already been prepped */
1500 tunnel = l2tp_tunnel(sk);
1501 if (tunnel != NULL) {
1502 /* This socket has already been prepped */
1503 err = -EBUSY;
1504 goto err;
1505 }
1506
1507 tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); 1444 tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL);
1508 if (tunnel == NULL) { 1445 if (tunnel == NULL) {
1509 err = -ENOMEM; 1446 err = -ENOMEM;
@@ -1520,72 +1457,113 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1520 rwlock_init(&tunnel->hlist_lock); 1457 rwlock_init(&tunnel->hlist_lock);
1521 tunnel->acpt_newsess = true; 1458 tunnel->acpt_newsess = true;
1522 1459
1523 /* The net we belong to */
1524 tunnel->l2tp_net = net;
1525 pn = l2tp_pernet(net);
1526
1527 if (cfg != NULL) 1460 if (cfg != NULL)
1528 tunnel->debug = cfg->debug; 1461 tunnel->debug = cfg->debug;
1529 1462
1530 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
1531 tunnel->encap = encap; 1463 tunnel->encap = encap;
1532 if (encap == L2TP_ENCAPTYPE_UDP) {
1533 struct udp_tunnel_sock_cfg udp_cfg = { };
1534
1535 udp_cfg.sk_user_data = tunnel;
1536 udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
1537 udp_cfg.encap_rcv = l2tp_udp_encap_recv;
1538 udp_cfg.encap_destroy = l2tp_udp_encap_destroy;
1539
1540 setup_udp_tunnel_sock(net, sock, &udp_cfg);
1541 } else {
1542 sk->sk_user_data = tunnel;
1543 }
1544 1464
1545 /* Bump the reference count. The tunnel context is deleted
1546 * only when this drops to zero. A reference is also held on
1547 * the tunnel socket to ensure that it is not released while
1548 * the tunnel is extant. Must be done before sk_destruct is
1549 * set.
1550 */
1551 refcount_set(&tunnel->ref_count, 1); 1465 refcount_set(&tunnel->ref_count, 1);
1552 sock_hold(sk);
1553 tunnel->sock = sk;
1554 tunnel->fd = fd; 1466 tunnel->fd = fd;
1555 1467
1556 /* Hook on the tunnel socket destructor so that we can cleanup
1557 * if the tunnel socket goes away.
1558 */
1559 tunnel->old_sk_destruct = sk->sk_destruct;
1560 sk->sk_destruct = &l2tp_tunnel_destruct;
1561 lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
1562
1563 sk->sk_allocation = GFP_ATOMIC;
1564
1565 /* Init delete workqueue struct */ 1468 /* Init delete workqueue struct */
1566 INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work); 1469 INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
1567 1470
1568 /* Add tunnel to our list */
1569 INIT_LIST_HEAD(&tunnel->list); 1471 INIT_LIST_HEAD(&tunnel->list);
1570 spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1571 list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
1572 spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
1573 1472
1574 err = 0; 1473 err = 0;
1575err: 1474err:
1576 if (tunnelp) 1475 if (tunnelp)
1577 *tunnelp = tunnel; 1476 *tunnelp = tunnel;
1578 1477
1579 /* If tunnel's socket was created by the kernel, it doesn't
1580 * have a file.
1581 */
1582 if (sock && sock->file)
1583 sockfd_put(sock);
1584
1585 return err; 1478 return err;
1586} 1479}
1587EXPORT_SYMBOL_GPL(l2tp_tunnel_create); 1480EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
1588 1481
1482static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
1483 enum l2tp_encap_type encap)
1484{
1485 if (!net_eq(sock_net(sk), net))
1486 return -EINVAL;
1487
1488 if (sk->sk_type != SOCK_DGRAM)
1489 return -EPROTONOSUPPORT;
1490
1491 if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) ||
1492 (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP))
1493 return -EPROTONOSUPPORT;
1494
1495 if (sk->sk_user_data)
1496 return -EBUSY;
1497
1498 return 0;
1499}
1500
1501int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
1502 struct l2tp_tunnel_cfg *cfg)
1503{
1504 struct l2tp_net *pn;
1505 struct socket *sock;
1506 struct sock *sk;
1507 int ret;
1508
1509 if (tunnel->fd < 0) {
1510 ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id,
1511 tunnel->peer_tunnel_id, cfg,
1512 &sock);
1513 if (ret < 0)
1514 goto err;
1515 } else {
1516 sock = sockfd_lookup(tunnel->fd, &ret);
1517 if (!sock)
1518 goto err;
1519
1520 ret = l2tp_validate_socket(sock->sk, net, tunnel->encap);
1521 if (ret < 0)
1522 goto err_sock;
1523 }
1524
1525 sk = sock->sk;
1526
1527 sock_hold(sk);
1528 tunnel->sock = sk;
1529 tunnel->l2tp_net = net;
1530
1531 pn = l2tp_pernet(net);
1532 spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1533 list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
1534 spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
1535
1536 if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
1537 struct udp_tunnel_sock_cfg udp_cfg = {
1538 .sk_user_data = tunnel,
1539 .encap_type = UDP_ENCAP_L2TPINUDP,
1540 .encap_rcv = l2tp_udp_encap_recv,
1541 .encap_destroy = l2tp_udp_encap_destroy,
1542 };
1543
1544 setup_udp_tunnel_sock(net, sock, &udp_cfg);
1545 } else {
1546 sk->sk_user_data = tunnel;
1547 }
1548
1549 tunnel->old_sk_destruct = sk->sk_destruct;
1550 sk->sk_destruct = &l2tp_tunnel_destruct;
1551 lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class,
1552 "l2tp_sock");
1553 sk->sk_allocation = GFP_ATOMIC;
1554
1555 if (tunnel->fd >= 0)
1556 sockfd_put(sock);
1557
1558 return 0;
1559
1560err_sock:
1561 sockfd_put(sock);
1562err:
1563 return ret;
1564}
1565EXPORT_SYMBOL_GPL(l2tp_tunnel_register);
1566
1589/* This function is used by the netlink TUNNEL_DELETE command. 1567/* This function is used by the netlink TUNNEL_DELETE command.
1590 */ 1568 */
1591void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) 1569void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 2718d0b284d0..12f0fa82f162 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -226,6 +226,9 @@ struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth);
226int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, 226int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,
227 u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, 227 u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg,
228 struct l2tp_tunnel **tunnelp); 228 struct l2tp_tunnel **tunnelp);
229int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
230 struct l2tp_tunnel_cfg *cfg);
231
229void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); 232void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
230void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); 233void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
231struct l2tp_session *l2tp_session_create(int priv_size, 234struct l2tp_session *l2tp_session_create(int priv_size,
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index e7ea9c4b89ff..45db9b73eb1a 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -251,9 +251,19 @@ static int l2tp_nl_cmd_tunnel_create(struct sk_buff *skb, struct genl_info *info
251 break; 251 break;
252 } 252 }
253 253
254 if (ret >= 0) 254 if (ret < 0)
255 ret = l2tp_tunnel_notify(&l2tp_nl_family, info, 255 goto out;
256 tunnel, L2TP_CMD_TUNNEL_CREATE); 256
257 l2tp_tunnel_inc_refcount(tunnel);
258 ret = l2tp_tunnel_register(tunnel, net, &cfg);
259 if (ret < 0) {
260 kfree(tunnel);
261 goto out;
262 }
263 ret = l2tp_tunnel_notify(&l2tp_nl_family, info, tunnel,
264 L2TP_CMD_TUNNEL_CREATE);
265 l2tp_tunnel_dec_refcount(tunnel);
266
257out: 267out:
258 return ret; 268 return ret;
259} 269}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index d6deca11da19..896bbca9bdaa 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -698,6 +698,15 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
698 error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel); 698 error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel);
699 if (error < 0) 699 if (error < 0)
700 goto end; 700 goto end;
701
702 l2tp_tunnel_inc_refcount(tunnel);
703 error = l2tp_tunnel_register(tunnel, sock_net(sk),
704 &tcfg);
705 if (error < 0) {
706 kfree(tunnel);
707 goto end;
708 }
709 drop_tunnel = true;
701 } 710 }
702 } else { 711 } else {
703 /* Error if we can't find the tunnel */ 712 /* Error if we can't find the tunnel */