[v3,25/33] user_ns: Set user_ns before net_ns creation

Submitted by Kirill Tkhai on Feb. 16, 2017, 12:10 p.m.

Details

Message ID 148724701494.22444.17229631456601059855.stgit@localhost.localdomain
State New
Series "Nested user namespaces support"
Headers show

Commit Message

Kirill Tkhai Feb. 16, 2017, 12:10 p.m.
Since net ns may reffer not only to root_user_ns,
set appropriate user_ns before its creation.

v3: New

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

Patch hide | download patch | download mbox

diff --git a/criu/net.c b/criu/net.c
index 200199822..fb4d9f84d 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1721,9 +1721,39 @@  static int open_net_ns(struct ns_id *nsid, struct rst_info *rst)
 	return 0;
 }
 
+static int create_net_ns(void *arg)
+{
+	struct ns_id *uns, *ns = arg;
+	int ufd;
+
+	uns = ns->user_ns;
+	ufd = fdstore_get(uns->user.nsfd_id);
+	if (ufd < 0) {
+		pr_err("Can't get user ns\n");
+		exit(1);
+	}
+	if (setns(ufd, CLONE_NEWUSER) < 0) {
+		pr_perror("Can't set user ns");
+		exit(2);
+	}
+	close(ufd);
+	if (unshare(CLONE_NEWNET)) {
+		pr_perror("Unable to create a new netns");
+		exit(3);
+	}
+	if (prepare_net_ns(ns->id))
+		exit(4);
+	if (open_net_ns(ns, rsti(root_item)))
+		exit(5);
+	exit(0);
+}
+
 int prepare_net_namespaces()
 {
+	char stack[128] __stack_aligned__;
 	struct ns_id *nsid;
+	int status;
+	pid_t pid;
 
 	if (!(root_ns_mask & CLONE_NEWNET))
 		return 0;
@@ -1732,6 +1762,19 @@  int prepare_net_namespaces()
 		if (nsid->nd != &net_ns_desc)
 			continue;
 
+		if (root_user_ns && nsid->user_ns != root_user_ns) {
+			pid = clone(create_net_ns, stack + 128, CLONE_NEWNET | SIGCHLD, nsid);
+			if (pid < 0) {
+				pr_perror("Can't clone");
+				goto err;
+			}
+			if (waitpid(pid, &status, 0) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
+				pr_perror("Child process waiting %d", status);
+				goto err;
+			}
+			continue;
+		}
+
 		if (unshare(CLONE_NEWNET)) {
 			pr_perror("Unable to create a new netns");
 			goto err;

Comments

Andrey Vagin Feb. 21, 2017, 7:34 a.m.
On Thu, Feb 16, 2017 at 03:10:14PM +0300, Kirill Tkhai wrote:
> Since net ns may reffer not only to root_user_ns,
> set appropriate user_ns before its creation.

We need a test for this case

> 
> v3: New
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  criu/net.c |   43 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/criu/net.c b/criu/net.c
> index 200199822..fb4d9f84d 100644
> --- a/criu/net.c
> +++ b/criu/net.c
> @@ -1721,9 +1721,39 @@ static int open_net_ns(struct ns_id *nsid, struct rst_info *rst)
>  	return 0;
>  }
>  
> +static int create_net_ns(void *arg)
> +{
> +	struct ns_id *uns, *ns = arg;
> +	int ufd;
> +
> +	uns = ns->user_ns;
> +	ufd = fdstore_get(uns->user.nsfd_id);
> +	if (ufd < 0) {
> +		pr_err("Can't get user ns\n");
> +		exit(1);
> +	}
> +	if (setns(ufd, CLONE_NEWUSER) < 0) {
> +		pr_perror("Can't set user ns");
> +		exit(2);
> +	}

should we set a proper uid here?

> +	close(ufd);
> +	if (unshare(CLONE_NEWNET)) {
> +		pr_perror("Unable to create a new netns");
> +		exit(3);
> +	}
> +	if (prepare_net_ns(ns->id))
> +		exit(4);
> +	if (open_net_ns(ns, rsti(root_item)))
> +		exit(5);
> +	exit(0);
> +}
> +
>  int prepare_net_namespaces()
>  {
> +	char stack[128] __stack_aligned__;
>  	struct ns_id *nsid;
> +	int status;
> +	pid_t pid;
>  
>  	if (!(root_ns_mask & CLONE_NEWNET))
>  		return 0;
> @@ -1732,6 +1762,19 @@ int prepare_net_namespaces()
>  		if (nsid->nd != &net_ns_desc)
>  			continue;
>  
> +		if (root_user_ns && nsid->user_ns != root_user_ns) {
> +			pid = clone(create_net_ns, stack + 128, CLONE_NEWNET | SIGCHLD, nsid);
> +			if (pid < 0) {
> +				pr_perror("Can't clone");
> +				goto err;
> +			}
> +			if (waitpid(pid, &status, 0) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
> +				pr_perror("Child process waiting %d", status);
> +				goto err;
> +			}
> +			continue;
> +		}
> +
>  		if (unshare(CLONE_NEWNET)) {
>  			pr_perror("Unable to create a new netns");
>  			goto err;
> 
> _______________________________________________
> CRIU mailing list
> CRIU@openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
Kirill Tkhai Feb. 21, 2017, 2:13 p.m.
On 21.02.2017 10:34, Andrei Vagin wrote:
> On Thu, Feb 16, 2017 at 03:10:14PM +0300, Kirill Tkhai wrote:
>> Since net ns may reffer not only to root_user_ns,
>> set appropriate user_ns before its creation.
> 
> We need a test for this case

There is unshare(CLONE_NEWNET) in userns00.
 
>>
>> v3: New
>>
>> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
>> ---
>>  criu/net.c |   43 +++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 43 insertions(+)
>>
>> diff --git a/criu/net.c b/criu/net.c
>> index 200199822..fb4d9f84d 100644
>> --- a/criu/net.c
>> +++ b/criu/net.c
>> @@ -1721,9 +1721,39 @@ static int open_net_ns(struct ns_id *nsid, struct rst_info *rst)
>>  	return 0;
>>  }
>>  
>> +static int create_net_ns(void *arg)
>> +{
>> +	struct ns_id *uns, *ns = arg;
>> +	int ufd;
>> +
>> +	uns = ns->user_ns;
>> +	ufd = fdstore_get(uns->user.nsfd_id);
>> +	if (ufd < 0) {
>> +		pr_err("Can't get user ns\n");
>> +		exit(1);
>> +	}
>> +	if (setns(ufd, CLONE_NEWUSER) < 0) {
>> +		pr_perror("Can't set user ns");
>> +		exit(2);
>> +	}
> 
> should we set a proper uid here?

I haven't seen, unshare() requires uid in additional to capabilities. What are you implying?
 
>> +	close(ufd);
>> +	if (unshare(CLONE_NEWNET)) {
>> +		pr_perror("Unable to create a new netns");
>> +		exit(3);
>> +	}
>> +	if (prepare_net_ns(ns->id))
>> +		exit(4);
>> +	if (open_net_ns(ns, rsti(root_item)))
>> +		exit(5);
>> +	exit(0);
>> +}
>> +
>>  int prepare_net_namespaces()
>>  {
>> +	char stack[128] __stack_aligned__;
>>  	struct ns_id *nsid;
>> +	int status;
>> +	pid_t pid;
>>  
>>  	if (!(root_ns_mask & CLONE_NEWNET))
>>  		return 0;
>> @@ -1732,6 +1762,19 @@ int prepare_net_namespaces()
>>  		if (nsid->nd != &net_ns_desc)
>>  			continue;
>>  
>> +		if (root_user_ns && nsid->user_ns != root_user_ns) {
>> +			pid = clone(create_net_ns, stack + 128, CLONE_NEWNET | SIGCHLD, nsid);
>> +			if (pid < 0) {
>> +				pr_perror("Can't clone");
>> +				goto err;
>> +			}
>> +			if (waitpid(pid, &status, 0) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
>> +				pr_perror("Child process waiting %d", status);
>> +				goto err;
>> +			}
>> +			continue;
>> +		}
>> +
>>  		if (unshare(CLONE_NEWNET)) {
>>  			pr_perror("Unable to create a new netns");
>>  			goto err;
>>
>> _______________________________________________
>> CRIU mailing list
>> CRIU@openvz.org
>> https://lists.openvz.org/mailman/listinfo/criu