diff --git a/Makefile b/Makefile index 90b3dd954..f563bac7e 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,7 @@ LIBC_TOP_HALF_MUSL_SOURCES = \ misc/realpath.c \ misc/syslog.c \ mman/shm_open.c \ + mman/memfd_create.c \ errno/strerror.c \ \ network/services.c \ diff --git a/Makefile-eh b/Makefile-eh index a782c86bf..db48f36b2 100644 --- a/Makefile-eh +++ b/Makefile-eh @@ -117,6 +117,7 @@ LIBC_TOP_HALF_MUSL_SOURCES = \ misc/realpath.c \ misc/syslog.c \ mman/shm_open.c \ + mman/memfd_create.c \ errno/strerror.c \ \ network/services.c \ diff --git a/expected/wasm32-wasi-eh/defined-symbols.txt b/expected/wasm32-wasi-eh/defined-symbols.txt index 51b29a402..885ca8eb6 100644 --- a/expected/wasm32-wasi-eh/defined-symbols.txt +++ b/expected/wasm32-wasi-eh/defined-symbols.txt @@ -1203,6 +1203,7 @@ memccpy memchr memcmp memcpy +memfd_create memmem memmove mempcpy diff --git a/expected/wasm32-wasi-ehpic/defined-symbols.txt b/expected/wasm32-wasi-ehpic/defined-symbols.txt index 3885a6652..0ecadc1cd 100644 --- a/expected/wasm32-wasi-ehpic/defined-symbols.txt +++ b/expected/wasm32-wasi-ehpic/defined-symbols.txt @@ -1211,6 +1211,7 @@ memccpy memchr memcmp memcpy +memfd_create memmem memmove mempcpy diff --git a/expected/wasm32-wasi-threads/defined-symbols.txt b/expected/wasm32-wasi-threads/defined-symbols.txt index c8996ef3b..e42ac12b7 100644 --- a/expected/wasm32-wasi-threads/defined-symbols.txt +++ b/expected/wasm32-wasi-threads/defined-symbols.txt @@ -1133,6 +1133,7 @@ memccpy memchr memcmp memcpy +memfd_create memmem memmove mempcpy diff --git a/expected/wasm32-wasi/defined-symbols.txt b/expected/wasm32-wasi/defined-symbols.txt index 6d33bff74..f34d6fb8a 100644 --- a/expected/wasm32-wasi/defined-symbols.txt +++ b/expected/wasm32-wasi/defined-symbols.txt @@ -1209,6 +1209,7 @@ memccpy memchr memcmp memcpy +memfd_create memmem memmove mempcpy diff --git a/expected/wasm64-wasi/defined-symbols.txt b/expected/wasm64-wasi/defined-symbols.txt index cd3d45b83..9fa4c60cb 100644 --- a/expected/wasm64-wasi/defined-symbols.txt +++ b/expected/wasm64-wasi/defined-symbols.txt @@ -1167,6 +1167,7 @@ memccpy memchr memcmp memcpy +memfd_create memmem memmove mempcpy diff --git a/libc-top-half/musl/src/mman/memfd_create.c b/libc-top-half/musl/src/mman/memfd_create.c new file mode 100644 index 000000000..98c2a8ab3 --- /dev/null +++ b/libc-top-half/musl/src/mman/memfd_create.c @@ -0,0 +1,93 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#define MEMFD_NAME_MAX 249 + +static int create_unlinked_temp(char *template_path, unsigned int flags) { + int fd; + if (flags & MFD_CLOEXEC) { + fd = mkostemp(template_path, O_CLOEXEC); + } else { + fd = mkstemp(template_path); + } + if (fd < 0) + return -1; + + if (unlink(template_path) != 0) { + int saved_errno = errno; + close(fd); + errno = saved_errno; + return -1; + } + + return fd; +} + +// Returns the number of characters copied, excluding any null terminator. +// If the returned length == dst_len, src contained at least dst_len +// non-null characters and dst is not null-terminated (no room for a terminator). +static int sanitize_name(char *dst, size_t dst_len, const char *src) { + size_t i = 0; + + while (i < dst_len && src[i] != '\0') { + unsigned char c = (unsigned char)src[i]; + if (isalnum(c) || c == '_' || c == '-' || c == '.') { + dst[i] = (char)c; + } else { + dst[i] = '_'; + } + i++; + } + + return i; +} + +int memfd_create(const char *name, unsigned int flags) { + if (flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB)) { + errno = EINVAL; + return -1; + } + + if (flags & (MFD_HUGETLB | MFD_ALLOW_SEALING)) { + /* Seals are not currently supported by the WASIX fcntl subset. */ + /* hugetlbfs is not currently supported by the WASIX filesystem subset. */ + errno = ENOTSUP; + return -1; + } + + if (name == NULL) { + errno = EFAULT; + return -1; + } + + // Construct a string like "/tmp/.memfd--XXXXXX" + char tmp_template[sizeof("/tmp/.memfd-") - 1 + MEMFD_NAME_MAX + + sizeof("-XXXXXX") - 1 + 1]; + memcpy(tmp_template, "/tmp/.memfd-", sizeof("/tmp/.memfd-") - 1); + int name_len = sanitize_name(tmp_template + sizeof("/tmp/.memfd-") - 1, + MEMFD_NAME_MAX + 1, name); + if (name_len > MEMFD_NAME_MAX) { + errno = EINVAL; + return -1; + } + memcpy(tmp_template + sizeof("/tmp/.memfd-") - 1 + name_len, "-XXXXXX", + sizeof("-XXXXXX")); + + int fd = create_unlinked_temp(tmp_template, flags); + if (fd >= 0) + return fd; + + // If that failed, try ".memfd--XXXXXX" in the current working + // directory. Restore the -XXXXXX placeholder because it got overwritten by + // the previous call to mkstemp. + memcpy(tmp_template + sizeof("/tmp/.memfd-") - 1 + name_len, "-XXXXXX", + sizeof("-XXXXXX")); + return create_unlinked_temp(tmp_template + sizeof("/tmp/") - 1, flags); +}