[06/10] net: create a parasite socket for each network namespace

Submitted by Andrei Vagin on Aug. 31, 2016, 10:55 p.m.

Details

Message ID 1472684133-23692-7-git-send-email-avagin@openvz.org
State Rejected
Series "Dump and restore nested network namespaces"
Headers show

Commit Message

Andrei Vagin Aug. 31, 2016, 10:55 p.m.
From: Andrei Vagin <avagin@virtuozzo.com>

CRIU uses an unix socket to comunicate with a parasite code,
but an unix socket created from one netns is invisible
from another netns.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/include/parasite.h |  2 ++
 criu/net.c              | 27 +++++++++++++++++++++------
 criu/parasite-syscall.c | 22 +++-------------------
 3 files changed, 26 insertions(+), 25 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/parasite.h b/criu/include/parasite.h
index 7211477..e26b7f0 100644
--- a/criu/include/parasite.h
+++ b/criu/include/parasite.h
@@ -275,6 +275,8 @@  struct parasite_dump_cgroup_args {
 #define parasite_sym(pblob, ptype, symbol)				\
 	((void *)(pblob) + __pblob_offset(ptype, symbol))
 
+extern int gen_parasite_saddr(struct sockaddr_un *saddr, int key);
+
 #endif /* !__ASSEMBLY__ */
 
 #include "parasite-compat.h"
diff --git a/criu/net.c b/criu/net.c
index e4a7627..7a50640 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -29,6 +29,7 @@ 
 #include "string.h"
 #include "sysctl.h"
 #include "kerndat.h"
+#include "parasite.h"
 
 #include "protobuf.h"
 #include "images/netdev.pb-c.h"
@@ -1661,7 +1662,9 @@  int veth_pair_add(char *in, char *out)
 
 static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
 {
-	int nsret = -1, ret;
+	int nsret = -1, ret, sk;
+	struct sockaddr_un addr;
+	s32 addr_len;
 
 	if (ns->type != NS_CRIU) {
 		pr_info("Switching to %d's net for collecting sockets\n", ns->ns_pid);
@@ -1678,12 +1681,24 @@  static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
 	} else
 		ns->net.nlsk = -1;
 
-	ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
-	if (ret < 0) {
+	sk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
+	if (sk < 0) {
 		pr_perror("Can't create seqsk for parasite");
 		goto err_sq;
 	}
 
+	addr_len = gen_parasite_saddr(&addr, getpid());
+	if (bind(sk, (struct sockaddr *)&addr, addr_len) < 0) {
+		pr_perror("Can't bind socket");
+		goto err_ret;
+	}
+
+	if (listen(sk, 1)) {
+		pr_perror("Can't listen on transport socket");
+		goto err_ret;
+	}
+
+	ns->net.seqsk = sk;
 	ret = 0;
 out:
 	if (nsret >= 0 && restore_ns(nsret, &net_ns_desc) < 0) {
@@ -1695,11 +1710,11 @@  out:
 	return ret;
 
 err_ret:
-	close(ns->net.seqsk);
+	close_safe(&sk);
 err_sq:
-	if (ns->net.nlsk >= 0)
-		close(ns->net.nlsk);
+	close_safe(&ns->net.nlsk);
 err_nl:
+	ret = -1;
 	goto out;
 }
 
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index fb1c245..18923a5 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -363,7 +363,7 @@  int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl)
 	return ret;
 }
 
-static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
+int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
 {
 	int sun_len;
 
@@ -454,25 +454,12 @@  static int restore_child_handler()
 static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
 		struct parasite_init_args *args, struct ns_id *net)
 {
-	static int ssock = -1;
+	int ssock;
 
 	pr_info("Putting tsock into pid %d\n", pid);
 	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
 
-	if (ssock == -1) {
-		ssock = net->net.seqsk;
-		net->net.seqsk = -1;
-
-		if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
-			pr_perror("Can't bind socket");
-			goto err;
-		}
-
-		if (listen(ssock, 1)) {
-			pr_perror("Can't listen on transport socket");
-			goto err;
-		}
-	}
+	ssock = net->net.seqsk;
 
 	/* Check a case when parasite can't initialize a command socket */
 	if (fault_injected(FI_PARASITE_CONNECT))
@@ -484,9 +471,6 @@  static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
 	 */
 	ctl->tsock = -ssock;
 	return 0;
-err:
-	close_safe(&ssock);
-	return -1;
 }
 
 static int accept_tsock(struct parasite_ctl *ctl)

Comments

Pavel Emelianov Oct. 17, 2016, 11:45 a.m.
On 09/01/2016 01:55 AM, Andrei Vagin wrote:
> From: Andrei Vagin <avagin@virtuozzo.com>

Create? It's already created as such. Should the subject rather be
'move parasite socket binding and listening to another place'?

