diff options
-rw-r--r-- | include/linux/sock_diag.h | 1 | ||||
-rw-r--r-- | include/net/net_namespace.h | 1 | ||||
-rw-r--r-- | net/core/sock_diag.c | 27 | ||||
-rw-r--r-- | net/ipv4/inet_diag.c | 21 | ||||
-rw-r--r-- | net/ipv4/udp_diag.c | 10 | ||||
-rw-r--r-- | net/unix/diag.c | 9 |
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 | ||
45 | int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); | 45 | int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); |
46 | 46 | ||
47 | extern 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 | ||
169 | struct sock *sock_diag_nlsk; | 169 | static int __net_init diag_net_init(struct net *net) |
170 | EXPORT_SYMBOL_GPL(sock_diag_nlsk); | ||
171 | |||
172 | static 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 | |||
180 | static void __net_exit diag_net_exit(struct net *net) | ||
181 | { | ||
182 | netlink_kernel_release(net->diag_nlsk); | ||
183 | net->diag_nlsk = NULL; | ||
184 | } | ||
185 | |||
186 | static struct pernet_operations diag_net_ops = { | ||
187 | .init = diag_net_init, | ||
188 | .exit = diag_net_exit, | ||
189 | }; | ||
190 | |||
191 | static int __init sock_diag_init(void) | ||
192 | { | ||
193 | return register_pernet_subsys(&diag_net_ops); | ||
181 | } | 194 | } |
182 | 195 | ||
183 | static void __exit sock_diag_exit(void) | 196 | static 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 | ||
188 | module_init(sock_diag_init); | 201 | module_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, | |||
943 | static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) | 952 | static 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) | |||
973 | static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | 983 | static 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: | |||
287 | static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | 291 | static 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 | } |