Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 26abe14

Browse files
ebiedermdavem330
authored andcommittedMay 11, 2015
net: Modify sk_alloc to not reference count the netns of kernel sockets.
Now that sk_alloc knows when a kernel socket is being allocated modify it to not reference count the network namespace of kernel sockets. Keep track of if a socket needs reference counting by adding a flag to struct sock called sk_net_refcnt. Update all of the callers of sock_create_kern to stop using sk_change_net and sk_release_kernel as those hacks are no longer needed, to avoid reference counting a kernel socket. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 11aa9c2 commit 26abe14

File tree

8 files changed

+30
-45
lines changed

8 files changed

+30
-45
lines changed
 

‎include/net/inet_common.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
4141

4242
static inline void inet_ctl_sock_destroy(struct sock *sk)
4343
{
44-
sk_release_kernel(sk);
44+
sock_release(sk->sk_socket);
4545
}
4646

4747
#endif

‎include/net/sock.h

+2
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ struct sock_common {
184184
unsigned char skc_reuse:4;
185185
unsigned char skc_reuseport:1;
186186
unsigned char skc_ipv6only:1;
187+
unsigned char skc_net_refcnt:1;
187188
int skc_bound_dev_if;
188189
union {
189190
struct hlist_node skc_bind_node;
@@ -323,6 +324,7 @@ struct sock {
323324
#define sk_reuse __sk_common.skc_reuse
324325
#define sk_reuseport __sk_common.skc_reuseport
325326
#define sk_ipv6only __sk_common.skc_ipv6only
327+
#define sk_net_refcnt __sk_common.skc_net_refcnt
326328
#define sk_bound_dev_if __sk_common.skc_bound_dev_if
327329
#define sk_bind_node __sk_common.skc_bind_node
328330
#define sk_prot __sk_common.skc_prot

‎net/core/sock.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,10 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
14121412
*/
14131413
sk->sk_prot = sk->sk_prot_creator = prot;
14141414
sock_lock_init(sk);
1415-
sock_net_set(sk, get_net(net));
1415+
sk->sk_net_refcnt = kern ? 0 : 1;
1416+
if (likely(sk->sk_net_refcnt))
1417+
get_net(net);
1418+
sock_net_set(sk, net);
14161419
atomic_set(&sk->sk_wmem_alloc, 1);
14171420

14181421
sock_update_classid(sk);
@@ -1446,7 +1449,8 @@ static void __sk_free(struct sock *sk)
14461449
if (sk->sk_peer_cred)
14471450
put_cred(sk->sk_peer_cred);
14481451
put_pid(sk->sk_peer_pid);
1449-
put_net(sock_net(sk));
1452+
if (likely(sk->sk_net_refcnt))
1453+
put_net(sock_net(sk));
14501454
sk_prot_free(sk->sk_prot_creator, sk);
14511455
}
14521456

‎net/ipv4/af_inet.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,
14301430
struct net *net)
14311431
{
14321432
struct socket *sock;
1433-
int rc = sock_create_kern(&init_net, family, type, protocol, &sock);
1433+
int rc = sock_create_kern(net, family, type, protocol, &sock);
14341434

14351435
if (rc == 0) {
14361436
*sk = sock->sk;
@@ -1440,8 +1440,6 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,
14401440
* we do not wish this socket to see incoming packets.
14411441
*/
14421442
(*sk)->sk_prot->unhash(*sk);
1443-
1444-
sk_change_net(*sk, net);
14451443
}
14461444
return rc;
14471445
}

‎net/ipv4/udp_tunnel.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
1515
struct socket *sock = NULL;
1616
struct sockaddr_in udp_addr;
1717

18-
err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &sock);
18+
err = sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock);
1919
if (err < 0)
2020
goto error;
2121

