This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] Linux: Add memfd_create system call wrapper
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: libc-alpha at sourceware dot org
- Date: Wed, 8 Nov 2017 18:24:36 -0200
- Subject: Re: [PATCH] Linux: Add memfd_create system call wrapper
- Authentication-results: sourceware.org; auth=none
- References: <20171103232445.B2FB241C85DF3@oldenburg.str.redhat.com>
On 03/11/2017 21:24, Florian Weimer wrote:
> The system call is somewhat obscure because it is closely related
> to file descriptor sealing. However, it is also the recommended
> way to create alias mappings, which is why it has more general use.
>
> No emulation is provided. Except for the name of the
> /proc/self/fd links, it would be possible to implement an
> approximation using O_TMPFILE and tmpfs, but this does not appear
> to be worth the added complexity.
I agree an emulation is not worth the trouble.
>
> 2017-11-03 Florian Weimer <fweimer@redhat.com>
>
> Linux: Add memfd_create system call wrapper
> * sysdeps/unix/sysv/linux/Makefile [misc] (sysdep_headers): Add
> sys/memfd.h.
> (tests): Add tst-memfd_create.
> * sysdeps/unix/sysv/linux/Versions (GLIBC_2.27): Add memfd_create.
> * sysdeps/unix/sysv/linux/syscalls.list (memfd_create): Add.
> * sysdeps/unix/sysv/linux/sys/memfd.h: New file.
> * sysdeps/unix/sysv/linux/**.abilist: Update.
> * manual/llio.texi (Memory-mapped I/O): Document memfd_create.
> * support/Makefile (libsupport-routines): Add xreadlink, xstrndup,
> xunlink.
> (tests): Add tst-xreadlink.
> * support/support.h (xstrndup): Declare.
> * support/xunistd.h (xunlink, xreadlink): Declare.
> * support/temp_file.h (support_create_temp_directory): Declare.
> * support/temp_file.c (support_create_temp_directory): New function.
> * support/support_chroot.c (support_chroot_create): Use it.
> * support/xreadlink.c: New file.
> * support/xstrndup.c: Likewise.
> * support/xunlink.c: Likewise.
> * support/tst-xreadlink.c: Likewise.
>
Missing sysdeps/unix/sysv/linux/tst-memfd_create.c entry.
> diff --git a/manual/llio.texi b/manual/llio.texi
> index e72c53c785..5ab68e1511 100644
> --- a/manual/llio.texi
> +++ b/manual/llio.texi
> @@ -1775,6 +1775,40 @@ the given @var{name} previously created by @code{shm_open}.
> On failure @code{errno} is set.
> @end deftypefn
>
> +@deftypefn Function int memfd_create (const char *@var{name}, unsigned int flags)
> +@standards{Linux, sys/memfd.h}
> +
> +The @code{memfd_create} function returns a file descriptor which can be
> +used to create memory mappings using the @code{mmap} function. It is
> +similar to the @code{shm_open} function in the sense that these mappings
> +are not backed by actual files. However, the descriptor return by
> +@code{memfd_create} does not correspond to a named object; the
> +@var{name} argument is used for informative purposes only. The
> +descriptor can be passed between processes (for example, over local
> +domain sockets), and mappings at the same offset refer to the same
> +memory, or the descriptor can be used to create alias mappings within
> +the same process.
> +
> +The descriptor initially refers to a zero-length file. Before mappings
> +can be created which are backed by memory, the file size needs to be
> +increased with the @code{ftruncate} function. @xref{File Size}.
> +
> +The @var{flags} argument can be a combination of the following flags:
> +
> +@table @code
> +@item MFD_CLOEXEC
> +The descriptor is created with the @code{O_CLOEXEC} flag.
> +
> +@item MFD_ALLOW_SEALING
> +The descriptor supports the addition of seals using the @code{fcntl}
> +function.
> +@end table
> +
> +The @code{memfd_create} function is specific to Linux.
> +
> +@end deftypefn
> +
> +
> @node Waiting for I/O
> @section Waiting for Input or Output
> @cindex waiting for input or output
Ok.
> diff --git a/support/Makefile b/support/Makefile
> index 027a663000..dafb1737a4 100644
> --- a/support/Makefile
> +++ b/support/Makefile
> @@ -109,19 +109,22 @@ libsupport-routines = \
> xpthread_once \
> xpthread_rwlock_init \
> xpthread_rwlock_rdlock \
> - xpthread_rwlock_wrlock \
> xpthread_rwlock_unlock \
> + xpthread_rwlock_wrlock \
> xpthread_rwlockattr_init \
> xpthread_rwlockattr_setkind_np \
> xpthread_sigmask \
> xpthread_spin_lock \
> xpthread_spin_unlock \
> + xreadlink \
> xrealloc \
> xrecvfrom \
> xsendto \
> xsetsockopt \
> xsocket \
> xstrdup \
> + xstrndup \
> + xunlink \
> xwaitpid \
> xwrite \
>
> @@ -138,6 +141,7 @@ tests = \
> tst-support_capture_subprocess \
> tst-support_format_dns_packet \
> tst-support_record_failure \
> + tst-xreadlink \
>
> ifeq ($(run-built-tests),yes)
> tests-special = \
> diff --git a/support/support.h b/support/support.h
> index 4b5f04c2cc..bbba803ba1 100644
> --- a/support/support.h
> +++ b/support/support.h
> @@ -68,6 +68,7 @@ void *xrealloc (void *p, size_t n);
> char *xasprintf (const char *format, ...)
> __attribute__ ((format (printf, 1, 2), malloc));
> char *xstrdup (const char *);
> +char *xstrndup (const char *, size_t);
>
> __END_DECLS
>
Ok.
> diff --git a/support/support_chroot.c b/support/support_chroot.c
> index f3ef551b05..f6fad18f33 100644
> --- a/support/support_chroot.c
> +++ b/support/support_chroot.c
> @@ -46,10 +46,11 @@ support_chroot_create (struct support_chroot_configuration conf)
> {
> struct support_chroot *chroot = xmalloc (sizeof (*chroot));
>
> - chroot->path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
> - if (mkdtemp (chroot->path_chroot) == NULL)
> - FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", chroot->path_chroot);
> - add_temp_file (chroot->path_chroot);
> + {
> + char *template = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir);
> + chroot->path_chroot = support_create_temp_directory (template);
> + free (template);
> + }
>
> /* Create the /etc directory in the chroot environment. */
> char *path_etc = xasprintf ("%s/etc", chroot->path_chroot);
Ok.
> diff --git a/support/temp_file.c b/support/temp_file.c
> index fdb2477ab9..cbd54e2e17 100644
> --- a/support/temp_file.c
> +++ b/support/temp_file.c
> @@ -86,6 +86,19 @@ create_temp_file (const char *base, char **filename)
> return fd;
> }
>
> +char *
> +support_create_temp_directory (const char *base)
> +{
> + char *base_copy = xstrdup (base);
> + if (mkdtemp (base_copy) == NULL)
> + {
> + printf ("error: mkdtemp (\"%s\"): %m", base);
> + exit (1);
> + }
> + add_temp_file (base_copy);
> + return base_copy;
> +}
> +
> /* Helper functions called by the test skeleton follow. */
>
> void
Ok.
> diff --git a/support/temp_file.h b/support/temp_file.h
> index 6fed8df1ea..dfefe585de 100644
> --- a/support/temp_file.h
> +++ b/support/temp_file.h
> @@ -32,6 +32,11 @@ void add_temp_file (const char *name);
> *FILENAME. */
> int create_temp_file (const char *base, char **filename);
>
> +/* Create a temporary directory and schedule it for deletion. BASE
> + must end with the six characters "XXXXXX". Return the name of the
> + temporary directory. The caller should free the string. */
> +char *support_create_temp_directory (const char *base);
> +
> __END_DECLS
>
> #endif /* SUPPORT_TEMP_FILE_H */
Ok.
> diff --git a/support/tst-xreadlink.c b/support/tst-xreadlink.c
> new file mode 100644
> index 0000000000..cb2c12a888
> --- /dev/null
> +++ b/support/tst-xreadlink.c
> @@ -0,0 +1,72 @@
> +/* Test the xreadlink function.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/temp_file.h>
> +#include <support/xunistd.h>
> +
> +static int
> +do_test (void)
> +{
> + char *dir = support_create_temp_directory ("/tmp/tst-xreadlink-XXXXXX");
> + char *symlink_name = xasprintf ("%s/symlink", dir);
> + add_temp_file (symlink_name);
> +
> + /* The limit 10000 is arbitrary and simply there to prevent an
> + attempt to exhaust all available disk space. */
> + for (int size = 1; size < 10000; ++size)
> + {
> + char *contents = xmalloc (size + 1);
> + for (int i = 0; i < size; ++i)
> + contents[i] = 'a' + (rand () % 26);
> + contents[size] = '\0';
> + if (symlink (contents, symlink_name) != 0)
> + {
> + if (errno == ENAMETOOLONG)
> + {
> + printf ("info: ENAMETOOLONG failure at %d bytes\n", size);
> + free (contents);
> + break;
> + }
> + FAIL_EXIT1 ("symlink (%d bytes): %m", size);
> + }
> +
> + char *readlink_result = xreadlink (symlink_name);
> + TEST_VERIFY (strcmp (readlink_result, contents) == 0);
> + free (readlink_result);
> + xunlink (symlink_name);
> + free (contents);
> + }
> +
> + /* Create an empty file to suppress the temporary file deletion
> + warning. */
> + xclose (xopen (symlink_name, O_WRONLY | O_CREAT, 0));
> +
> + free (symlink_name);
> + free (dir);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
I think it is better to split this test and the xreadlink
addition on another patch.
> diff --git a/support/xreadlink.c b/support/xreadlink.c
> new file mode 100644
> index 0000000000..aec58a2aa6
> --- /dev/null
> +++ b/support/xreadlink.c
> @@ -0,0 +1,44 @@
> +/* Error-checking, allocating wrapper for readlink.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#include <scratch_buffer.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <xunistd.h>
> +
> +char *
> +xreadlink (const char *path)
> +{
> + struct scratch_buffer buf;
> + scratch_buffer_init (&buf);
> +
> + while (true)
> + {
> + ssize_t count = readlink (path, buf.data, buf.length);
> + if (count < 0)
> + FAIL_EXIT1 ("readlink (\"%s\"): %m", path);
> + if (count < buf.length)
> + {
> + char *result = xstrndup (buf.data, count);
> + scratch_buffer_free (&buf);
> + return result;
> + }
> + if (!scratch_buffer_grow (&buf))
> + FAIL_EXIT1 ("scratch_buffer_grow in xreadlink");
> + }
> +}
I am not very found this way to handle unknown buffer size
requirements, but the other possible option I can think of
(lstat plus realloc) is not really different.
Ok.
> diff --git a/support/xstrndup.c b/support/xstrndup.c
> new file mode 100644
> index 0000000000..d59a283d25
> --- /dev/null
> +++ b/support/xstrndup.c
> @@ -0,0 +1,30 @@
> +/* strndup with error checking.
> + Copyright (C) 2016-2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#include <support/support.h>
> +
> +#include <string.h>
> +
> +char *
> +xstrndup (const char *s, size_t length)
> +{
> + char *p = strndup (s, length);
> + if (p == NULL)
> + oom_error ("strndup", length);
> + return p;
> +}
Ok.
> diff --git a/support/xunistd.h b/support/xunistd.h
> index c947bfd8fb..05c2626a7b 100644
> --- a/support/xunistd.h
> +++ b/support/xunistd.h
> @@ -38,6 +38,11 @@ int xopen (const char *path, int flags, mode_t);
> void xstat (const char *path, struct stat64 *);
> void xmkdir (const char *path, mode_t);
> void xchroot (const char *path);
> +void xunlink (const char *path);
> +
> +/* Read the link at PATH. The caller should free the returned string
> + with free. */
> +char *xreadlink (const char *path);
>
> /* Close the file descriptor. Ignore EINTR errors, but terminate the
> process on other errors. */
Ok.
> diff --git a/support/xunlink.c b/support/xunlink.c
> new file mode 100644
> index 0000000000..f94ee118cf
> --- /dev/null
> +++ b/support/xunlink.c
> @@ -0,0 +1,27 @@
> +/* Error-checking wrapper for unlink.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#include <support/check.h>
> +#include <support/xunistd.h>
> +
> +void
> +xunlink (const char *path)
> +{
> + if (unlink (path) != 0)
> + FAIL_EXIT1 ("unlink (\"%s\"): %m", path);
> +}
Ok.
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 0c8a009b5e..3a5515d092 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -39,7 +39,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
> sys/klog.h \
> sys/user.h sys/prctl.h \
> sys/kd.h sys/soundcard.h sys/vt.h \
> - sys/quota.h sys/fsuid.h \
> + sys/quota.h sys/fsuid.h sys/memfd.h \
> scsi/sg.h scsi/scsi.h scsi/scsi_ioctl.h sys/pci.h \
> sys/raw.h sys/personality.h sys/epoll.h \
> bits/a.out.h sys/inotify.h sys/signalfd.h sys/eventfd.h \
> @@ -50,7 +50,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
> bits/siginfo-arch.h bits/siginfo-consts-arch.h
>
> tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
> - tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max
> + tst-quota tst-sync_file_range test-errno-linux tst-sysconf-iov_max \
> + tst-memfd_create
>
> # Generate the list of SYS_* macros for the system calls (__NR_*
> # macros). The file syscall-names.list contains all possible system
Ok.
> diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
> index 6c9e06f4f9..992c19729f 100644
> --- a/sysdeps/unix/sysv/linux/Versions
> +++ b/sysdeps/unix/sysv/linux/Versions
> @@ -166,6 +166,9 @@ libc {
> GLIBC_2.15 {
> process_vm_readv; process_vm_writev;
> }
> + GLIBC_2.27 {
> + memfd_create;
> + }
> GLIBC_PRIVATE {
> # functions used in other libraries
> __syscall_rt_sigqueueinfo;
Ok.
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index ed598aedac..140ca28abc 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2106,6 +2106,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 4e57f36bcf..f698e1b2f4 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2017,6 +2017,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index 5b70e1bfc9..8a8af3e3e4 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -107,6 +107,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.4 GLIBC_2.4 A
> GLIBC_2.4 _Exit F
> GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 6a2500a8b3..5b81a6cd7d 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -1871,6 +1871,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index 9ab4e3642a..51ead9e867 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2036,6 +2036,7 @@ GLIBC_2.26 wcstof128_l F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index 81bb623fe8..78b4ee8d40 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -1900,6 +1900,7 @@ GLIBC_2.26 wcstof128_l F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 5a33b57390..d9c97779e4 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -108,6 +108,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.4 GLIBC_2.4 A
> GLIBC_2.4 _Exit F
> GLIBC_2.4 _IO_2_1_stderr_ D 0x98
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 50a86e74fa..4acbf7eeed 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -1985,6 +1985,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index 250ef305c3..93f02f08ce 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2106,3 +2106,4 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index 87a1dc4ad7..795e85de70 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -1960,6 +1960,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index f2b35f250e..dc714057b7 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -1958,6 +1958,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index ade654dbea..ce7bc9b175 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -1956,6 +1956,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index 56032c3f82..3fdd85eace 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -1951,6 +1951,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index c599dd9212..3e0bcb2a5c 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2147,3 +2147,4 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 385409aa6e..375c69d9d1 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -1989,6 +1989,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index e99cb454b5..a88172a906 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -1994,6 +1994,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> index 173672ab5e..fa026a332c 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> @@ -2201,3 +2201,4 @@ GLIBC_2.26 wcstof128_l F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> index 8a654436ab..838f395d78 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> @@ -108,6 +108,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 _Exit F
> GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index dbd411ceb1..41b79c496a 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -1989,6 +1989,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index 5617784ca0..68251a0e69 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -1890,6 +1890,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 0f840e6e88..bc1aae275e 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -1875,6 +1875,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index bb7e1042c7..93e6d092ac 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -1982,6 +1982,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 4053b0a51c..b11d6764d4 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -1919,6 +1919,7 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.27 strfromf128 F
> GLIBC_2.27 strtof128 F
> GLIBC_2.27 strtof128_l F
> diff --git a/sysdeps/unix/sysv/linux/sys/memfd.h b/sysdeps/unix/sysv/linux/sys/memfd.h
> new file mode 100644
> index 0000000000..8255ecd7a4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/sys/memfd.h
> @@ -0,0 +1,28 @@
> +/* memfd_create system call and constants.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#ifndef _SYS_MEMFD_H
> +#define _SYS_MEMFD_H
> +
> +#include <linux/memfd.h>
How do we handle the case of installed kernels version being lower
than 3.16 (the one that provides this header)?
> +
> +/* Create a new memory file descriptor. NAME is a name for debugging.
> + FLAGS is a combination of the MFD_* constants. */
> +int memfd_create (const char *__name, unsigned int __flags);
> +
> +#endif /* _SYS_MEMFD_H */
> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
> index 8bfb080d80..40c4fbb9ea 100644
> --- a/sysdeps/unix/sysv/linux/syscalls.list
> +++ b/sysdeps/unix/sysv/linux/syscalls.list
> @@ -109,3 +109,4 @@ setns EXTRA setns i:ii setns
>
> process_vm_readv EXTRA process_vm_readv i:ipipii process_vm_readv
> process_vm_writev EXTRA process_vm_writev i:ipipii process_vm_writev
> +memfd_create EXTRA memfd_create i:si memfd_create
Ok.
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> index 38a96d3a02..e9eb4ff7bd 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> @@ -2113,3 +2113,4 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> index 572b917d7d..8f08e909cd 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> @@ -2113,3 +2113,4 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> index 38a96d3a02..e9eb4ff7bd 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> @@ -2113,3 +2113,4 @@ GLIBC_2.26 reallocarray F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> diff --git a/sysdeps/unix/sysv/linux/tst-memfd_create.c b/sysdeps/unix/sysv/linux/tst-memfd_create.c
> new file mode 100644
> index 0000000000..709cf46791
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-memfd_create.c
> @@ -0,0 +1,134 @@
> +/* Test for the memfd_create system call.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <support/check.h>
> +#include <support/support.h>
> +#include <support/test-driver.h>
> +#include <support/xunistd.h>
> +#include <sys/syscall.h>
> +
> +#ifndef SYS_memfd_create
> +static int
> +do_test (void)
> +{
> + puts ("warning: kernel headers do not support memfd_create");
> + return EXIT_UNSUPPORTED;
> +}
> +
> +#else /* SYS_memfd_create */
> +
> +#include <sys/memfd.h>
> +
> +/* Return true if the descriptor has the FD_CLOEXEC flag set. */
> +static bool
> +is_cloexec (int fd)
> +{
> + int flags = fcntl (fd, F_GETFD);
> + TEST_VERIFY (flags >= 0);
> + return flags & FD_CLOEXEC;
> +}
> +
> +/* Return the seals set on FD. */
> +static int
> +get_seals (int fd)
> +{
> + int flags = fcntl (fd, F_GET_SEALS);
> + TEST_VERIFY (flags >= 0);
> + return flags;
> +}
> +
> +/* Return true if the F_SEAL_SEAL flag is set on the descriptor. */
> +static bool
> +is_sealed (int fd)
> +{
> + return get_seals (fd) & F_SEAL_SEAL;
> +}
> +
> +static int
> +do_test (void)
> +{
> + /* Initialized by the first call to memfd_create to 0 (memfd_create
> + unsupported) or 1 (memfd_create is implemented in the kernel).
> + Subsequent iterations check that the success/failure state is
> + consistent. */
> + int supported = -1;
I am not following why adding this extra logic and the one which
checks SYS_memfd_create. If __NR_memfd_create is not defined by
kernel headers a stub which returns ENOSYS will be created. Why
not just bail out with EXIT_UNSUPPORTED if errno is ENOSYS on
first call? Is there any expectation that memfd_create won't
return ENOSYS with different flags?
> +
> + for (int do_cloexec = 0; do_cloexec < 2; ++do_cloexec)
> + for (int do_sealing = 0; do_sealing < 2; ++do_sealing)
> + {
> + int flags = 0;
> + if (do_cloexec)
> + flags |= MFD_CLOEXEC;
> + if (do_sealing)
> + flags |= MFD_ALLOW_SEALING;
> + if (test_verbose > 0)
> + printf ("info: memfd_create with flags=0x%x\n", flags);
> + int fd = memfd_create ("tst-memfd_create", flags);
> + if (fd < 0)
> + {
> + if (errno == ENOSYS)
> + {
> + if (supported < 0)
> + {
> + supported = 0;
> + continue;
> + }
> + TEST_VERIFY (supported == 0);
> + continue;
> + }
> + else
> + FAIL_EXIT1 ("memfd_create: %m");
> + }
> + if (supported < 0)
> + supported = 1;
> + TEST_VERIFY (supported > 0);
> +
> + char *fd_path = xasprintf ("/proc/self/fd/%d", fd);
> + char *link = xreadlink (fd_path);
> + if (test_verbose > 0)
> + printf ("info: memfd link: %s\n", link);
> + TEST_VERIFY (strcmp (link, "memfd:tst-memfd_create (deleted)"));
> + TEST_VERIFY (is_cloexec (fd) == do_cloexec);
> + TEST_VERIFY (is_sealed (fd) == !do_sealing);
> + if (do_sealing)
> + {
> + TEST_VERIFY (fcntl (fd, F_ADD_SEALS, F_SEAL_WRITE) == 0);
> + TEST_VERIFY (!is_sealed (fd));
> + TEST_VERIFY (get_seals (fd) & F_SEAL_WRITE);
> + TEST_VERIFY (fcntl (fd, F_ADD_SEALS, F_SEAL_SEAL) == 0);
> + TEST_VERIFY (is_sealed (fd));
> + }
> + xclose (fd);
> + free (fd_path);
> + free (link);
> + }
> +
> + if (supported == 0)
> + return EXIT_UNSUPPORTED;
> + return 0;
> +}
> +
> +#endif /* SYS_memfd_create */
> +
> +#include <support/test-driver.c>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index b83d25c2e3..0a4f7797ac 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1877,6 +1877,7 @@ GLIBC_2.26 wcstof128_l F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
> GLIBC_2.3 GLIBC_2.3 A
> GLIBC_2.3 __ctype_b_loc F
> GLIBC_2.3 __ctype_tolower_loc F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index cba1d59057..23f6a91429 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2120,3 +2120,4 @@ GLIBC_2.26 wcstof128_l F
> GLIBC_2.27 GLIBC_2.27 A
> GLIBC_2.27 glob F
> GLIBC_2.27 glob64 F
> +GLIBC_2.27 memfd_create F
>