Re: [PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
Bump. ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
Hi all, Any news about this? Thanks, --- Simon Ser https://emersion.fr On Wednesday, August 15, 2018 4:14 PM, Simon Ser wrote: > On Linux, try using memfd_create and file sealing. Fallback to > shm_open on old kernels. > > On FreeBSD, use shm_open with SHM_ANON. > > Otherwise, use shm_open with a random name, making sure the name > isn't already taken. > > Signed-off-by: Simon Ser cont...@emersion.fr > > Makefile.am | 2 +- > configure.ac | 4 +- > cursor/os-compatibility.c | 172 ++ > 3 files changed, 86 insertions(+), 92 deletions(-) > > diff --git a/Makefile.am b/Makefile.am > index 697c517..c612672 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -136,7 +136,7 @@ libwayland_cursor_la_SOURCES = \ > cursor/cursor-data.h \ > cursor/xcursor.c \ > cursor/xcursor.h > -libwayland_cursor_la_LIBADD = libwayland-client.la > +libwayland_cursor_la_LIBADD = libwayland-client.la -lrt > > pkgconfig_DATA += cursor/wayland-cursor.pc > > diff --git a/configure.ac b/configure.ac > index 9419ae3..d59c61d 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -62,8 +62,8 @@ if test "x$GCC" = "xyes"; then > fi > AC_SUBST(GCC_CFLAGS) > > -AC_CHECK_HEADERS([sys/prctl.h]) > -AC_CHECK_FUNCS([accept4 mkostemp posix_fallocate prctl]) > +AC_CHECK_HEADERS([sys/prctl.h linux/memfd.h]) > +AC_CHECK_FUNCS([accept4 prctl]) > > AC_ARG_ENABLE([libraries], > [AC_HELP_STRING([--disable-libraries], > diff --git a/cursor/os-compatibility.c b/cursor/os-compatibility.c > index e972d21..96649e3 100644 > --- a/cursor/os-compatibility.c > +++ b/cursor/os-compatibility.c > @@ -25,124 +25,118 @@ > > #define _GNU_SOURCE > > -#include > -#include > -#include > #include > -#include > +#include > #include > +#include > +#include > +#include > +#include > +#include > +#include > > - > > +#ifdef HAVE_LINUX_MEMFD_H > +#include > +#endif > > #include "config.h" > #include "os-compatibility.h" > > -#ifndef HAVE_MKOSTEMP > +static void > +randname(char *buf) { > > - struct timespec ts; > > - long r; > > - int i; > > - > - clock_gettime(CLOCK_REALTIME, ); > > - r = ts.tv_nsec; > > - for (i = 0; i < 6; ++i) { > > - buf[i] = 'A'+(r&15)+(r&16)*2; > > > - r >>= 5; > > > - } > +} > > - > > static int > -set_cloexec_or_close(int fd) > +anonymous_shm_open(off_t size) > { > > - long flags; > - > - if (fd == -1) > - return -1; > > > > - char name[] = "/wayland-cursor-XX"; > - int fd, retries = 100; > > - flags = fcntl(fd, F_GETFD); > - if (flags == -1) > - goto err; > > > > - do { > - randname(name + strlen(name) - 6); > > > > - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) > - goto err; > > > > - --retries; > > > - fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600); > > > - if (fd >= 0) { > > > - shm_unlink(name); > > > - return fd; > > > - } > > > - } while (retries > 0 && errno == EEXIST); > > > - return fd; > - > > -err: > > - close(fd); > return -1; > } > > > - > > +static int > +seal_or_close(int fd) { > +#if defined(F_ADD_SEALS) && defined(F_SEAL_SHRINK) > > - if (fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK) == -1) { > - close(fd); > > > - return -1; > > > - } > #endif > > - return 0; > +} > > - > > static int > -create_tmpfile_cloexec(char *tmpname) > +create_anonymous_file(off_t size) > { > > - int fd; > > - int fd, flags; > > -#ifdef HAVE_MKOSTEMP > > > - fd = mkostemp(tmpname, O_CLOEXEC); > > - if (fd >= 0) > > - unlink(tmpname); > > > > -#else > > - fd = mkstemp(tmpname); > +#if defined(__NR_memfd_create) && defined(MFD_CLOEXEC) > > > - flags = MFD_CLOEXEC; > +#if defined(MFD_ALLOW_SEALING) > > - flags |= MFD_ALLOW_SEALING; > +#endif > > - fd = syscall(__NR_memfd_create, "wayland-cursor", flags); > if (fd >= 0) { > > > - fd = set_cloexec_or_close(fd); > > > - unlink(tmpname); > > > - } > > - if (ftruncate(fd, size) < 0) { > > > - close(fd); > > > - return -1; > > > - } > > > - > > +#if defined(MFD_ALLOW_SEALING) > > - if (seal_or_close(fd) != 0) > > > - return -1; > > > > #endif > > - return fd; > > > - } else if (errno != ENOSYS) > - return fd; > > > > +#endif > + > +#if defined(FreeBSD) > > - fd = shm_open(SHM_ANON, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600); > +#else > > - fd = anonymous_shm_open(size); > +#endif > > - > - if (ftruncate(fd, size) < 0) { > - close(fd); > > > - return -1; > > > - } > - return fd; > } > > -/* > > > - - Create a new, unique, anonymous file of the given size, and > - - return the file descriptor for it. The file descriptor is set > - - CLOEXEC. The file is immediately suitable for mmap()'ing > - - the given size at offset zero. > - - > - - The file should not have a permanent
Re: [PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
On Thursday 2018-08-16 12:41, Emil Velikov wrote: >On 15 August 2018 at 15:14, Simon Ser wrote: >> On Linux, try using memfd_create and file sealing. Fallback to >> shm_open on old kernels. >> >> On FreeBSD, use shm_open with SHM_ANON. >> >> Otherwise, use shm_open with a random name, making sure the name >> isn't already taken. >> >Thinking out loud: > >I wonder if the next POSIX standard will finally standardise >random/anonymous shm files. Be that shm_open+SHM_ANON [...] According to the shm_open.3 from Linux man-pages-4.16 project, shm_open is already marked standardized: CONFORMING TO POSIX.1-2001, POSIX.1-2008. ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
On August 16, 2018 11:57 AM, Jan Engelhardt wrote: > On Thursday 2018-08-16 12:41, Emil Velikov wrote: > > > On 15 August 2018 at 15:14, Simon Ser cont...@emersion.fr wrote: > > > > > On Linux, try using memfd_create and file sealing. Fallback to > > > shm_open on old kernels. > > > On FreeBSD, use shm_open with SHM_ANON. > > > Otherwise, use shm_open with a random name, making sure the name > > > isn't already taken. > > > > Thinking out loud: > > I wonder if the next POSIX standard will finally standardise > > random/anonymous shm files. Be that shm_open+SHM_ANON [...] > > According to the shm_open.3 from Linux man-pages-4.16 project, > shm_open is already marked standardized: > > CONFORMING TO > POSIX.1-2001, POSIX.1-2008. Yes, but this doesn't include SHM_ANON unfortunately. So we still need to generate a random name and make sure it hasn't been taken already. ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
Re: [PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
On 15 August 2018 at 15:14, Simon Ser wrote: > On Linux, try using memfd_create and file sealing. Fallback to > shm_open on old kernels. > > On FreeBSD, use shm_open with SHM_ANON. > > Otherwise, use shm_open with a random name, making sure the name > isn't already taken. > Thinking out loud: I wonder if the next POSIX standard will finally standardise random/anonymous shm files. Be that shm_open+SHM_ANON (FreeBSD), shm_mk*temp (OpenBSD) or any other solution. -Emil ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] cursor: use memfd_create or shm_open for anonymous in-memory files
On Linux, try using memfd_create and file sealing. Fallback to shm_open on old kernels. On FreeBSD, use shm_open with SHM_ANON. Otherwise, use shm_open with a random name, making sure the name isn't already taken. Signed-off-by: Simon Ser --- Makefile.am | 2 +- configure.ac | 4 +- cursor/os-compatibility.c | 172 ++ 3 files changed, 86 insertions(+), 92 deletions(-) diff --git a/Makefile.am b/Makefile.am index 697c517..c612672 100644 --- a/Makefile.am +++ b/Makefile.am @@ -136,7 +136,7 @@ libwayland_cursor_la_SOURCES = \ cursor/cursor-data.h\ cursor/xcursor.c\ cursor/xcursor.h -libwayland_cursor_la_LIBADD = libwayland-client.la +libwayland_cursor_la_LIBADD = libwayland-client.la -lrt pkgconfig_DATA += cursor/wayland-cursor.pc diff --git a/configure.ac b/configure.ac index 9419ae3..d59c61d 100644 --- a/configure.ac +++ b/configure.ac @@ -62,8 +62,8 @@ if test "x$GCC" = "xyes"; then fi AC_SUBST(GCC_CFLAGS) -AC_CHECK_HEADERS([sys/prctl.h]) -AC_CHECK_FUNCS([accept4 mkostemp posix_fallocate prctl]) +AC_CHECK_HEADERS([sys/prctl.h linux/memfd.h]) +AC_CHECK_FUNCS([accept4 prctl]) AC_ARG_ENABLE([libraries], [AC_HELP_STRING([--disable-libraries], diff --git a/cursor/os-compatibility.c b/cursor/os-compatibility.c index e972d21..96649e3 100644 --- a/cursor/os-compatibility.c +++ b/cursor/os-compatibility.c @@ -25,124 +25,118 @@ #define _GNU_SOURCE -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LINUX_MEMFD_H +#include +#endif #include "config.h" #include "os-compatibility.h" -#ifndef HAVE_MKOSTEMP +static void +randname(char *buf) { + struct timespec ts; + long r; + int i; + + clock_gettime(CLOCK_REALTIME, ); + r = ts.tv_nsec; + for (i = 0; i < 6; ++i) { + buf[i] = 'A'+(r&15)+(r&16)*2; + r >>= 5; + } +} + static int -set_cloexec_or_close(int fd) +anonymous_shm_open(off_t size) { - long flags; - - if (fd == -1) - return -1; + char name[] = "/wayland-cursor-XX"; + int fd, retries = 100; - flags = fcntl(fd, F_GETFD); - if (flags == -1) - goto err; + do { + randname(name + strlen(name) - 6); - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; + --retries; + fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0600); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); - return fd; - -err: - close(fd); return -1; } + +static int +seal_or_close(int fd) { +#if defined(F_ADD_SEALS) && defined(F_SEAL_SHRINK) + if (fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK) == -1) { + close(fd); + return -1; + } #endif + return 0; +} + static int -create_tmpfile_cloexec(char *tmpname) +create_anonymous_file(off_t size) { - int fd; + int fd, flags; -#ifdef HAVE_MKOSTEMP - fd = mkostemp(tmpname, O_CLOEXEC); - if (fd >= 0) - unlink(tmpname); -#else - fd = mkstemp(tmpname); +#if defined(__NR_memfd_create) && defined(MFD_CLOEXEC) + flags = MFD_CLOEXEC; +#if defined(MFD_ALLOW_SEALING) + flags |= MFD_ALLOW_SEALING; +#endif + fd = syscall(__NR_memfd_create, "wayland-cursor", flags); if (fd >= 0) { - fd = set_cloexec_or_close(fd); - unlink(tmpname); - } + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + +#if defined(MFD_ALLOW_SEALING) + if (seal_or_close(fd) != 0) + return -1; #endif + return fd; + } else if (errno != ENOSYS) + return fd; +#endif + +#if defined(__FreeBSD__) + fd = shm_open(SHM_ANON, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600); +#else + fd = anonymous_shm_open(size); +#endif + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + return fd; } -/* - * Create a new, unique, anonymous file of the given size, and - * return the file descriptor for it. The file descriptor is set - * CLOEXEC. The file is immediately suitable for mmap()'ing - * the given size at offset zero. - * - * The file should not have a permanent backing store like a disk, - * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. - * - * The file name is deleted from the file system. - * - * The file is suitable for buffer sharing between processes by - * transmitting the file descriptor over Unix