netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net-next: make sock diag per-namespace
@ 2012-07-16 12:14 Andrew Vagin
  2012-07-16 12:32 ` Eric Dumazet
  2012-07-16 14:00 ` Ben Hutchings
  0 siblings, 2 replies; 5+ messages in thread
From: Andrew Vagin @ 2012-07-16 12:14 UTC (permalink / raw)
  To: David S. Miller
  Cc: Andrew Vagin, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Pavel Emelyanov,
	linux-kernel, netdev

Before this patch sock_diag works for init_net only and dumps
information about sockets from all namespaces.

This patch expands sock_diag for all name-spaces.
It creates a netlink kernel socket for each netns and filters
data during dumping.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: linux-kernel@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Andrew Vagin <avagin@openvz.org>
---
 include/linux/sock_diag.h   |    1 -
 include/net/net_namespace.h |    1 +
 net/core/sock_diag.c        |   28 ++++++++++++++++++++++------
 net/ipv4/inet_diag.c        |   13 ++++++++++---
 net/ipv4/udp_diag.c         |    3 ++-
 net/unix/diag.c             |    9 +++++++--
 6 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index 6793fac..e3e395a 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);
 
 int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
 
-extern struct sock *sock_diag_nlsk;
 #endif /* KERNEL */
 #endif
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index ac9195e..ae1cd6c 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -101,6 +101,7 @@ struct net {
 	struct netns_xfrm	xfrm;
 #endif
 	struct netns_ipvs	*ipvs;
+	struct sock		*diag_nlsk;
 };
 
 
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 07a29eb..d060251 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -166,23 +166,39 @@ static void sock_diag_rcv(struct sk_buff *skb)
 	mutex_unlock(&sock_diag_mutex);
 }
 
-struct sock *sock_diag_nlsk;
-EXPORT_SYMBOL_GPL(sock_diag_nlsk);
+struct sock *diag_nlsk;
+EXPORT_SYMBOL_GPL(diag_nlsk);
 
-static int __init sock_diag_init(void)
+static int __net_init diag_net_init(struct net *net)
 {
 	struct netlink_kernel_cfg cfg = {
 		.input	= sock_diag_rcv,
 	};
 
-	sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG,
+	net->diag_nlsk = netlink_kernel_create(net, NETLINK_SOCK_DIAG,
 					       THIS_MODULE, &cfg);
-	return sock_diag_nlsk == NULL ? -ENOMEM : 0;
+	return net->diag_nlsk == NULL ? -ENOMEM : 0;
+}
+
+static void __net_exit diag_net_exit(struct net *net)
+{
+	netlink_kernel_release(net->diag_nlsk);
+	net->diag_nlsk = NULL;
+}
+
+static struct pernet_operations diag_net_ops = {
+	.init = diag_net_init,
+	.exit = diag_net_exit,
+};
+
+static int __init sock_diag_init(void)
+{
+	return register_pernet_subsys(&diag_net_ops);
 }
 
 static void __exit sock_diag_exit(void)
 {
-	netlink_kernel_release(sock_diag_nlsk);
+	unregister_pernet_subsys(&diag_net_ops);
 }
 
 module_init(sock_diag_init);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 38064a2..4703c58 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -272,6 +272,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
 	int err;
 	struct sock *sk;
 	struct sk_buff *rep;
+	struct net *net = sock_net(in_skb->sk);
 
 	err = -EINVAL;
 	if (req->sdiag_family == AF_INET) {
@@ -317,7 +318,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s
 		nlmsg_free(rep);
 		goto out;
 	}
-	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
+	err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 	if (err > 0)
 		err = 0;
@@ -724,6 +725,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 {
 	int i, num;
 	int s_i, s_num;
+	struct net *net = sock_net(skb->sk);
 
 	s_i = cb->args[1];
 	s_num = num = cb->args[2];
@@ -743,6 +745,9 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 			sk_nulls_for_each(sk, node, &ilb->head) {
 				struct inet_sock *inet = inet_sk(sk);
 
+				if (!net_eq(sock_net(sk), net))
+					continue;
+
 				if (num < s_num) {
 					num++;
 					continue;
@@ -943,6 +948,7 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
 static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	int hdrlen = sizeof(struct inet_diag_req);
+	struct net *net = sock_net(skb->sk);
 
 	if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX ||
 	    nlmsg_len(nlh) < hdrlen)
@@ -963,7 +969,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 			struct netlink_dump_control c = {
 				.dump = inet_diag_dump_compat,
 			};
-			return netlink_dump_start(sock_diag_nlsk, skb, nlh, &c);
+			return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
 		}
 	}
 
