Add qemu_memfd_alloc/free() helpers. The function helps to allocate and seal a memfd, and implements an open/unlink/mmap fallback for system that do not support memfd.
Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- include/qemu/osdep.h | 5 +++++ util/oslib-posix.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index adc138b..c49145f 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -167,6 +167,11 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *align); void qemu_vfree(void *ptr); void qemu_anon_ram_free(void *ptr, size_t size); +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, + int *fd); +void qemu_memfd_free(void *ptr, size_t size, int fd); + + #define QEMU_MADV_INVALID -1 #if defined(CONFIG_MADVISE) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 3ae4987..6e5a143 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -482,3 +482,65 @@ int qemu_read_password(char *buf, int buf_size) printf("\n"); return ret; } + +void *qemu_memfd_alloc(const char *name, size_t size, unsigned int seals, + int *fd) +{ + void *ptr; + int mfd; + + mfd = memfd_create(name, MFD_ALLOW_SEALING|MFD_CLOEXEC); + if (mfd != -1) { + if (ftruncate(mfd, size) == -1) { + perror("ftruncate"); + close(mfd); + return NULL; + } + + if (fcntl(mfd, F_ADD_SEALS, seals) == -1) { + perror("fcntl"); + close(mfd); + return NULL; + } + } else { + const char *tmpdir = getenv("TMPDIR"); + gchar *fname; + + tmpdir = tmpdir ? tmpdir : "/tmp"; + + fname = g_strdup_printf("%s/memfd-XXXXXX", tmpdir); + mfd = mkstemp(fname); + unlink(fname); + g_free(fname); + + if (mfd == -1) { + perror("mkstemp"); + return NULL; + } + + if (ftruncate(mfd, size) == -1) { + perror("ftruncate"); + close(mfd); + return NULL; + } + } + + ptr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0); + if (ptr == MAP_FAILED) { + perror("mmap"); + close(mfd); + return NULL; + } + + *fd = mfd; + return ptr; +} + +void qemu_memfd_free(void *ptr, size_t size, int fd) +{ + if (ptr) { + munmap(ptr, size); + } + + close(fd); +} -- 2.4.3