[CRIU] [PATCH] remap: fix dead pid remap of /proc/<pid>

Pavel Emelyanov xemul at parallels.com
Wed Jan 13 05:05:28 PST 2016


On 01/06/2016 06:57 PM, Tycho Andersen wrote:
> It turns out we can't just test for /proc/<pid>, because the kernel appends
> (deleted), since the directory is actually deleted (vs. something like
> /proc/1/mountinfo, where the file still exists in the unlinked directory,
> so there is no (deleted)). See comment for details.
> 
> Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
> ---
>  files-reg.c                            | 34 +++++++++++++++++++++++++---------
>  test/zdtm/live/static/remap_dead_pid.c | 22 ++++++++++++++++++++--
>  2 files changed, 45 insertions(+), 11 deletions(-)
> 
> diff --git a/files-reg.c b/files-reg.c
> index 0f89be5..43872f0 100644
> --- a/files-reg.c
> +++ b/files-reg.c
> @@ -887,16 +887,32 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms,
>  			return -1;
>  		pid = strtol(start + 1, &end, 10);
>  
> -		/* if we didn't find another /, this path something
> -		 * like ./proc/kmsg, which we shouldn't mess with. */
> -		if (*end == '/') {
> -			*end = 0;
> -			ret = access(rpath, F_OK);
> -			*end = '/';
> -
> -			if (ret) {
> +		/* If strtol didn't convert anything, then we are looking at
> +		 * something like /proc/kmsg, which we shouldn't mess with.
> +		 * Anything under /proc/<pid> (including that directory itself)
> +		 * can be c/r'd with a dead pid remap, so let's allow all such
> +		 * cases.
> +		 */
> +		if (pid != 0) {
> +			bool is_dead = strip_deleted(link);
> +
> +			/* /proc/<pid> will be "/proc/1 (deleted)" when it is
> +			 * dead, but a path like /proc/1/mountinfo won't have
> +			 * the suffix, since it isn't actually deleted (still
> +			 * exists, but the parent dir is deleted). So, if we
> +			 * have a path like /proc/1/mountinfo, test if /proc/1
> +			 * exists instead, since this is what CRIU will need to
> +			 * open on restore.
> +			 */
> +			if (!is_dead) {

If the is_dead is 0 here we never go dumping the pid remap, which seems to
be breaking the behavior on /proc/pid/xxx files.

> +				*end = 0;
> +				ret = access(rpath, F_OK);

Shouldn't this be is_dead = access() instead?

> +				*end = '/';
> +			}
> +
> +			if (is_dead) {
>  				pr_info("Dumping dead process remap of %d\n", pid);
> -				return dump_dead_process_remap(pid, rpath + 1, plen - 1, ost, lfd, id, nsid);
> +				return dump_dead_process_remap(pid, rpath + 1, link->len - 1, ost, lfd, id, nsid);
>  			}
>  		}
>  
> diff --git a/test/zdtm/live/static/remap_dead_pid.c b/test/zdtm/live/static/remap_dead_pid.c
> index c16832d..a9d5d1a 100644
> --- a/test/zdtm/live/static/remap_dead_pid.c
> +++ b/test/zdtm/live/static/remap_dead_pid.c
> @@ -36,13 +36,23 @@ int main(int argc, char **argv)
>  		while(1)
>  			sleep(10);
>  	} else {
> -		int fd, ret;
> +		int fd, fd2, ret;
>  		char path[PATH_MAX];
>  		pid_t result;
>  
>  		sprintf(path, "/proc/%d/mountinfo", pid);
> -
>  		fd = open(path, O_RDONLY);
> +		if (fd < 0) {
> +			fail("failed to open fd");
> +			return -1;
> +		}
> +
> +		sprintf(path, "/proc/%d", pid);
> +		fd2 = open(path, O_RDONLY);
> +		if (fd2 < 0) {
> +			fail("failed to open fd2");
> +			return -1;
> +		}
>  
>  		/* no matter what, we should kill the child */
>  		kill(pid, SIGKILL);
> @@ -67,6 +77,14 @@ int main(int argc, char **argv)
>  			fail("bad fd after restore");
>  			return -1;
>  		}
> +
> +		ret = fcntl(fd2, F_GETFD);
> +		close(fd2);
> +
> +		if (ret) {
> +			fail("bad fd2 after restore");
> +			return -1;
> +		}
>  	}
>  
>  	pass();
> 



More information about the CRIU mailing list