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 | |
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')
-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 | }; |