@@ -973,6 +979,7 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 {
 	int hdrlen = sizeof(struct inet_diag_req_v2);
+	struct net *net = sock_net(skb->sk);
 
 	if (nlmsg_len(h) < hdrlen)
 		return -EINVAL;
@@ -991,7 +998,7 @@ static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 			struct netlink_dump_control c = {
 				.dump = inet_diag_dump,
 			};
-			return netlink_dump_start(sock_diag_nlsk, skb, h, &c);
+			return netlink_dump_start(net->diag_nlsk, skb, h, &c);
 		}
 	}
 
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index a7f86a3..52f42f9 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -34,6 +34,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 	int err = -EINVAL;
 	struct sock *sk;
 	struct sk_buff *rep;
+	struct net *net = sock_net(in_skb->sk);
 
 	if (req->sdiag_family == AF_INET)
 		sk = __udp4_lib_lookup(&init_net,
@@ -75,7 +76,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 		kfree_skb(rep);
 		goto out;
 	}
-	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
+	err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 	if (err > 0)
 		err = 0;
diff --git a/net/unix/diag.c b/net/unix/diag.c
index a74864e..750b134 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)
 {
 	struct unix_diag_req *req;
 	int num, s_num, slot, s_slot;
+	struct net *net = sock_net(skb->sk);
 
 	req = nlmsg_data(cb->nlh);
 
@@ -192,6 +193,8 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 		num = 0;
 		sk_for_each(sk, node, &unix_socket_table[slot]) {
+			if (!net_eq(sock_net(sk), net))
+				continue;
 			if (num < s_num)
 				goto next;
 			if (!(req->udiag_states & (1 << sk->sk_state)))
@@ -243,6 +246,7 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
 	struct sock *sk;
 	struct sk_buff *rep;
 	unsigned int extra_len;
+	struct net *net = sock_net(in_skb->sk);
 
 	if (req->udiag_ino == 0)
 		goto out_nosk;
@@ -273,7 +277,7 @@ again:
 
 		goto again;
 	}
-	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
+	err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 	if (err > 0)
 		err = 0;
@@ -287,6 +291,7 @@ out_nosk:
 static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 {
 	int hdrlen = sizeof(struct unix_diag_req);
+	struct net *net = sock_net(skb->sk);
 
 	if (nlmsg_len(h) < hdrlen)
 		return -EINVAL;
@@ -295,7 +300,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
 		struct netlink_dump_control c = {
 			.dump = unix_diag_dump,
 		};
-		return netlink_dump_start(sock_diag_nlsk, skb, h, &c);
+		return netlink_dump_start(net->diag_nlsk, skb, h, &c);
 	} else
 		return unix_diag_get_exact(skb, h, nlmsg_data(h));
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] net-next: make sock diag per-namespace
  2012-07-16 12:14 [PATCH] net-next: make sock diag per-namespace Andrew Vagin
@ 2012-07-16 12:32 ` Eric Dumazet
  2012-07-16 12:38   ` Andrew Vagin
  2012-07-16 14:00 ` Ben Hutchings
  1 sibling, 1 reply; 5+ messages in thread
From: Eric Dumazet @ 2012-07-16 12:32 UTC (permalink / raw)
  To: Andrew Vagin
  Cc: David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Pavel Emelyanov,
	linux-kernel, netdev

On Mon, 2012-07-16 at 16:14 +0400, Andrew Vagin wrote:
> Before this patch sock_diag works for init_net only and dumps
> information about sockets from all namespaces.

...

> diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
> index a7f86a3..52f42f9 100644
> --- a/net/ipv4/udp_diag.c
> +++ b/net/ipv4/udp_diag.c
> @@ -34,6 +34,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
>  	int err = -EINVAL;
>  	struct sock *sk;
>  	struct sk_buff *rep;
> +	struct net *net = sock_net(in_skb->sk);
>  
>  	if (req->sdiag_family == AF_INET)
>  		sk = __udp4_lib_lookup(&init_net,

It seems you didnt fix udp_dump_one() correctly, since it
still mentions &init_net

> @@ -75,7 +76,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
>  		kfree_skb(rep);
>  		goto out;
>  	}
> -	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> +	err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
>  			      MSG_DONTWAIT);
>  	if (err > 0)
>  		err = 0;

udp_dump() also needs some care ?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] net-next: make sock diag per-namespace
  2012-07-16 12:32 ` Eric Dumazet