> CRIU uses an unix socket to comunicate with a parasite code,
> but an unix socket created from one netns is invisible
> from another netns.
> 
> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
> ---
>  criu/include/parasite.h |  2 ++
>  criu/net.c              | 27 +++++++++++++++++++++------
>  criu/parasite-syscall.c | 22 +++-------------------
>  3 files changed, 26 insertions(+), 25 deletions(-)
> 
> diff --git a/criu/include/parasite.h b/criu/include/parasite.h
> index 7211477..e26b7f0 100644
> --- a/criu/include/parasite.h
> +++ b/criu/include/parasite.h
> @@ -275,6 +275,8 @@ struct parasite_dump_cgroup_args {
>  #define parasite_sym(pblob, ptype, symbol)				\
>  	((void *)(pblob) + __pblob_offset(ptype, symbol))
>  
> +extern int gen_parasite_saddr(struct sockaddr_un *saddr, int key);
> +
>  #endif /* !__ASSEMBLY__ */
>  
>  #include "parasite-compat.h"
> diff --git a/criu/net.c b/criu/net.c
> index e4a7627..7a50640 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -29,6 +29,7 @@
>  #include "string.h"
>  #include "sysctl.h"
>  #include "kerndat.h"
> +#include "parasite.h"
>  
>  #include "protobuf.h"
>  #include "images/netdev.pb-c.h"
> @@ -1661,7 +1662,9 @@ int veth_pair_add(char *in, char *out)
>  
>  static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
>  {
> -	int nsret = -1, ret;
> +	int nsret = -1, ret, sk;
> +	struct sockaddr_un addr;
> +	s32 addr_len;
>  
>  	if (ns->type != NS_CRIU) {
>  		pr_info("Switching to %d's net for collecting sockets\n", ns->ns_pid);
> @@ -1678,12 +1681,24 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
>  	} else
>  		ns->net.nlsk = -1;
>  
> -	ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
> -	if (ret < 0) {
> +	sk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
> +	if (sk < 0) {
>  		pr_perror("Can't create seqsk for parasite");
>  		goto err_sq;
>  	}
>  
> +	addr_len = gen_parasite_saddr(&addr, getpid());
> +	if (bind(sk, (struct sockaddr *)&addr, addr_len) < 0) {
> +		pr_perror("Can't bind socket");
> +		goto err_ret;
> +	}
> +
> +	if (listen(sk, 1)) {
> +		pr_perror("Can't listen on transport socket");
> +		goto err_ret;
> +	}
> +
> +	ns->net.seqsk = sk;
>  	ret = 0;
>  out:
>  	if (nsret >= 0 && restore_ns(nsret, &net_ns_desc) < 0) {
> @@ -1695,11 +1710,11 @@ out:
>  	return ret;
>  
>  err_ret:
> -	close(ns->net.seqsk);
> +	close_safe(&sk);
>  err_sq:
> -	if (ns->net.nlsk >= 0)
> -		close(ns->net.nlsk);
> +	close_safe(&ns->net.nlsk);
>  err_nl:
> +	ret = -1;
>  	goto out;
>  }
>  
> diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
> index fb1c245..18923a5 100644
> --- a/criu/parasite-syscall.c
> +++ b/criu/parasite-syscall.c
> @@ -363,7 +363,7 @@ int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl)
>  	return ret;
>  }
>  
> -static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
> +int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
>  {
>  	int sun_len;
>  
> @@ -454,25 +454,12 @@ static int restore_child_handler()
>  static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
>  		struct parasite_init_args *args, struct ns_id *net)
>  {
> -	static int ssock = -1;
> +	int ssock;
>  
>  	pr_info("Putting tsock into pid %d\n", pid);
>  	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
>  
> -	if (ssock == -1) {
> -		ssock = net->net.seqsk;
> -		net->net.seqsk = -1;
> -
> -		if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
> -			pr_perror("Can't bind socket");
> -			goto err;
> -		}
> -
> -		if (listen(ssock, 1)) {
> -			pr_perror("Can't listen on transport socket");
> -			goto err;
> -		}
> -	}
> +	ssock = net->net.seqsk;
>  
>  	/* Check a case when parasite can't initialize a command socket */
>  	if (fault_injected(FI_PARASITE_CONNECT))
> @@ -484,9 +471,6 @@ static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
>  	 */
>  	ctl->tsock = -ssock;
>  	return 0;
> -err:
> -	close_safe(&ssock);
> -	return -1;
>  }
>  
>  static int accept_tsock(struct parasite_ctl *ctl)
>
Andrey Vagin Oct. 20, 2016, 11:54 p.m.
On Mon, Oct 17, 2016 at 02:45:42PM +0300, Pavel Emelyanov wrote:
> On 09/01/2016 01:55 AM, Andrei Vagin wrote:
> > From: Andrei Vagin <avagin@virtuozzo.com>
> 
> Create? It's already created as such. Should the subject rather be
> 'move parasite socket binding and listening to another place'?

"create" means to create a socket which is ready to accept a
connection;).

