Commit 1cb2e387 "libxfs: add xfile support" introduced a use of the memfd_create() system call, included in version xfsprogs v6.9.0. This system call was introduced in kernel commit [1], first included in kernel v3.17 (released on 2014-10-05). The memfd_create() glibc wrapper function was added much later in commit [2], first included in glibc version 2.27 (released on 2018-02-01). This direct use memfd_create() introduced a requirement on Kernel >= 3.17 and glibc >= 2.27. There is old toolchains like [3] for example (which ships gcc 7.3.1, glibc 2.25 and includes kernel v4.10 headers), that can still be used to build newer kernels. Even if such toolchains can be seen as outdated, they are still claimed as supported by recent kernel. For example, Kernel v6.10.5 has a requirement on gcc version 5.1 and greater. See [4]. When compiling xfsprogs v6.9.0 with a toolchain not providing the memfd_create() syscall wrapper, the compilation fail with message: xfile.c: In function 'xfile_create_fd': xfile.c:56:7: warning: implicit declaration of function 'memfd_create'; did you mean 'timer_create'? [-Wimplicit-function-declaration] fd = memfd_create(description, MFD_CLOEXEC | MFD_NOEXEC_SEAL); ^~~~~~~~~~~~ ../libxfs/.libs/libxfs.a(xfile.o): In function 'xfile_create_fd': /build/xfsprogs-6.9.0/libxfs/xfile.c:56: undefined reference to 'memfd_create' In order to let xfsprogs compile in a wider range of configurations, this commit adds a memfd_create() function check in autoconf configure script, and adds a system call wrapper which will be used if the function is not available. With this commit, the environment requirement is relaxed to only kernel >= v3.17. Note: this issue was found in xfsprogs integration in Buildroot [5] using the command "utils/test-pkg -a -p xfsprogs", which tests many toolchain/arch combinations. [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9183df25fe7b194563db3fec6dc3202a5855839c [2] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=59d2cbb1fe4b8601d5cbd359c3806973eab6c62d [3] https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz [4] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/process/changes.rst?h=v6.10.5#n32 [5] https://buildroot.org/ Signed-off-by: Julien Olivain <ju.o@xxxxxxx> --- configure.ac | 1 + include/builddefs.in | 1 + libxfs/Makefile | 4 ++++ libxfs/xfile.c | 16 ++++++++++++++++ m4/package_libcdev.m4 | 18 ++++++++++++++++++ 5 files changed, 40 insertions(+) diff --git a/configure.ac b/configure.ac index b84234b5..8a9ddb3f 100644 --- a/configure.ac +++ b/configure.ac @@ -151,6 +151,7 @@ AC_HAVE_MAP_SYNC AC_HAVE_DEVMAPPER AC_HAVE_MALLINFO AC_HAVE_MALLINFO2 +AC_HAVE_MEMFD_CREATE AC_PACKAGE_WANT_ATTRIBUTES_H AC_HAVE_LIBATTR if test "$enable_scrub" = "yes"; then diff --git a/include/builddefs.in b/include/builddefs.in index 734bd95e..1647d2cd 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -101,6 +101,7 @@ HAVE_MAP_SYNC = @have_map_sync@ HAVE_DEVMAPPER = @have_devmapper@ HAVE_MALLINFO = @have_mallinfo@ HAVE_MALLINFO2 = @have_mallinfo2@ +HAVE_MEMFD_CREATE = @have_memfd_create@ HAVE_LIBATTR = @have_libattr@ HAVE_LIBICU = @have_libicu@ HAVE_SYSTEMD = @have_systemd@ diff --git a/libxfs/Makefile b/libxfs/Makefile index 2f2791ca..833c6509 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -128,6 +128,10 @@ CFILES = buf_mem.c \ # #LCFLAGS += +ifeq ($(HAVE_MEMFD_CREATE),yes) +LCFLAGS += -DHAVE_MEMFD_CREATE +endif + FCFLAGS = -I. LTLIBS = $(LIBPTHREAD) $(LIBRT) diff --git a/libxfs/xfile.c b/libxfs/xfile.c index b4908b49..b8379775 100644 --- a/libxfs/xfile.c +++ b/libxfs/xfile.c @@ -8,6 +8,9 @@ #include "libxfs/xfile.h" #include <linux/memfd.h> #include <sys/mman.h> +#ifndef HAVE_MEMFD_CREATE +#include <sys/syscall.h> +#endif #include <sys/types.h> #include <sys/wait.h> @@ -36,6 +39,19 @@ # define MFD_NOEXEC_SEAL (0x0008U) #endif +/* + * The memfd_create system call was added to kernel 3.17 (2014), but + * its corresponding glibc wrapper was only added in glibc 2.27 + * (2018). In case a libc is not providing the wrapper, we provide + * one here. + */ +#ifndef HAVE_MEMFD_CREATE +static int memfd_create(const char *name, unsigned int flags) +{ + return syscall(SYS_memfd_create, name, flags); +} +#endif + /* * Open a memory-backed fd to back an xfile. We require close-on-exec here, * because these memfd files function as windowed RAM and hence should never diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4 index de64c9af..6de8b33e 100644 --- a/m4/package_libcdev.m4 +++ b/m4/package_libcdev.m4 @@ -177,6 +177,24 @@ test = mallinfo2(); AC_SUBST(have_mallinfo2) ]) +# +# Check if we have a memfd_create libc call (Linux) +# +AC_DEFUN([AC_HAVE_MEMFD_CREATE], + [ AC_MSG_CHECKING([for memfd_create]) + AC_LINK_IFELSE( + [ AC_LANG_PROGRAM([[ +#define _GNU_SOURCE +#include <sys/mman.h> + ]], [[ +memfd_create(0, 0); + ]]) + ], have_memfd_create=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) + AC_SUBST(have_memfd_create) + ]) + AC_DEFUN([AC_PACKAGE_CHECK_LTO], [ AC_MSG_CHECKING([if C compiler supports LTO]) OLD_CFLAGS="$CFLAGS" -- 2.46.0