[v3,36/55] restore: Implement set_next_pid() helper

Submitted by Kirill Tkhai on April 10, 2017, 8:21 a.m.

Details

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

Commit Message

Kirill Tkhai April 10, 2017, 8:21 a.m.
Move next pid writing functionality to separate function.
Also make set_next_pid() skip INIT_PID, as I'm going to
call this function unconditionally in next patches.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-restore.c     |   40 ++++++++++++++++++++++++++++++++++------
 criu/include/pstree.h |    1 +
 2 files changed, 35 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index a99a9be3c..be119274c 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -282,6 +282,34 @@  static int root_prepare_shared(void)
 	return ret;
 }
 
+int __set_next_pid(pid_t pid)
+{
+	char buf[32];
+	int len, fd;
+
+	fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
+	if (fd < 0)
+		return -1;
+
+	len = snprintf(buf, sizeof(buf), "%d", pid - 1);
+	len -= write(fd, buf, len);
+	close(fd);
+
+	if (len) {
+		pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int set_next_pid(struct ns_id *ns, struct pid *pid)
+{
+	if (pid->ns[0].virt == INIT_PID)
+		return 0;
+	return __set_next_pid(pid->ns[0].virt);
+}
+
 static rt_sigaction_t sigchld_act;
 /*
  * If parent's sigaction has blocked SIGKILL (which is non-sence),
@@ -977,12 +1005,16 @@  static inline int fork_with_pid(struct pstree_item *item)
 	struct cr_clone_arg ca;
 	int ret = -1;
 	pid_t pid = vpid(item);
+	struct ns_id *pid_ns;
 
 	if (item != root_item)
 		item->user_ns = current->user_ns;
 	else
 		item->user_ns = root_user_ns;
 
+	pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc);
+	BUG_ON(!pid_ns);
+
 	if (item->pid->state != TASK_HELPER) {
 		if (open_core(pid, &ca.core))
 			return -1;
@@ -1021,9 +1053,6 @@  static inline int fork_with_pid(struct pstree_item *item)
 	pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags);
 
 	if (!(ca.clone_flags & CLONE_NEWPID)) {
-		char buf[32];
-		int len;
-
 		ca.fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
 		if (ca.fd < 0)
 			goto err;
@@ -1034,9 +1063,8 @@  static inline int fork_with_pid(struct pstree_item *item)
 			goto err;
 		}
 
-		len = snprintf(buf, sizeof(buf), "%d", pid - 1);
-		if (write(ca.fd, buf, len) != len) {
-			pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
+		if (set_next_pid(pid_ns, item->pid) < 0) {
+			pr_err("Can't set next pid\n");
 			goto err_unlock;
 		}
 	} else {
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index b8b8dd3f5..05e5b1e8f 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -137,4 +137,5 @@  extern void pstree_free_cores(struct pstree_item *item);
 extern int collect_pstree_ids(void);
 
 extern int preorder_pstree_traversal(struct pstree_item *item, int (*f)(struct pstree_item *));
+extern int __set_next_pid(pid_t pid);
 #endif /* __CR_PSTREE_H__ */

Comments

Andrey Vagin April 25, 2017, 5:40 a.m.
On Mon, Apr 10, 2017 at 11:21:00AM +0300, Kirill Tkhai wrote:
> Move next pid writing functionality to separate function.
> Also make set_next_pid() skip INIT_PID, as I'm going to
> call this function unconditionally in next patches.
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  criu/cr-restore.c     |   40 ++++++++++++++++++++++++++++++++++------
>  criu/include/pstree.h |    1 +
>  2 files changed, 35 insertions(+), 6 deletions(-)
> 
> diff --git a/criu/cr-restore.c b/criu/cr-restore.c
> index a99a9be3c..be119274c 100644
> --- a/criu/cr-restore.c
> +++ b/criu/cr-restore.c
> @@ -282,6 +282,34 @@ static int root_prepare_shared(void)
>  	return ret;
>  }
>  
> +int __set_next_pid(pid_t pid)
> +{
> +	char buf[32];
> +	int len, fd;
> +
> +	fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
> +	if (fd < 0)
> +		return -1;
> +
> +	len = snprintf(buf, sizeof(buf), "%d", pid - 1);
> +	len -= write(fd, buf, len);
> +	close(fd);

close() can over-write errno
> +
> +	if (len) {
> +		pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static int set_next_pid(struct ns_id *ns, struct pid *pid)
> +{
> +	if (pid->ns[0].virt == INIT_PID)
> +		return 0;
> +	return __set_next_pid(pid->ns[0].virt);
> +}
> +
>  static rt_sigaction_t sigchld_act;
>  /*
>   * If parent's sigaction has blocked SIGKILL (which is non-sence),
> @@ -977,12 +1005,16 @@ static inline int fork_with_pid(struct pstree_item *item)
>  	struct cr_clone_arg ca;
>  	int ret = -1;
>  	pid_t pid = vpid(item);
> +	struct ns_id *pid_ns;
>  
>  	if (item != root_item)
>  		item->user_ns = current->user_ns;
>  	else
>  		item->user_ns = root_user_ns;
>  
> +	pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc);
> +	BUG_ON(!pid_ns);
> +
>  	if (item->pid->state != TASK_HELPER) {
>  		if (open_core(pid, &ca.core))
>  			return -1;
> @@ -1021,9 +1053,6 @@ static inline int fork_with_pid(struct pstree_item *item)
>  	pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags);
>  
>  	if (!(ca.clone_flags & CLONE_NEWPID)) {
> -		char buf[32];
> -		int len;
> -
>  		ca.fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
>  		if (ca.fd < 0)
>  			goto err;
> @@ -1034,9 +1063,8 @@ static inline int fork_with_pid(struct pstree_item *item)
>  			goto err;
>  		}
>  
> -		len = snprintf(buf, sizeof(buf), "%d", pid - 1);
> -		if (write(ca.fd, buf, len) != len) {
> -			pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
> +		if (set_next_pid(pid_ns, item->pid) < 0) {
> +			pr_err("Can't set next pid\n");
>  			goto err_unlock;
>  		}
>  	} else {
> diff --git a/criu/include/pstree.h b/criu/include/pstree.h
> index b8b8dd3f5..05e5b1e8f 100644
> --- a/criu/include/pstree.h
> +++ b/criu/include/pstree.h
> @@ -137,4 +137,5 @@ extern void pstree_free_cores(struct pstree_item *item);
>  extern int collect_pstree_ids(void);
>  
>  extern int preorder_pstree_traversal(struct pstree_item *item, int (*f)(struct pstree_item *));
> +extern int __set_next_pid(pid_t pid);
>  #endif /* __CR_PSTREE_H__ */
>
Kirill Tkhai April 25, 2017, 9:29 a.m.
On 25.04.2017 08:40, Andrei Vagin wrote:
> On Mon, Apr 10, 2017 at 11:21:00AM +0300, Kirill Tkhai wrote:
>> Move next pid writing functionality to separate function.
>> Also make set_next_pid() skip INIT_PID, as I'm going to
>> call this function unconditionally in next patches.
>>
>> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
>> ---
>>  criu/cr-restore.c     |   40 ++++++++++++++++++++++++++++++++++------
>>  criu/include/pstree.h |    1 +
>>  2 files changed, 35 insertions(+), 6 deletions(-)
>>
>> diff --git a/criu/cr-restore.c b/criu/cr-restore.c
>> index a99a9be3c..be119274c 100644
>> --- a/criu/cr-restore.c
>> +++ b/criu/cr-restore.c
>> @@ -282,6 +282,34 @@ static int root_prepare_shared(void)
>>  	return ret;
>>  }
>>  
>> +int __set_next_pid(pid_t pid)
>> +{
>> +	char buf[32];
>> +	int len, fd;
>> +
>> +	fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
>> +	if (fd < 0)
>> +		return -1;
>> +
>> +	len = snprintf(buf, sizeof(buf), "%d", pid - 1);
>> +	len -= write(fd, buf, len);
>> +	close(fd);
> 
> close() can over-write errno

Sure, thanks

>> +
>> +	if (len) {
>> +		pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
>> +		return -1;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int set_next_pid(struct ns_id *ns, struct pid *pid)
>> +{
>> +	if (pid->ns[0].virt == INIT_PID)
>> +		return 0;
>> +	return __set_next_pid(pid->ns[0].virt);
>> +}
>> +
>>  static rt_sigaction_t sigchld_act;
>>  /*
>>   * If parent's sigaction has blocked SIGKILL (which is non-sence),
>> @@ -977,12 +1005,16 @@ static inline int fork_with_pid(struct pstree_item *item)
>>  	struct cr_clone_arg ca;
>>  	int ret = -1;
>>  	pid_t pid = vpid(item);
>> +	struct ns_id *pid_ns;
>>  
>>  	if (item != root_item)
>>  		item->user_ns = current->user_ns;
>>  	else
>>  		item->user_ns = root_user_ns;
>>  
>> +	pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc);
>> +	BUG_ON(!pid_ns);
>> +
>>  	if (item->pid->state != TASK_HELPER) {
>>  		if (open_core(pid, &ca.core))
>>  			return -1;
>> @@ -1021,9 +1053,6 @@ static inline int fork_with_pid(struct pstree_item *item)
>>  	pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags);
>>  
>>  	if (!(ca.clone_flags & CLONE_NEWPID)) {
>> -		char buf[32];
>> -		int len;
>> -
>>  		ca.fd = open_proc_rw(PROC_GEN, LAST_PID_PATH);
>>  		if (ca.fd < 0)
>>  			goto err;
>> @@ -1034,9 +1063,8 @@ static inline int fork_with_pid(struct pstree_item *item)
>>  			goto err;
>>  		}
>>  
>> -		len = snprintf(buf, sizeof(buf), "%d", pid - 1);
>> -		if (write(ca.fd, buf, len) != len) {
>> -			pr_perror("%d: Write %s to %s", pid, buf, LAST_PID_PATH);
>> +		if (set_next_pid(pid_ns, item->pid) < 0) {
>> +			pr_err("Can't set next pid\n");
>>  			goto err_unlock;
>>  		}
>>  	} else {
>> diff --git a/criu/include/pstree.h b/criu/include/pstree.h
>> index b8b8dd3f5..05e5b1e8f 100644
>> --- a/criu/include/pstree.h
>> +++ b/criu/include/pstree.h
>> @@ -137,4 +137,5 @@ extern void pstree_free_cores(struct pstree_item *item);
>>  extern int collect_pstree_ids(void);
>>  
>>  extern int preorder_pstree_traversal(struct pstree_item *item, int (*f)(struct pstree_item *));
>> +extern int __set_next_pid(pid_t pid);
>>  #endif /* __CR_PSTREE_H__ */
>>