22-
sk_change_net(sock->sk, net);
23-
2422
udp_addr.sin_family = AF_INET;
2523
udp_addr.sin_addr = cfg->local_ip;
2624
udp_addr.sin_port = cfg->local_udp_port;
@@ -47,7 +45,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
4745
error:
4846
if (sock) {
4947
kernel_sock_shutdown(sock, SHUT_RDWR);
50-
sk_release_kernel(sock->sk);
48+
sock_release(sock);
5149
}
5250
*sockp = NULL;
5351
return err;
@@ -101,7 +99,7 @@ void udp_tunnel_sock_release(struct socket *sock)
10199
{
102100
rcu_assign_sk_user_data(sock->sk, NULL);
103101
kernel_sock_shutdown(sock, SHUT_RDWR);
104-
sk_release_kernel(sock->sk);
102+
sock_release(sock);
105103
}
106104
EXPORT_SYMBOL_GPL(udp_tunnel_sock_release);
107105

‎net/ipv6/ip6_udp_tunnel.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
1919
int err;
2020
struct socket *sock = NULL;
2121

22-
err = sock_create_kern(&init_net, AF_INET6, SOCK_DGRAM, 0, &sock);
22+
err = sock_create_kern(net, AF_INET6, SOCK_DGRAM, 0, &sock);
2323
if (err < 0)
2424
goto error;
2525

26-
sk_change_net(sock->sk, net);
27-
2826
udp6_addr.sin6_family = AF_INET6;
2927
memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
3028
sizeof(udp6_addr.sin6_addr));
@@ -55,7 +53,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
5553
error:
5654
if (sock) {
5755
kernel_sock_shutdown(sock, SHUT_RDWR);
58-
sk_release_kernel(sock->sk);
56+
sock_release(sock);
5957
}
6058
*sockp = NULL;
6159
return err;

‎net/l2tp/l2tp_core.c

+6-9
Original file line numberDiff line numberDiff line change
@@ -1334,9 +1334,10 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
13341334
if (sock)
13351335
inet_shutdown(sock, 2);
13361336
} else {
1337-
if (sock)
1337+
if (sock) {
13381338
kernel_sock_shutdown(sock, SHUT_RDWR);
1339-
sk_release_kernel(sk);
1339+
sock_release(sock);
1340+
}
13401341
}
13411342