@ 2012-07-16 12:38   ` Andrew Vagin
  2012-07-16 17:26     ` Jan Ceuleers
  0 siblings, 1 reply; 5+ messages in thread
From: Andrew Vagin @ 2012-07-16 12:38 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Andrew Vagin, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Pavel Emelianov,
	linux-kernel, netdev

On Mon, Jul 16, 2012 at 04:32:25PM +0400, Eric Dumazet wrote:
> On Mon, 2012-07-16 at 16:14 +0400, Andrew Vagin wrote:
> > Before this patch sock_diag works for init_net only and dumps
> > information about sockets from all namespaces.
> 
> ...
> 
> > diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
> > index a7f86a3..52f42f9 100644
> > --- a/net/ipv4/udp_diag.c
> > +++ b/net/ipv4/udp_diag.c
> > @@ -34,6 +34,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
> >  	int err = -EINVAL;
> >  	struct sock *sk;
> >  	struct sk_buff *rep;
> > +	struct net *net = sock_net(in_skb->sk);
> >  
> >  	if (req->sdiag_family == AF_INET)
> >  		sk = __udp4_lib_lookup(&init_net,
> 
> It seems you didnt fix udp_dump_one() correctly, since it
> still mentions &init_net
You are right. Sorry for this stupid fault. I will send a new patch.
> 
> > @@ -75,7 +76,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
> >  		kfree_skb(rep);
> >  		goto out;
> >  	}
> > -	err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> > +	err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid,
> >  			      MSG_DONTWAIT);
> >  	if (err > 0)
> >  		err = 0;
> 
> udp_dump() also needs some care ?
> 
> 
Yes

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] net-next: make sock diag per-namespace
  2012-07-16 12:14 [PATCH] net-next: make sock diag per-namespace Andrew Vagin
  2012-07-16 12:32 ` Eric Dumazet
@ 2012-07-16 14:00 ` Ben Hutchings
  1 sibling, 0 replies; 5+ messages in thread
From: Ben Hutchings @ 2012-07-16 14:00 UTC (permalink / raw)
  To: Andrew Vagin
  Cc: David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, Pavel Emelyanov,
	linux-kernel, netdev

On Mon, 2012-07-16 at 16:14 +0400, Andrew Vagin wrote:
> Before this patch sock_diag works for init_net only and dumps
> information about sockets from all namespaces.
> 
> This patch expands sock_diag for all name-spaces.
> It creates a netlink kernel socket for each netns and filters
> data during dumping.
[...]
> --- a/net/core/sock_diag.c
> +++ b/net/core/sock_diag.c
> @@ -166,23 +166,39 @@ static void sock_diag_rcv(struct sk_buff *skb)
>  	mutex_unlock(&sock_diag_mutex);
>  }
>  
> -struct sock *sock_diag_nlsk;
> -EXPORT_SYMBOL_GPL(sock_diag_nlsk);
> +struct sock *diag_nlsk;
> +EXPORT_SYMBOL_GPL(diag_nlsk);
[...]

This new variable seems to be unused.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] net-next: make sock diag per-namespace
  2012-07-16 12:38   ` Andrew Vagin
@ 2012-07-16 17:26     ` Jan Ceuleers
  0 siblings, 0 replies; 5+ messages in thread
From: Jan Ceuleers @ 2012-07-16 17:26 UTC (permalink / raw)
  To: Andrew Vagin
  Cc: Eric Dumazet, Andrew Vagin, David S. Miller, Alexey Kuznetsov,
	James Morris, Hideaki YOSHIFUJI, Patrick McHardy,
	Pavel Emelianov, linux-kernel, netdev

On 07/16/2012 02:38 PM, Andrew Vagin wrote:
> You are right. Sorry for this stupid fault. I will send a new patch.

Before doing so:

Could you put the "net-next" inside the square brackets (being the tree you are aiming your patch at, which should not end up in the commit log), and mention the subsystem in its place? Perhaps simply "net"?

Just a suggestion.

Thanks, Jan

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-07-16 17:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-16 12:14 [PATCH] net-next: make sock diag per-namespace Andrew Vagin
2012-07-16 12:32 ` Eric Dumazet
2012-07-16 12:38   ` Andrew Vagin
2012-07-16 17:26     ` Jan Ceuleers
2012-07-16 14:00 ` Ben Hutchings

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).