[v3,3/3] net: Create child with CLONE_VM in prepare_net_namespaces()

Submitted by Kirill Tkhai on March 20, 2017, 11:58 a.m.

Details

Message ID 149001113332.11023.8639270598672502337.stgit@localhost.localdomain
State New
Series "net: Create child with CLONE_VM in prepare_net_namespaces()"
Headers show

Commit Message

Kirill Tkhai March 20, 2017, 11:58 a.m.
Some functions in prepare_net_ns() use vmalloc(), and this
memory should be visible to our children.

v3: Call prepare_userns_creds() before restore net.
v2: No functional changes, just killed continue.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/net.c |   25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/net.c b/criu/net.c
index 309e2bd66..a09b5527e 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1749,6 +1749,10 @@  static int create_net_ns(void *arg)
 		pr_perror("Can't set user ns");
 		exit(2);
 	}
+	if (prepare_userns_creds() < 0) {
+		pr_err("Can't prepare creds");
+		exit(3);
+	}
 	close(ufd);
 	ret = do_create_net_ns(ns) ? 3 : 0;
 	exit(ret);
@@ -1756,20 +1760,27 @@  static int create_net_ns(void *arg)
 
 int prepare_net_namespaces()
 {
-	char stack[128] __stack_aligned__;
+	int status, stack_size;
 	struct ns_id *nsid;
-	int status;
+	char *stack;
 	pid_t pid;
 
 	if (!(root_ns_mask & CLONE_NEWNET))
 		return 0;
 
+	stack_size = 2 * 1024 * 1024;
+	stack = mmap(NULL, stack_size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+	if (stack == MAP_FAILED) {
+		pr_perror("Can't allocate stack");
+		return -1;
+	}
+
 	for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
 		if (nsid->nd != &net_ns_desc)
 			continue;
 
 		if (root_user_ns && nsid->user_ns != root_user_ns) {
-			pid = clone(create_net_ns, stack + 128, SIGCHLD, nsid);
+			pid = clone(create_net_ns, stack + stack_size, CLONE_VM | CLONE_FILES | SIGCHLD, nsid);
 			if (pid < 0) {
 				pr_perror("Can't clone");
 				goto err;
@@ -1778,13 +1789,15 @@  int prepare_net_namespaces()
 				pr_perror("Child process waiting %d", status);
 				goto err;
 			}
-			continue;
+		} else {
+			if (do_create_net_ns(nsid))
+				goto err;
+
 		}
 
-		if (do_create_net_ns(nsid))
-			goto err;
 	}
 
+	munmap(stack, stack_size);
 	close_service_fd(NS_FD_OFF);
 
 	return 0;

Comments

Andrey Vagin March 20, 2017, 6:39 p.m.
On Mon, Mar 20, 2017 at 02:58:53PM +0300, Kirill Tkhai wrote:
> Some functions in prepare_net_ns() use vmalloc(), and this
> memory should be visible to our children.
> 
> v3: Call prepare_userns_creds() before restore net.
> v2: No functional changes, just killed continue.
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  criu/net.c |   25 +++++++++++++++++++------
>  1 file changed, 19 insertions(+), 6 deletions(-)
> 
> diff --git a/criu/net.c b/criu/net.c
> index 309e2bd66..a09b5527e 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -1749,6 +1749,10 @@ static int create_net_ns(void *arg)
>  		pr_perror("Can't set user ns");
>  		exit(2);
>  	}
> +	if (prepare_userns_creds() < 0) {
> +		pr_err("Can't prepare creds");
> +		exit(3);
> +	}
>  	close(ufd);
>  	ret = do_create_net_ns(ns) ? 3 : 0;
>  	exit(ret);
> @@ -1756,20 +1760,27 @@ static int create_net_ns(void *arg)
>  
>  int prepare_net_namespaces()
>  {
> -	char stack[128] __stack_aligned__;
> +	int status, stack_size;
>  	struct ns_id *nsid;
> -	int status;
> +	char *stack;
>  	pid_t pid;
>  
>  	if (!(root_ns_mask & CLONE_NEWNET))
>  		return 0;
>  
> +	stack_size = 2 * 1024 * 1024;
> +	stack = mmap(NULL, stack_size, PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> +	if (stack == MAP_FAILED) {
> +		pr_perror("Can't allocate stack");
> +		return -1;
> +	}
> +
>  	for (nsid = ns_ids; nsid != NULL; nsid = nsid->next) {
>  		if (nsid->nd != &net_ns_desc)
>  			continue;
>  
>  		if (root_user_ns && nsid->user_ns != root_user_ns) {
> -			pid = clone(create_net_ns, stack + 128, SIGCHLD, nsid);
> +			pid = clone(create_net_ns, stack + stack_size, CLONE_VM | CLONE_FILES | SIGCHLD, nsid);
>  			if (pid < 0) {
>  				pr_perror("Can't clone");
>  				goto err;
> @@ -1778,13 +1789,15 @@ int prepare_net_namespaces()
>  				pr_perror("Child process waiting %d", status);
>  				goto err;

You have to unmap stack in error cases.

>  			}
> -			continue;
> +		} else {
> +			if (do_create_net_ns(nsid))
> +				goto err;
> +
>  		}
>  
> -		if (do_create_net_ns(nsid))
> -			goto err;
>  	}
>  
> +	munmap(stack, stack_size);
>  	close_service_fd(NS_FD_OFF);
>  
>  	return 0;
>