[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