The main thing is in "static int ssock = -1;", this means that only one
socket will be "created".
> 
> > CRIU uses an unix socket to comunicate with a parasite code,
> > but an unix socket created from one netns is invisible
> > from another netns.
> > 
> > Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
> > ---
> >  criu/include/parasite.h |  2 ++
> >  criu/net.c              | 27 +++++++++++++++++++++------
> >  criu/parasite-syscall.c | 22 +++-------------------
> >  3 files changed, 26 insertions(+), 25 deletions(-)
> > 
> > diff --git a/criu/include/parasite.h b/criu/include/parasite.h
> > index 7211477..e26b7f0 100644
> > --- a/criu/include/parasite.h
> > +++ b/criu/include/parasite.h
> > @@ -275,6 +275,8 @@ struct parasite_dump_cgroup_args {
> >  #define parasite_sym(pblob, ptype, symbol)				\
> >  	((void *)(pblob) + __pblob_offset(ptype, symbol))
> >  
> > +extern int gen_parasite_saddr(struct sockaddr_un *saddr, int key);
> > +
> >  #endif /* !__ASSEMBLY__ */
> >  
> >  #include "parasite-compat.h"
> > diff --git a/criu/net.c b/criu/net.c
> > index e4a7627..7a50640 100644
> > --- a/criu/net.c
> > +++ b/criu/net.c
> > @@ -29,6 +29,7 @@
> >  #include "string.h"
> >  #include "sysctl.h"
> >  #include "kerndat.h"
> > +#include "parasite.h"
> >  
> >  #include "protobuf.h"
> >  #include "images/netdev.pb-c.h"
> > @@ -1661,7 +1662,9 @@ int veth_pair_add(char *in, char *out)
> >  
> >  static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
> >  {
> > -	int nsret = -1, ret;
> > +	int nsret = -1, ret, sk;
> > +	struct sockaddr_un addr;
> > +	s32 addr_len;
> >  
> >  	if (ns->type != NS_CRIU) {
> >  		pr_info("Switching to %d's net for collecting sockets\n", ns->ns_pid);
> > @@ -1678,12 +1681,24 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
> >  	} else
> >  		ns->net.nlsk = -1;
> >  
> > -	ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
> > -	if (ret < 0) {
> > +	sk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
> > +	if (sk < 0) {
> >  		pr_perror("Can't create seqsk for parasite");
> >  		goto err_sq;
> >  	}
> >  
> > +	addr_len = gen_parasite_saddr(&addr, getpid());
> > +	if (bind(sk, (struct sockaddr *)&addr, addr_len) < 0) {
> > +		pr_perror("Can't bind socket");
> > +		goto err_ret;
> > +	}
> > +
> > +	if (listen(sk, 1)) {
> > +		pr_perror("Can't listen on transport socket");
> > +		goto err_ret;
> > +	}
> > +
> > +	ns->net.seqsk = sk;
> >  	ret = 0;
> >  out:
> >  	if (nsret >= 0 && restore_ns(nsret, &net_ns_desc) < 0) {
> > @@ -1695,11 +1710,11 @@ out:
> >  	return ret;
> >  
> >  err_ret:
> > -	close(ns->net.seqsk);
> > +	close_safe(&sk);
> >  err_sq:
> > -	if (ns->net.nlsk >= 0)
> > -		close(ns->net.nlsk);
> > +	close_safe(&ns->net.nlsk);
> >  err_nl:
> > +	ret = -1;
> >  	goto out;
> >  }
> >  
> > diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
> > index fb1c245..18923a5 100644
> > --- a/criu/parasite-syscall.c
> > +++ b/criu/parasite-syscall.c
> > @@ -363,7 +363,7 @@ int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl)
> >  	return ret;
> >  }
> >  
> > -static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
> > +int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
> >  {
> >  	int sun_len;
> >  
> > @@ -454,25 +454,12 @@ static int restore_child_handler()
> >  static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
> >  		struct parasite_init_args *args, struct ns_id *net)
> >  {
> > -	static int ssock = -1;
> > +	int ssock;
> >  
> >  	pr_info("Putting tsock into pid %d\n", pid);
> >  	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
> >  
> > -	if (ssock == -1) {
> > -		ssock = net->net.seqsk;
> > -		net->net.seqsk = -1;
> > -
> > -		if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
> > -			pr_perror("Can't bind socket");
> > -			goto err;
> > -		}
> > -
> > -		if (listen(ssock, 1)) {
> > -			pr_perror("Can't listen on transport socket");
> > -			goto err;
> > -		}
> > -	}
> > +	ssock = net->net.seqsk;
> >  
> >  	/* Check a case when parasite can't initialize a command socket */
> >  	if (fault_injected(FI_PARASITE_CONNECT))
> > @@ -484,9 +471,6 @@ static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
> >  	 */
> >  	ctl->tsock = -ssock;
> >  	return 0;
> > -err:
> > -	close_safe(&ssock);
> > -	return -1;
> >  }
> >  
> >  static int accept_tsock(struct parasite_ctl *ctl)
> > 
>