diff options
| author | Tom Parkin <tparkin@katalix.com> | 2013-01-31 18:43:03 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-02-05 14:20:30 -0500 |
| commit | 167eb17e0b178549f5e19036b16b6d6e35856b67 (patch) | |
| tree | 0f8866d325659e6aef8e10506d4e316335d1e54c /net/l2tp | |
| parent | cbb95e0ca92869cc94a1c5e5ac58395afbbda26e (diff) | |
l2tp: create tunnel sockets in the right namespace
When creating unmanaged tunnel sockets we should honour the network namespace
passed to l2tp_tunnel_create. Furthermore, unmanaged tunnel sockets should
not hold a reference to the network namespace lest they accidentally keep
alive a namespace which should otherwise have been released.
Unmanaged tunnel sockets now drop their namespace reference via sk_change_net,
and are released in a new pernet exit callback, l2tp_exit_net.
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp')
| -rw-r--r-- | net/l2tp/l2tp_core.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 60a498a459dd..b6ba65fa3c50 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1409,18 +1409,18 @@ static void l2tp_tunnel_del_work(struct work_struct *work) | |||
| 1409 | sock = sk->sk_socket; | 1409 | sock = sk->sk_socket; |
| 1410 | BUG_ON(!sock); | 1410 | BUG_ON(!sock); |
| 1411 | 1411 | ||
| 1412 | /* Force the tunnel socket to close. This will eventually | 1412 | /* If the tunnel socket was created directly by the kernel, use the |
| 1413 | * cause the tunnel to be deleted via the normal socket close | 1413 | * sk_* API to release the socket now. Otherwise go through the |
| 1414 | * mechanisms when userspace closes the tunnel socket. | 1414 | * inet_* layer to shut the socket down, and let userspace close it. |
| 1415 | * In either case the tunnel resources are freed in the socket | ||
| 1416 | * destructor when the tunnel socket goes away. | ||
| 1415 | */ | 1417 | */ |
| 1416 | inet_shutdown(sock, 2); | 1418 | if (sock->file == NULL) { |
| 1417 | 1419 | kernel_sock_shutdown(sock, SHUT_RDWR); | |
| 1418 | /* If the tunnel's socket was created by the kernel, | 1420 | sk_release_kernel(sk); |
| 1419 | * close the socket here since the socket was not | 1421 | } else { |
| 1420 | * created by userspace. | 1422 | inet_shutdown(sock, 2); |
| 1421 | */ | 1423 | } |
| 1422 | if (sock->file == NULL) | ||
| 1423 | inet_release(sock); | ||
| 1424 | 1424 | ||
| 1425 | l2tp_tunnel_sock_put(sk); | 1425 | l2tp_tunnel_sock_put(sk); |
| 1426 | } | 1426 | } |
| @@ -1428,29 +1428,37 @@ static void l2tp_tunnel_del_work(struct work_struct *work) | |||
| 1428 | /* Create a socket for the tunnel, if one isn't set up by | 1428 | /* Create a socket for the tunnel, if one isn't set up by |
| 1429 | * userspace. This is used for static tunnels where there is no | 1429 | * userspace. This is used for static tunnels where there is no |
| 1430 | * managing L2TP daemon. | 1430 | * managing L2TP daemon. |
| 1431 | * | ||
| 1432 | * Since we don't want these sockets to keep a namespace alive by | ||
| 1433 | * themselves, we drop the socket's namespace refcount after creation. | ||
| 1434 | * These sockets are freed when the namespace exits using the pernet | ||
| 1435 | * exit hook. | ||
| 1431 | */ | 1436 | */ |
| 1432 | static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct socket **sockp) | 1437 | static int l2tp_tunnel_sock_create(struct net *net, |
| 1438 | u32 tunnel_id, | ||
| 1439 | u32 peer_tunnel_id, | ||
| 1440 | struct l2tp_tunnel_cfg *cfg, | ||
| 1441 | struct socket **sockp) | ||
| 1433 | { | 1442 | { |
| 1434 | int err = -EINVAL; | 1443 | int err = -EINVAL; |
| 1435 | struct sockaddr_in udp_addr; | 1444 | struct socket *sock = NULL; |
| 1445 | struct sockaddr_in udp_addr = {0}; | ||
| 1446 | struct sockaddr_l2tpip ip_addr = {0}; | ||
| 1436 | #if IS_ENABLED(CONFIG_IPV6) | 1447 | #if IS_ENABLED(CONFIG_IPV6) |
| 1437 | struct sockaddr_in6 udp6_addr; | 1448 | struct sockaddr_in6 udp6_addr = {0}; |
| 1438 | struct sockaddr_l2tpip6 ip6_addr; | 1449 | struct sockaddr_l2tpip6 ip6_addr = {0}; |
| 1439 | #endif | 1450 | #endif |
| 1440 | struct sockaddr_l2tpip ip_addr; | ||
| 1441 | struct socket *sock = NULL; | ||
| 1442 | 1451 | ||
| 1443 | switch (cfg->encap) { | 1452 | switch (cfg->encap) { |
| 1444 | case L2TP_ENCAPTYPE_UDP: | 1453 | case L2TP_ENCAPTYPE_UDP: |
| 1445 | #if IS_ENABLED(CONFIG_IPV6) | 1454 | #if IS_ENABLED(CONFIG_IPV6) |
| 1446 | if (cfg->local_ip6 && cfg->peer_ip6) { | 1455 | if (cfg->local_ip6 && cfg->peer_ip6) { |
| 1447 | err = sock_create(AF_INET6, SOCK_DGRAM, 0, sockp); | 1456 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock); |
| 1448 | if (err < 0) | 1457 | if (err < 0) |
| 1449 | goto out; | 1458 | goto out; |
| 1450 | 1459 | ||
| 1451 | sock = *sockp; | 1460 | sk_change_net(sock->sk, net); |
| 1452 | 1461 | ||
| 1453 | memset(&udp6_addr, 0, sizeof(udp6_addr)); | ||
| 1454 | udp6_addr.sin6_family = AF_INET6; | 1462 | udp6_addr.sin6_family = AF_INET6; |
| 1455 | memcpy(&udp6_addr.sin6_addr, cfg->local_ip6, | 1463 | memcpy(&udp6_addr.sin6_addr, cfg->local_ip6, |
| 1456 | sizeof(udp6_addr.sin6_addr)); | 1464 | sizeof(udp6_addr.sin6_addr)); |
| @@ -1472,13 +1480,12 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
| 1472 | } else | 1480 | } else |
| 1473 | #endif | 1481 | #endif |
| 1474 | { | 1482 | { |
| 1475 | err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp); | 1483 | err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock); |
| 1476 | if (err < 0) | 1484 | if (err < 0) |
| 1477 | goto out; | 1485 | goto out; |
| 1478 | 1486 | ||
| 1479 | sock = *sockp; | 1487 | sk_change_net(sock->sk, net); |
| 1480 | 1488 | ||
| 1481 | memset(&udp_addr, 0, sizeof(udp_addr)); | ||
| 1482 | udp_addr.sin_family = AF_INET; | 1489 | udp_addr.sin_family = AF_INET; |
| 1483 | udp_addr.sin_addr = cfg->local_ip; | 1490 | udp_addr.sin_addr = cfg->local_ip; |
| 1484 | udp_addr.sin_port = htons(cfg->local_udp_port); | 1491 | udp_addr.sin_port = htons(cfg->local_udp_port); |
| @@ -1505,14 +1512,13 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
| 1505 | case L2TP_ENCAPTYPE_IP: | 1512 | case L2TP_ENCAPTYPE_IP: |
| 1506 | #if IS_ENABLED(CONFIG_IPV6) | 1513 | #if IS_ENABLED(CONFIG_IPV6) |
| 1507 | if (cfg->local_ip6 && cfg->peer_ip6) { | 1514 | if (cfg->local_ip6 && cfg->peer_ip6) { |
| 1508 | err = sock_create(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP, | 1515 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, |
| 1509 | sockp); | 1516 | IPPROTO_L2TP, &sock); |
| 1510 | if (err < 0) | 1517 | if (err < 0) |
| 1511 | goto out; | 1518 | goto out; |
| 1512 | 1519 | ||
| 1513 | sock = *sockp; | 1520 | sk_change_net(sock->sk, net); |
| 1514 | 1521 | ||
| 1515 | memset(&ip6_addr, 0, sizeof(ip6_addr)); | ||
| 1516 | ip6_addr.l2tp_family = AF_INET6; | 1522 | ip6_addr.l2tp_family = AF_INET6; |
| 1517 | memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6, | 1523 | memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6, |
| 1518 | sizeof(ip6_addr.l2tp_addr)); | 1524 | sizeof(ip6_addr.l2tp_addr)); |
| @@ -1534,14 +1540,13 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
| 1534 | } else | 1540 | } else |
| 1535 | #endif | 1541 | #endif |
| 1536 | { | 1542 | { |
| 1537 | err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, | 1543 | err = sock_create_kern(AF_INET, SOCK_DGRAM, |
| 1538 | sockp); | 1544 | IPPROTO_L2TP, &sock); |
| 1539 | if (err < 0) | 1545 | if (err < 0) |
| 1540 | goto out; | 1546 | goto out; |
| 1541 | 1547 | ||
| 1542 | sock = *sockp; | 1548 | sk_change_net(sock->sk, net); |
| 1543 | 1549 | ||
| 1544 | memset(&ip_addr, 0, sizeof(ip_addr)); | ||
| 1545 | ip_addr.l2tp_family = AF_INET; | 1550 | ip_addr.l2tp_family = AF_INET; |
| 1546 | ip_addr.l2tp_addr = cfg->local_ip; | 1551 | ip_addr.l2tp_addr = cfg->local_ip; |
| 1547 | ip_addr.l2tp_conn_id = tunnel_id; | 1552 | ip_addr.l2tp_conn_id = tunnel_id; |
| @@ -1565,8 +1570,10 @@ static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2t | |||
| 1565 | } | 1570 | } |
| 1566 | 1571 | ||
| 1567 | out: | 1572 | out: |
| 1573 | *sockp = sock; | ||
| 1568 | if ((err < 0) && sock) { | 1574 | if ((err < 0) && sock) { |
| 1569 | sock_release(sock); | 1575 | kernel_sock_shutdown(sock, SHUT_RDWR); |
| 1576 | sk_release_kernel(sock->sk); | ||
| 1570 | *sockp = NULL; | 1577 | *sockp = NULL; |
| 1571 | } | 1578 | } |
| 1572 | 1579 | ||
| @@ -1589,7 +1596,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 | |||
| 1589 | * kernel socket. | 1596 | * kernel socket. |
| 1590 | */ | 1597 | */ |
| 1591 | if (fd < 0) { | 1598 | if (fd < 0) { |
| 1592 | err = l2tp_tunnel_sock_create(tunnel_id, peer_tunnel_id, cfg, &sock); | 1599 | err = l2tp_tunnel_sock_create(net, tunnel_id, peer_tunnel_id, |
| 1600 | cfg, &sock); | ||
| 1593 | if (err < 0) | 1601 | if (err < 0) |
| 1594 | goto err; | 1602 | goto err; |
| 1595 | } else { | 1603 | } else { |
| @@ -1909,8 +1917,21 @@ static __net_init int l2tp_init_net(struct net *net) | |||
| 1909 | return 0; | 1917 | return 0; |
| 1910 | } | 1918 | } |
| 1911 | 1919 | ||
| 1920 | static __net_exit void l2tp_exit_net(struct net *net) | ||
| 1921 | { | ||
| 1922 | struct l2tp_net *pn = l2tp_pernet(net); | ||
| 1923 | struct l2tp_tunnel *tunnel = NULL; | ||
| 1924 | |||
| 1925 | rcu_read_lock_bh(); | ||
| 1926 | list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { | ||
| 1927 | (void)l2tp_tunnel_delete(tunnel); | ||
| 1928 | } | ||
| 1929 | rcu_read_unlock_bh(); | ||
| 1930 | } | ||
| 1931 | |||
| 1912 | static struct pernet_operations l2tp_net_ops = { | 1932 | static struct pernet_operations l2tp_net_ops = { |
| 1913 | .init = l2tp_init_net, | 1933 | .init = l2tp_init_net, |
| 1934 | .exit = l2tp_exit_net, | ||
| 1914 | .id = &l2tp_net_id, | 1935 | .id = &l2tp_net_id, |
| 1915 | .size = sizeof(struct l2tp_net), | 1936 | .size = sizeof(struct l2tp_net), |
| 1916 | }; | 1937 | }; |
