[CRIU] [PATCH 3/3] shmem: use memfd_create() to restore shared memory reqions

Pavel Emelyanov xemul at parallels.com
Fri Oct 10 11:40:01 PDT 2014


On 10/10/2014 08:39 PM, Andrey Vagin wrote:
> /proc/PID/map_files are protected by the global CAP_SYS_ADMIN, so we
> need to avoid using them to support user namespaces.
> 
> We are going to use memfd_create() to get the first file descriptor and
> then all others processes will able to open it via /proc/PID/fd/X.
> 
> In this patch memfd_create() is used to get a file descriptor, which is
> associated with a shared memory region.
> 
> If memfd_create() isn't supported, the old scheme will be used.
> 
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  shmem.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 41 insertions(+), 10 deletions(-)
> 
> diff --git a/shmem.c b/shmem.c
> index bfe2743..abf2634 100644
> --- a/shmem.c
> +++ b/shmem.c
> @@ -7,6 +7,7 @@
>  #include "shmem.h"
>  #include "image.h"
>  #include "cr_options.h"
> +#include "kerndat.h"
>  #include "page-pipe.h"
>  #include "page-xfer.h"
>  #include "rst-malloc.h"
> @@ -175,8 +176,9 @@ err_unmap:
>  int get_shmem_fd(int pid, VmaEntry *vi)
>  {
>  	struct shmem_info *si;
> -	void *addr;
> -	int f;
> +	void *addr = MAP_FAILED;
> +	int f = -1;
> +	int flags;
>  
>  	si = find_shmem_by_id(vi->shmid);
>  	pr_info("Search for 0x%016"PRIx64" shmem 0x%"PRIx64" %p/%d\n", vi->start, vi->shmid, si, si ? si->pid : -1);
> @@ -191,6 +193,28 @@ int get_shmem_fd(int pid, VmaEntry *vi)
>  	if (si->fd != -1)
>  		return dup(si->fd);
>  
> +	if (kerndat_has_memfd_create()) {
> +		char name[PATH_MAX];

PATH_MAX?

> +
> +		snprintf(name, sizeof(name), "%d-%lx", pid, vi->shmid);
> +		f = sys_memfd_create(name, 0);
> +		if (f < 0) {
> +			pr_perror("Unable to create memfd");
> +			goto err;
> +		}
> +
> +		if (ftruncate(f, si->size)) {
> +			pr_perror("Unable to truncate memfd");
> +			goto err;
> +		}
> +	}
> +
> +	flags = MAP_SHARED;
> +	if (f == -1)
> +		flags |= MAP_ANONYMOUS;
> +	else
> +		flags |= MAP_FILE;

The flags should better be set up in the if () above.

> +
>  	/*
>  	 * The following hack solves problems:
>  	 * vi->pgoff may be not zero in a target process.
> @@ -198,23 +222,25 @@ int get_shmem_fd(int pid, VmaEntry *vi)
>  	 * The restorer doesn't have snprintf.
>  	 * Here is a good place to restore content
>  	 */
> -	addr = mmap(NULL, si->size,
> -			PROT_WRITE | PROT_READ,
> -			MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> +	addr = mmap(NULL, si->size, PROT_WRITE | PROT_READ, flags, f, 0);
>  	if (addr == MAP_FAILED) {
>  		pr_err("Can't mmap shmid=0x%"PRIx64" size=%ld\n",
>  				vi->shmid, si->size);
> -		return -1;
> +		goto err;
>  	}
>  
>  	if (restore_shmem_content(addr, si) < 0) {
>  		pr_err("Can't restore shmem content\n");
> -		return -1;
> +		goto err;
>  	}
>  
> -	f = open_proc_rw(getpid(), "map_files/%lx-%lx",
> -			(unsigned long) addr,
> -			(unsigned long) addr + si->size);
> +	if (f == -1) {
> +		f = open_proc_rw(getpid(), "map_files/%lx-%lx",
> +				(unsigned long) addr,
> +				(unsigned long) addr + si->size);
> +		if (f < 0)
> +			goto err;
> +	}
>  	munmap(addr, si->size);
>  
>  	si->fd = f;
> @@ -228,6 +254,11 @@ int get_shmem_fd(int pid, VmaEntry *vi)
>  	futex_wait_until(&si->lock, si->count - si->self_count + 1);
>  
>  	return f;
> +err:
> +	if (addr != MAP_FAILED)
> +		munmap(addr, si->size);
> +	close_safe(&f);
> +	return -1;
>  }
>  
>  struct shmem_info_dump {
> 



More information about the CRIU mailing list