13421343
l2tp_tunnel_sock_put(sk);
@@ -1399,13 +1400,11 @@ static int l2tp_tunnel_sock_create(struct net *net,
13991400
if (cfg->local_ip6 && cfg->peer_ip6) {
14001401
struct sockaddr_l2tpip6 ip6_addr = {0};
14011402

1402-
err = sock_create_kern(&init_net, AF_INET6, SOCK_DGRAM,
1403+
err = sock_create_kern(net, AF_INET6, SOCK_DGRAM,
14031404
IPPROTO_L2TP, &sock);
14041405
if (err < 0)
14051406
goto out;
14061407

1407-
sk_change_net(sock->sk, net);
1408-
14091408
ip6_addr.l2tp_family = AF_INET6;
14101409
memcpy(&ip6_addr.l2tp_addr, cfg->local_ip6,
14111410
sizeof(ip6_addr.l2tp_addr));
@@ -1429,13 +1428,11 @@ static int l2tp_tunnel_sock_create(struct net *net,
14291428
{
14301429
struct sockaddr_l2tpip ip_addr = {0};
14311430

1432-
err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM,
1431+
err = sock_create_kern(net, AF_INET, SOCK_DGRAM,
14331432
IPPROTO_L2TP, &sock);
14341433
if (err < 0)
14351434
goto out;
14361435

1437-
sk_change_net(sock->sk, net);
1438-
14391436
ip_addr.l2tp_family = AF_INET;
14401437
ip_addr.l2tp_addr = cfg->local_ip;
14411438
ip_addr.l2tp_conn_id = tunnel_id;
@@ -1462,7 +1459,7 @@ static int l2tp_tunnel_sock_create(struct net *net,
14621459
*sockp = sock;
14631460
if ((err < 0) && sock) {
14641461
kernel_sock_shutdown(sock, SHUT_RDWR);
1465-
sk_release_kernel(sock->sk);
1462+
sock_release(sock);
14661463
*sockp = NULL;
14671464
}
14681465

‎net/netfilter/ipvs/ip_vs_sync.c

+9-21
Original file line numberDiff line numberDiff line change
@@ -1457,18 +1457,12 @@ static struct socket *make_send_sock(struct net *net, int id)
14571457
struct socket *sock;
14581458
int result;
14591459

1460-
/* First create a socket move it to right name space later */
1461-
result = sock_create_kern(&init_net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
1460+
/* First create a socket */
1461+
result = sock_create_kern(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
14621462
if (result < 0) {
14631463
pr_err("Error during creation of socket; terminating\n");
14641464
return ERR_PTR(result);
14651465
}
1466-
/*
1467-
* Kernel sockets that are a part of a namespace, should not
1468-
* hold a reference to a namespace in order to allow to stop it.
1469-
* After sk_change_net should be released using sk_release_kernel.
1470-
*/
1471-
sk_change_net(sock->sk, net);
14721466
result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn);
14731467
if (result < 0) {
14741468
pr_err("Error setting outbound mcast interface\n");
@@ -1497,7 +1491,7 @@ static struct socket *make_send_sock(struct net *net, int id)
14971491
return sock;
14981492

14991493
error:
1500-
sk_release_kernel(sock->sk);
1494+
sock_release(sock);
15011495
return ERR_PTR(result);
15021496
}
15031497

@@ -1518,17 +1512,11 @@ static struct socket *make_receive_sock(struct net *net, int id)
15181512
int result;
15191513

15201514
/* First create a socket */
1521-
result = sock_create_kern(&init_net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
1515+
result = sock_create_kern(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
15221516
if (result < 0) {
15231517
pr_err("Error during creation of socket; terminating\n");
15241518
return ERR_PTR(result);
15251519
}
1526-
/*
1527-
* Kernel sockets that are a part of a namespace, should not
1528-
* hold a reference to a namespace in order to allow to stop it.
1529-
* After sk_change_net should be released using sk_release_kernel.
1530-
*/
1531-
sk_change_net(sock->sk, net);
15321520
/* it is equivalent to the REUSEADDR option in user-space */
15331521
sock->sk->sk_reuse = SK_CAN_REUSE;
15341522
result = sysctl_sync_sock_size(ipvs);
@@ -1554,7 +1542,7 @@ static struct socket *make_receive_sock(struct net *net, int id)
15541542
return sock;
15551543

15561544
error:
1557-
sk_release_kernel(sock->sk);
1545+
sock_release(sock);
15581546
return ERR_PTR(result);
15591547
}
15601548

@@ -1692,7 +1680,7 @@ static int sync_thread_master(void *data)
16921680
ip_vs_sync_buff_release(sb);
16931681

16941682
/* release the sending multicast socket */
1695-
sk_release_kernel(tinfo->sock->sk);
1683+
sock_release(tinfo->sock);
16961684
kfree(tinfo);
16971685

16981686
return 0;
@@ -1729,7 +1717,7 @@ static int sync_thread_backup(void *data)
17291717
}
17301718

17311719
/* release the sending multicast socket */
1732-
sk_release_kernel(tinfo->sock->sk);
1720+
sock_release(tinfo->sock);
17331721
kfree(tinfo->buf);
17341722
kfree(tinfo);
17351723

@@ -1854,11 +1842,11 @@ int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid)
18541842
return 0;
18551843

18561844
outsocket:
1857-
sk_release_kernel(sock->sk);
1845+
sock_release(sock);
18581846

18591847
outtinfo:
18601848
if (tinfo) {
1861-
sk_release_kernel(tinfo->sock->sk);
1849+
sock_release(tinfo->sock);
18621850
kfree(tinfo->buf);
18631851
kfree(tinfo);
18641852
}

0 commit comments

Comments
 (0)
Please sign in to comment.