Skip to content

CRIU can't dump memfd_secret fd containing process #2188

@warusadura

Description

@warusadura

dumpee src:

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>

static int memfd_secret(unsigned int flags)
{
	return syscall(SYS_memfd_secret, flags);
}

static void *secret_init(size_t size)
{
	int fd;
	void *secret_mem = NULL;

	fd = memfd_secret(0);
	if (fd < 0)
		return secret_mem;

	if (ftruncate(fd, size) < 0) {
		close(fd);
		return secret_mem;
	}

	secret_mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (secret_mem == MAP_FAILED) {
		close(fd);
		return secret_mem;
	}

	return secret_mem;
}

static void secret_fini(void *mem, size_t size)
{
	munmap(mem, size);
}

int main(int argc, char *argv[])
{
	const char secret_msg[] = "CRIU";
	size_t size = sizeof(secret_msg);
	void *secret_mem;

	fprintf(stdout, "ppid: %d\n", getppid());
    	fprintf(stdout, "pid: %d\n", getpid());

	secret_mem = secret_init(size);
	if (! secret_mem)
		perror("not supported operation");

	strncpy(secret_mem, secret_msg, size);
	fprintf(stdout, "%zu bytes of secret data stored successfully at %p\n",
			size, secret_mem);

	pause();

	secret_fini(secret_mem, size);
	fprintf(stdout, "secret data successfully discarded\n");

	return 0;
}

dumpee

./memfd_app 
ppid: 3883
pid: 3959
5 bytes of secret data stored successfully at 0x7fadc0ed2000

criu dump:
sudo ./criu/criu dump --shell-job -D dumpdir/ -v4 -t 3959

to reproduce this:
Please apply the following diff otherwise the dump will fail at: vma_get_mapfile

diff --git a/criu/include/image.h b/criu/include/image.h
index 9a275565f..fe1ab9761 100644
--- a/criu/include/image.h
+++ b/criu/include/image.h
@@ -84,6 +84,7 @@
 #define VMA_AREA_VVAR	 (1 << 12)
 #define VMA_AREA_AIORING (1 << 13)
 #define VMA_AREA_MEMFD	 (1 << 14)
+#define VMA_AREA_MEMFD_SECRET (1 << 15)
 
 #define VMA_EXT_PLUGIN	  (1 << 27)
 #define VMA_CLOSE	  (1 << 28)
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 61c1eee24..ad8c8f3e1 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -79,6 +79,12 @@ static char *buf = __buf.buf;
 
 #define AIO_FNAME "/[aio]"
 
+/*
+ * memfd_secret fd
+ */
+
+#define SECRETMEM_NAME "/secretmem (deleted)"
+
 /* check the @line starts with "%lx-%lx" format */
 static bool __is_vma_range_fmt(char *line)
 {
@@ -440,13 +446,17 @@ static int vma_get_mapfile(const char *fname, struct vma_area *vma, DIR *mfd, st
 
 	*vm_file_fd = openat(dirfd(mfd), path, flags);
 	if (*vm_file_fd < 0) {
-		if (errno == ENOENT)
+		if (errno == ENOENT) {
 			/* Just mapping w/o map_files link */
+			pr_debug("memfd_secret: ENOENT\n");
 			return 0;
+		}
 
 		if (errno == ENXIO) {
 			struct stat buf;
 
+			pr_debug("memfd_secret: ENXIO\n");
+
 			if (fstatat(dirfd(mfd), path, &buf, 0))
 				return -1;
 
@@ -464,6 +474,14 @@ static int vma_get_mapfile(const char *fname, struct vma_area *vma, DIR *mfd, st
 				return 0;
 			}
 
+			/* memfd_secret */
+			if (!strncmp(fname, SECRETMEM_NAME, sizeof(SECRETMEM_NAME))) {
+				pr_debug("memfd_secret: fd identified\n");
+				/* VmaEntry *e; include/vma.h:32 */
+				vma->e->status = VMA_AREA_MEMFD_SECRET;
+				return 0;
+			}
+
 			pr_err("Unknown shit %o (%s)\n", buf.st_mode, fname);
 			return -1;
 		}

Metadata

Metadata

Assignees

Labels

no-auto-closeDon't auto-close as a stale issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions