aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sock_diag.h1
-rw-r--r--include/net/net_namespace.h1
-rw-r--r--net/core/sock_diag.c27
-rw-r--r--net/ipv4/inet_diag.c21
-rw-r--r--net/ipv4/udp_diag.c10
-rw-r--r--net/unix/diag.c9
6 files changed, 51 insertions, 18 deletions
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index 6793fac5eab5..e3e395acc2fd 100644
--- a/include/linux/sock_diag.h
+++ b/include/linux/sock_diag.h
@@ -44,6 +44,5 @@ void sock_diag_save_cookie(void *sk, __u32 *cookie);
44 44
45int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); 45int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
46 46
47extern struct sock *sock_diag_nlsk;
48#endif /* KERNEL */ 47#endif /* KERNEL */
49#endif 48#endif
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ac9195e6a062..ae1cd6c9ba52 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -101,6 +101,7 @@ struct net {
101 struct netns_xfrm xfrm; 101 struct netns_xfrm xfrm;
102#endif 102#endif
103 struct netns_ipvs *ipvs; 103 struct netns_ipvs *ipvs;
104 struct sock *diag_nlsk;
104}; 105};
105 106
106 107
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 07a29eb34a41..9d8755e4a7a5 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -166,23 +166,36 @@ static void sock_diag_rcv(struct sk_buff *skb)
166 mutex_unlock(&sock_diag_mutex); 166 mutex_unlock(&sock_diag_mutex);
167} 167}
168 168
169struct sock *sock_diag_nlsk; 169static int __net_init diag_net_init(struct net *net)
170EXPORT_SYMBOL_GPL(sock_diag_nlsk);
171
172static int __init sock_diag_init(void)
173{ 170{
174 struct netlink_kernel_cfg cfg = { 171 struct netlink_kernel_cfg cfg = {
175 .input = sock_diag_rcv, 172 .input = sock_diag_rcv,
176 }; 173 };
177 174
178 sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 175 net->diag_nlsk = netlink_kernel_create(net, NETLINK_SOCK_DIAG,
179 THIS_MODULE, &cfg); 176 THIS_MODULE, &cfg);
180 return sock_diag_nlsk == NULL ? -ENOMEM : 0; 177 return net->diag_nlsk == NULL ? -ENOMEM : 0;
178}
179
180static void __net_exit diag_net_exit(struct net *net)
181{
182 netlink_kernel_release(net->diag_nlsk);
183 net->diag_nlsk = NULL;
184}
185
186static struct pernet_operations diag_net_ops = {
187 .init = diag_net_init,
188 .exit = diag_net_exit,
189};
190
191static int __init sock_diag_init(void)
192{
193 return register_pernet_subsys(&diag_net_ops);
181} 194}
182 195
183static void __exit sock_diag_exit(void) 196static void __exit sock_diag_exit(void)
184{ 197{
185 netlink_kernel_release(sock_diag_nlsk); 198 unregister_pernet_subsys(&diag_net_ops);
186} 199}
187 200
188module_init(sock_diag_init); 201module_init(sock_diag_init);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 38064a285cca..570e61f9611f 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -272,16 +272,17 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
272 int err; 272 int err;
273 struct sock *sk; 273 struct sock *sk;
274 struct sk_buff *rep; 274 struct sk_buff *rep;
275 struct net *net = sock_net(in_skb->sk);
275 276
276 err = -EINVAL; 277 err = -EINVAL;
277 if (req->sdiag_family == AF_INET) { 278 if (req->sdiag_family == AF_INET) {
278 sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0], 279 sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0],
279 req->id.idiag_dport, req->id.idiag_src[0], 280 req->id.idiag_dport, req->id.idiag_src[0],
280 req->id.idiag_sport, req->id.idiag_if); 281 req->id.idiag_sport, req->id.idiag_if);
281 } 282 }
282#if IS_ENABLED(CONFIG_IPV6) 283#if IS_ENABLED(CONFIG_IPV6)
283 else if (req->sdiag_family == AF_INET6) { 284 else if (req->sdiag_family == AF_INET6) {
284 sk = inet6_lookup(&init_net, hashinfo, 285 sk = inet6_lookup(net, hashinfo,
285 (struct in6_addr *)req->id.idiag_dst, 286 (struct in6_addr *)req->id.idiag_dst,
286 req->id.idiag_dport, 287 req->id.idiag_dport,
287 (struct in6_addr *)req->id.idiag_src, 288 (struct in6_addr *)req->id.idiag_src,
@@ -317,7 +318,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
317 nlmsg_free(rep); 318 nlmsg_free(rep);
318 goto out; 319 goto out;
319 } 320 }
320 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, 321 err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
321 MSG_DONTWAIT); 322 MSG_DONTWAIT);
322 if (err > 0) 323 if (err > 0)
323 err = 0; 324 err = 0;
@@ -724,6 +725,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
724{ 725{
725 int i, num; 726 int i, num;
726 int s_i, s_num; 727 int s_i, s_num;
728 struct net *net = sock_net(skb->sk);
727 729
728 s_i = cb->args[1]; 730 s_i = cb->args[1];
729 s_num = num = cb->args[2]; 731 s_num = num = cb->args[2];
@@ -743,6 +745,9 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
743 sk_nulls_for_each(sk, node, &ilb->head) { 745 sk_nulls_for_each(sk, node, &ilb->head) {
744 struct inet_sock *inet = inet_sk(sk); 746 struct inet_sock *inet = inet_sk(sk);
745 747
748 if (!net_eq(sock_net(sk), net))
749 continue;
750
746 if (num < s_num) { 751 if (num < s_num) {
747 num++; 752 num++;
748 continue; 753 continue;
@@ -813,6 +818,8 @@ skip_listen_ht:
813 sk_nulls_for_each(sk, node, &head->chain) { 818 sk_nulls_for_each(sk, node, &head->chain) {
814 struct inet_sock *inet = inet_sk(sk); 819 struct inet_sock *inet = inet_sk(sk);
815 820
821 if (!net_eq(sock_net(sk), net))
822 continue;
816 if (num < s_num) 823 if (num < s_num)
817 goto next_normal; 824 goto next_normal;
818 if (!(r->idiag_states & (1 << sk->sk_state))) 825 if (!(r->idiag_states & (1 << sk->sk_state)))
@@ -839,6 +846,8 @@ next_normal:
839 846
840 inet_twsk_for_each(tw, node, 847 inet_twsk_for_each(tw, node,
841 &head->twchain) { 848 &head->twchain) {
849 if (!net_eq(twsk_net(tw), net))
850 continue;
842 851
843 if (num < s_num) 852 if (num < s_num)
844 goto next_dying; 853 goto next_dying;
@@ -943,6 +952,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
943static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) 952static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
944{ 953{
945 int hdrlen = sizeof(struct inet_diag_req); 954 int hdrlen = sizeof(struct inet_diag_req);
955 struct net *net = sock_net(skb->sk);
946 956
947 if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX || 957 if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX ||
948 nlmsg_len(nlh) < hdrlen) 958 nlmsg_len(nlh) < hdrlen)
@@ -963,7 +973,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
963 struct netlink_dump_control c = { 973 struct netlink_dump_control c = {
964 .dump = inet_diag_dump_compat, 974 .dump = inet_diag_dump_compat,
965 }; 975 };
966 return netlink_dump_start(sock_diag_nlsk, skb, nlh, &c); 976 return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
967 } 977 }
968 } 978 }
969 979
@@ -973,6 +983,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
973static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) 983static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
974{ 984{
975 int hdrlen = sizeof(struct inet_diag_req_v2); 985 int hdrlen = sizeof(struct inet_diag_req_v2);
986 struct net *net = sock_net(skb->sk);
976 987
977 if (nlmsg_len(h) < hdrlen) 988 if (nlmsg_len(h) < hdrlen)
978 return -EINVAL; 989 return -EINVAL;
@@ -991,7 +1002,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
991 struct netlink_dump_control c = { 1002 struct netlink_dump_control c = {
992 .dump = inet_diag_dump, 1003 .dump = inet_diag_dump,
993 }; 1004 };
994 return netlink_dump_start(sock_diag_nlsk, skb, h, &c); 1005 return netlink_dump_start(net->diag_nlsk, skb, h, &c);
995 } 1006 }
996 } 1007 }
997 1008
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index a7f86a3cd502..16d0960062be 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -34,15 +34,16 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
34 int err = -EINVAL; 34 int err = -EINVAL;
35 struct sock *sk; 35 struct sock *sk;
36 struct sk_buff *rep; 36 struct sk_buff *rep;
37 struct net *net = sock_net(in_skb->sk);
37 38
38 if (req->sdiag_family == AF_INET) 39 if (req->sdiag_family == AF_INET)
39 sk = __udp4_lib_lookup(&init_net, 40 sk = __udp4_lib_lookup(net,
40 req->id.idiag_src[0], req->id.idiag_sport, 41 req->id.idiag_src[0], req->id.idiag_sport,
41 req->id.idiag_dst[0], req->id.idiag_dport, 42 req->id.idiag_dst[0], req->id.idiag_dport,
42 req->id.idiag_if, tbl); 43 req->id.idiag_if, tbl);
43#if IS_ENABLED(CONFIG_IPV6) 44#if IS_ENABLED(CONFIG_IPV6)
44 else if (req->sdiag_family == AF_INET6) 45 else if (req->sdiag_family == AF_INET6)
45 sk = __udp6_lib_lookup(&init_net, 46 sk = __udp6_lib_lookup(net,
46 (struct in6_addr *)req->id.idiag_src, 47 (struct in6_addr *)req->id.idiag_src,
47 req->id.idiag_sport, 48 req->id.idiag_sport,
48 (struct in6_addr *)req->id.idiag_dst, 49 (struct in6_addr *)req->id.idiag_dst,
@@ -75,7 +76,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
75 kfree_skb(rep); 76 kfree_skb(rep);
76 goto out; 77 goto out;
77 } 78 }
78 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, 79 err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
79 MSG_DONTWAIT); 80 MSG_DONTWAIT);
80 if (err > 0) 81 if (err > 0)
81 err = 0; 82 err = 0;
@@ -90,6 +91,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
90 struct inet_diag_req_v2 *r, struct nlattr *bc) 91 struct inet_diag_req_v2 *r, struct nlattr *bc)
91{ 92{
92 int num, s_num, slot, s_slot; 93 int num, s_num, slot, s_slot;
94 struct net *net = sock_net(skb->sk);
93 95
94 s_slot = cb->args[0]; 96 s_slot = cb->args[0];
95 num = s_num = cb->args[1]; 97 num = s_num = cb->args[1];
@@ -106,6 +108,8 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
106 sk_nulls_for_each(sk, node, &hslot->head) { 108 sk_nulls_for_each(sk, node, &hslot->head) {
107 struct inet_sock *inet = inet_sk(sk); 109 struct inet_sock *inet = inet_sk(sk);
108 110
111 if (!net_eq(sock_net(sk), net))
112 continue;
109 if (num < s_num) 113 if (num < s_num)
110 goto next; 114 goto next;
111 if (!(r->idiag_states & (1 << sk->sk_state))) 115 if (!(r->idiag_states & (1 << sk->sk_state)))
diff --git a/net/unix/diag.c b/net/unix/diag.c
index a74864eedfcd..750b13408449 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -177,6 +177,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
177{ 177{
178 struct unix_diag_req *req; 178 struct unix_diag_req *req;
179 int num, s_num, slot, s_slot; 179 int num, s_num, slot, s_slot;
180 struct net *net = sock_net(skb->sk);
180 181
181 req = nlmsg_data(cb->nlh); 182 req = nlmsg_data(cb->nlh);
182 183
@@ -192,6 +193,8 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
192 193
193 num = 0; 194 num = 0;
194 sk_for_each(sk, node, &unix_socket_table[slot]) { 195 sk_for_each(sk, node, &unix_socket_table[slot]) {
196 if (!net_eq(sock_net(sk), net))
197 continue;
195 if (num < s_num) 198 if (num < s_num)
196 goto next; 199 goto next;
197 if (!(req->udiag_states & (1 << sk->sk_state))) 200 if (!(req->udiag_states & (1 << sk->sk_state)))
@@ -243,6 +246,7 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
243 struct sock *sk; 246 struct sock *sk;
244 struct sk_buff *rep; 247 struct sk_buff *rep;
245 unsigned int extra_len; 248 unsigned int extra_len;
249 struct net *net = sock_net(in_skb->sk);
246 250
247 if (req->udiag_ino == 0) 251 if (req->udiag_ino == 0)
248 goto out_nosk; 252 goto out_nosk;
@@ -273,7 +277,7 @@ again:
273 277
274 goto again; 278 goto again;
275 } 279 }
276 err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, 280 err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
277 MSG_DONTWAIT); 281 MSG_DONTWAIT);
278 if (err > 0) 282 if (err > 0)
279 err = 0; 283 err = 0;
@@ -287,6 +291,7 @@ out_nosk:
287static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) 291static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
288{ 292{
289 int hdrlen = sizeof(struct unix_diag_req); 293 int hdrlen = sizeof(struct unix_diag_req);
294 struct net *net = sock_net(skb->sk);
290 295
291 if (nlmsg_len(h) < hdrlen) 296 if (nlmsg_len(h) < hdrlen)
292 return -EINVAL; 297 return -EINVAL;
@@ -295,7 +300,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
295 struct netlink_dump_control c = { 300 struct netlink_dump_control c = {
296 .dump = unix_diag_dump, 301 .dump = unix_diag_dump,
297 }; 302 };
298 return netlink_dump_start(sock_diag_nlsk, skb, h, &c); 303 return netlink_dump_start(net->diag_nlsk, skb, h, &c);
299 } else 304 } else
300 return unix_diag_get_exact(skb, h, nlmsg_data(h)); 305 return unix_diag_get_exact(skb, h, nlmsg_data(h));
301} 306}