Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

glibc-2.27 memfd_create not being detected correctly with kernels 3.10.y/3.14.y #8099

Closed
MilhouseVH opened this issue Feb 5, 2018 · 24 comments · Fixed by #8229
Closed

glibc-2.27 memfd_create not being detected correctly with kernels 3.10.y/3.14.y #8099

MilhouseVH opened this issue Feb 5, 2018 · 24 comments · Fixed by #8229

Comments

@MilhouseVH
Copy link
Contributor

MilhouseVH commented Feb 5, 2018

Submission type

  • Bug report

systemd version the issue has been seen with

237

Used distribution

LibreELEC 9.0

In case of bug report: Expected behaviour you didn't see

Successful systemd build with glibc-2.27 and kernels that do not implement memfd_create.

In case of bug report: Unexpected behaviour you saw

systemd build failure with glibc-2.27 and kernels that do not implement memfd_create.

systemd builds successfully with glibc-2.27 and kernel 4.14.16.

In case of bug report: Steps to reproduce the problem

Build systemd-237 with glibc-2.27 and kernels 3.10.108 or 3.14.29 (most likely any other kernel prior to 3.17.0 when the memfd_create syscall is introduced to the kernel).

I've encountered a problem building systemd-237 and glibc-2.27 with kernels that do not implement the memfd_create syscall (ie. any kernel before 3.17.0).

For example, when building 3.10.108, glibc-2.27 and systemd-237:

[66/985] Compiling C object 'src/basic/basic@sta/barrier.c.o'.
[67/985] Compiling C object 'src/basic/basic@sta/calendarspec.c.o'.
FAILED: src/basic/basic@sta/calendarspec.c.o
/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/bin/armv8a-libreelec-linux-gnueabi-gcc -march=armv8-a+crc -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -fomit-frame-pointer -Wall -pipe -Os -flto -ffat-lto-objects -Isrc/basic/basic@sta -Isrc/basic -I../src/basic -I. -I../ -Isrc/libsystemd-network -I../src/libsystemd-network -I../src/libsystemd/sd-network -I../src/libsystemd/sd-netlink -I../src/libsystemd/sd-id128 -I../src/libsystemd/sd-hwdb -I../src/libsystemd/sd-device -I../src/libsystemd/sd-bus -Isrc/core -I../src/core -Isrc/libudev -I../src/libudev -Isrc/udev -I../src/udev -Isrc/login -I../src/login -Isrc/timesync -I../src/timesync -Isrc/resolve -I../src/resolve -Isrc/journal -I../src/journal -Isrc/systemd -I../src/systemd -Isrc/shared -I../src/shared -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/blkid -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/uuid -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -std=gnu99 -Wextra -Werror=undef -Wlogical-op -Wmissing-include-dirs -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wsuggest-attribute=noreturn -Werror=missing-prototypes -Werror=implicit-function-declaration -Werror=missing-declarations -Werror=return-type -Werror=incompatible-pointer-types -Werror=format=2 -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wimplicit-fallthrough=5 -Wshadow -Wendif-labels -Wstrict-aliasing=2 -Wwrite-strings -Werror=overflow -Wdate-time -Wnested-externs -ffast-math -fno-common -fdiagnostics-show-option -fno-strict-aliasing -fvisibility=hidden -fstack-protector -fstack-protector-strong --param=ssp-buffer-size=4 -fPIE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -Werror=shadow -ffunction-sections -fdata-sections -include config.h -fPIC -pthread -fvisibility=default -MMD -MQ 'src/basic/basic@sta/calendarspec.c.o' -MF 'src/basic/basic@sta/calendarspec.c.o.d' -o 'src/basic/basic@sta/calendarspec.c.o' -c ../src/basic/calendarspec.c
In file included from ../src/basic/missing.h:1358:0,
                 from ../src/basic/util.h:47,
                 from ../src/basic/calendarspec.h:29,
                 from ../src/basic/calendarspec.c:34:
../src/basic/missing_syscall.h:65:19: error: static declaration of 'memfd_create' follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
In file included from /home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/bits/mman-linux.h:115:0,
                 from /home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/bits/mman.h:40,
                 from /home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/sys/mman.h:41,
                 from ../src/basic/calendarspec.c:30:
/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/bits/mman-shared.h:46:5: note: previous declaration of 'memfd_create' was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~
[68/985] Compiling C object 'src/basic/basic@sta/cap-list.c.o'.
[69/985] Compiling C object 'src/basic/basic@sta/capability-util.c.o'.
[70/985] Compiling C object 'src/basic/basic@sta/clock-util.c.o'.
[71/985] Compiling C object 'src/basic/basic@sta/exit-status.c.o'.
[72/985] Compiling C object 'src/basic/basic@sta/ether-addr-util.c.o'.
[73/985] Compiling C object 'src/basic/basic@sta/copy.c.o'.
[74/985] Compiling C object 'src/basic/basic@sta/btrfs-util.c.o'.
[75/985] Compiling C object 'src/basic/basic@sta/extract-word.c.o'.
[76/985] Compiling C object 'src/basic/basic@sta/cgroup-util.c.o'.
../src/basic/cgroup-util.c: In function 'cg_pid_get_path':
../src/basic/cgroup-util.c:1066:48: warning: 'controller_str' may be used uninitialized in this function [-Wmaybe-uninitialized]
                                 if (k == cs && memcmp(word, controller_str, cs) == 0) {
                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ninja: build stopped: subcommand failed.

The HAVE_MEMFD_CREATE detection in meson.build is failing to determine that memfd_create is now implemented by glibc-2.27, however it appears to fail only when the kernel does not also implement this syscall. If the kernel does implement memfd_create, ie. 4.14.16, then the meson detection works as expected and the build succeeds.

system-237 sets the following #defines when building with glibc-2.27 and the stated kernels:

kernel 3.10.108:

config.h:#define HAVE_LINUX_MEMFD_H 0
config.h:#define HAVE_MEMFD_CREATE 0

kernel 3.14.29:

config.h:#define HAVE_LINUX_MEMFD_H 0
config.h:#define HAVE_MEMFD_CREATE 0

kernel 4.14.16:

config.h:#define HAVE_LINUX_MEMFD_H 1
config.h:#define HAVE_MEMFD_CREATE 1

Consequently systemd-237 fails to build with glibc-2.27 and kernels 3.10.108 and 3.14.29 (see build error, above), but builds successfully with 4.14.16.

Since LibreELEC will only be building with glibc-2.27 (which implements memfd_create) as a workaround I'm using this patch to force enable HAVE_MEMFD_CREATE in meson.build and I'm able to successfully build systemd-237 with all kernels.

The patch confirms that systemd-237 is building with the glibc-2.27 implementation of memfd_create because if we use the patch and build systemd-237 with glibc-2.26 (and not glibc-2.27) then systemd will fail to build as memfd_create is no longer declared. For example:

FAILED: src/basic/basic@sta/fileio.c.o
/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/bin/armv8a-libreelec-linux-gnueabi-gcc -march=armv8-a+crc -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -fomit-frame-pointer -Wall -pipe -Os -flto -ffat-lto-objects -Isrc/basic/basic@sta -Isrc/basic -I../src/basic -I. -I../ -Isrc/libsystemd-network -I../src/libsystemd-network -I../src/libsystemd/sd-network -I../src/libsystemd/sd-netlink -I../src/libsystemd/sd-id128 -I../src/libsystemd/sd-hwdb -I../src/libsystemd/sd-device -I../src/libsystemd/sd-bus -Isrc/core -I../src/core -Isrc/libudev -I../src/libudev -Isrc/udev -I../src/udev -Isrc/login -I../src/login -Isrc/timesync -I../src/timesync -Isrc/resolve -I../src/resolve -Isrc/journal -I../src/journal -Isrc/systemd -I../src/systemd -Isrc/shared -I../src/shared -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/blkid -I/home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/armv8a-libreelec-linux-gnueabi/sysroot/usr/include/uuid -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -std=gnu99 -Wextra -Werror=undef -Wlogical-op -Wmissing-include-dirs -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wsuggest-attribute=noreturn -Werror=missing-prototypes -Werror=implicit-function-declaration -Werror=missing-declarations -Werror=return-type -Werror=incompatible-pointer-types -Werror=format=2 -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wimplicit-fallthrough=5 -Wshadow -Wendif-labels -Wstrict-aliasing=2 -Wwrite-strings -Werror=overflow -Wdate-time -Wnested-externs -ffast-math -fno-common -fdiagnostics-show-option -fno-strict-aliasing -fvisibility=hidden -fstack-protector -fstack-protector-strong --param=ssp-buffer-size=4 -fPIE -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -Werror=shadow -ffunction-sections -fdata-sections -include config.h -fPIC -pthread -fvisibility=default -MMD -MQ 'src/basic/basic@sta/fileio.c.o' -MF 'src/basic/basic@sta/fileio.c.o.d' -o 'src/basic/basic@sta/fileio.c.o' -c ../src/basic/fileio.c
../src/basic/fileio.c: In function 'open_serialization_fd':
../src/basic/fileio.c:1460:14: error: implicit declaration of function 'memfd_create'; did you mean 'timer_create'? [-Werror=implicit-function-declaration]
         fd = memfd_create(ident, MFD_CLOEXEC);
              ^~~~~~~~~~~~
              timer_create
../src/basic/fileio.c:1460:14: warning: nested extern declaration of 'memfd_create' [-Wnested-externs]
cc1: some warnings being treated as errors

However this patch, while it works, is not ideal as we'd rather not patch against upstream. And it's just a hack.

Does anyone have any idea why HAVE_MEMFD_CREATE is not being determined correctly by meson.build when the kernel does not implement memfd_create but glibc does?

@yuwata
Copy link
Member

yuwata commented Feb 5, 2018

If I understand correctly, memfd_create() is added to glibc quite recently.
https://sourceware.org/git/?p=glibc.git;a=commit;h=59d2cbb1fe4b8601d5cbd359c3806973eab6c62d
So, for such system which does not have recent glibc, HAVE_MEMFD_CREATE is set to false.

Note that, in the case of Fedora, v27 (the most recent release) does not have memfd_create() in glibc header, and the current development (rawhide) has it.

@MilhouseVH
Copy link
Contributor Author

MilhouseVH commented Feb 5, 2018

Yes, memfd_create is added in glibc-2.27, which is the version LibreELEC 9.0 is building with, yet systemd-237 is failing to correctly determine that glibc-2.27 is now providing memfd_create when building with these older 3.x kernels (that do not implement memfd_create). Consequently the systemd build fails when systemd redeclares memfd_create which is being provided by the glibc-2.27 headers (the same glibc headers that meson.build failed to findprocess correctly during configure).

I believe 85db59b should have addressed this issue and should now be configuring #define HAVE_MEMFD_CREATE 1 regardless of kernel version when memfd_create is provided by glibc-2.27, but for some reason it isn't working reliably and the test fails with these older 3.x kernels, meaning HAVE_MEMFD_CREATE remains disabled when it should be enabled.

In short, it would appear that HAVE_MEMFD_CREATE is not working with glibc-2.27 depending on the kernel (although this is just a guess, based on the pattern of failures I've seen so far with these 3 kernels).

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

We don't have glibc-2.27 in Fedora. The latest is glibc-devel-2.26.9000-51.fc28.x86_64. I expect that it's essentially identical to the released version though.

I tried to replicate the build failure with glibc-2.26.9000, and kernels going back to kernel-headers-4.9.4-201.fc25.x86_64, and it builds fine. But I'm on amd64, arm might be different.

Please attach build/meson-logs/meson-log.txt from one of the affected systems.

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

Builds fine on Fedora arm too: kernel-headers-4.14.13-300.fc27.armv7hl and glibc-devel-2.26.9000-51.fc28.armv7hl.

@MilhouseVH
Copy link
Contributor Author

There is no problem with glibc-2.26 - I can build systemd-237 with glibc-2.26 and (for example) kernel 3.10.108 without any issue, as glibc-2.26 does not implement memfd_create.

However, when building with glibc-2.27 and systemd-237 and 3.10.108 (or 3.14.29), systemd will fail to build as systemd fails to determine the presence of memfd_create which is now being provided by glibc-2.27.

This only seems to be an issue with kernels that DON'T implement memfd_create (so anything prior to 3.17.0) - there is no problem with 4.14.16, but there is a problem with 3.10.108 and 3.14.29.

meson-log.txt (systemd-237 + glibc-2.27 + kernel 3.14.29): http://ix.io/FhH (which fails)
meson-log.txt (systemd-237 + glibc-2.27 + kernel 4.14.16): http://ix.io/FhJ (successful)

With 3.14.29, the first test fails as __stub_memfd_create is defined in include/gnu/stubs-hard.h, which is correct as this kernel doesn't implement the syscall.

The next test also fails (but shouldn't!) because memfd_create is not defined, however there is a memfd_create function declaration in the glibc-2.27 header - it's in include/bits/mman-shared.h.

Is the ! defined(memfd_create) test correct? I'm not a C guru so I'm not sure if defined is a valid test for a function declaration. But this second test should be successful as glibc-2.27 is now providing memfd_create.

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

Oh, I think it comes down to the meson version. With meson-0.44.0:

Code:
 #include <sys/mman.h>
#include <limits.h>

        #if defined __stub_memfd_create || defined __stub___memfd_create
        fail fail fail this function is not going to work
        #endif
        
int main() {
            void *a = (void*) &memfd_create;
            long b = (long) a;
            return (int) b;
        }
Compiler stdout:
 
Compiler stderr:
 
Checking for function "memfd_create": YES

Essentially, the test is broken in meson-0.42.

@MilhouseVH
Copy link
Contributor Author

Ah OK thanks, I'll try upgrading to meson-0.44.0 and will report back once I've tested.

@MilhouseVH
Copy link
Contributor Author

Unfortunately I'm not seeing any difference with meson-0.44.0: http://ix.io/Fik

Note that it's not the first test that is the problem, it's the second:

Running compile:
Working directory:  /tmp/tmp63a184_e
Command line:  /home/neil/projects/scratch/alternates/LibreELEC.tv/build.LibreELEC-WeTek_Hub.arm-9.0-devel-next/toolchain/bin/armv8a-libreelec-linux-gnueabi-gcc /tmp/tmp63a184_e/testfile.c -march=armv8-a+crc -mabi=aapcs-linux -Wno-psabi -Wa,-mno-warn-deprecated -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -fomit-frame-pointer -Wall -pipe -Os -flto -ffat-lto-objects -march=armv8-a+crc -mtune=cortex-a53 -Wl,--as-needed -fuse-ld=gold -fuse-linker-plugin -flto -O0 -std=gnu99 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -o /tmp/tmp63a184_e/output.exe 

Code:
 #include <sys/mman.h>
        int main() {
        #ifdef __has_builtin
            #if !__has_builtin(__builtin_memfd_create)
                #error "__builtin_memfd_create not found"
            #endif
        #elif ! defined(memfd_create)
            /* Check for __builtin_memfd_create only if no includes were added to the
             * prefix above, which means no definition of memfd_create can be found.
             * We would always check for this, but we get false positives on
             * MSYS2 if we do. Their toolchain is broken, but we can at least
             * give them a workaround. */
            #if 0
                __builtin_memfd_create;
            #else
                #error "No definition for __builtin_memfd_create found in the prefix"
            #endif
        #endif
        }
Compiler stdout:
 
Compiler stderr:
 /tmp/tmp63a184_e/testfile.c: In function 'main':
/tmp/tmp63a184_e/testfile.c:16:18: error: #error "No definition for __builtin_memfd_create found in the prefix"
                 #error "No definition for __builtin_memfd_create found in the prefix"
                  ^~~~~

Checking for function "memfd_create": NO

The failure of this second test leaves HAVE_MEMFD_CREATE set to 0, which results in systemd trying to redeclare the memfd_create syscall that is now implemented by glibc-2.27.

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

Oh, OK. So the test fails because __stub_memfd_create or __stub___memfd_create is defined. This defeats the test which checks for function memfd_create. Then the second test checks for __builtin_memfd_create, which doesn't exist. So the real problem is the first fails, not the second.

But on Fedora, even with kernel-headers-3.16.3-302.fc21.x86_64, memfd_create is detected properly with new glibc. So it seems something is different in your glibc headers...

@MilhouseVH
Copy link
Contributor Author

By the way I'm building with gcc-7.3.0. I don't know what else to look for, but I have a workaround for now. If not reproducible, then no big deal.

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

It's probably reproducible, but requires the right combination of kernel/glibc...

@keszybz
Copy link
Member

keszybz commented Feb 5, 2018

I now tested with glibc-devel-2.27-1.fc28.x86_64, and it works.

@MilhouseVH
Copy link
Contributor Author

Did I mention I'm cross-compiling? :)

@keszybz
Copy link
Member

keszybz commented Feb 20, 2018

To recap: the build is failing because either __stub_memfd_create or __stub___memfd_create is defined, so meson assumes that stub_memfd_create is not declared, but it actually is declared, so the build fails, because the system definition conflicts with our definition.

The real issue is that there's confusion in what meson.get_compiler().has_function() means:

  • meson effectively checks if the function is defined and usable
  • we need a check if the function is defined

So either our logic or meson needs to change.

keszybz added a commit to keszybz/systemd that referenced this issue Feb 20, 2018
In meson.build we check that functions are available using:
    meson.get_compiler('c').has_function('foo')
which checks the following:
if __stub_foo or __stub___foo are defined, return false
if foo is declared (a pointer to the function can be taken), return true
otherwise check for __builtin_memfd_create

_stub is documented by glibc as
   It defines a symbol '__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.

So if __stub is defined, we know we don't want to use the glibc version, but
this doesn't tell us if the name itself is defined or not. If it _is_ defined,
and we define our replacement as an inline static function, we get an error:

In file included from ../src/basic/missing.h:1358:0,
                 from ../src/basic/util.h:47,
                 from ../src/basic/calendarspec.h:29,
                 from ../src/basic/calendarspec.c:34:
../src/basic/missing_syscall.h:65:19: error: static declaration of 'memfd_create' follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
.../usr/include/bits/mman-shared.h:46:5: note: previous declaration of 'memfd_create' was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~

To avoid this problem, call our inline functions different than glibc,
and use a #define to map the official name to our replacement.

Fixes systemd#8099.
@keszybz keszybz added the has-pr label Feb 20, 2018
keszybz added a commit to keszybz/systemd that referenced this issue Feb 21, 2018
In meson.build we check that functions are available using:
    meson.get_compiler('c').has_function('foo')
which checks the following:
- if __stub_foo or __stub___foo are defined, return false
- if foo is declared (a pointer to the function can be taken), return true
- otherwise check for __builtin_memfd_create

_stub is documented by glibc as
   It defines a symbol '__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.

So if __stub is defined, we know we don't want to use the glibc version, but
this doesn't tell us if the name itself is defined or not. If it _is_ defined,
and we define our replacement as an inline static function, we get an error:

In file included from ../src/basic/missing.h:1358:0,
                 from ../src/basic/util.h:47,
                 from ../src/basic/calendarspec.h:29,
                 from ../src/basic/calendarspec.c:34:
../src/basic/missing_syscall.h:65:19: error: static declaration of 'memfd_create' follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
.../usr/include/bits/mman-shared.h:46:5: note: previous declaration of 'memfd_create' was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~

To avoid this problem, call our inline functions different than glibc,
and use a #define to map the official name to our replacement.

Fixes systemd#8099.

v2:
- use "missing_" as the prefix instead of "_"
keszybz added a commit to keszybz/systemd that referenced this issue Feb 21, 2018
In meson.build we check that functions are available using:
    meson.get_compiler('c').has_function('foo')
which checks the following:
- if __stub_foo or __stub___foo are defined, return false
- if foo is declared (a pointer to the function can be taken), return true
- otherwise check for __builtin_memfd_create

_stub is documented by glibc as
   It defines a symbol '__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.

So if __stub is defined, we know we don't want to use the glibc version, but
this doesn't tell us if the name itself is defined or not. If it _is_ defined,
and we define our replacement as an inline static function, we get an error:

In file included from ../src/basic/missing.h:1358:0,
                 from ../src/basic/util.h:47,
                 from ../src/basic/calendarspec.h:29,
                 from ../src/basic/calendarspec.c:34:
../src/basic/missing_syscall.h:65:19: error: static declaration of 'memfd_create' follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
.../usr/include/bits/mman-shared.h:46:5: note: previous declaration of 'memfd_create' was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~

To avoid this problem, call our inline functions different than glibc,
and use a #define to map the official name to our replacement.

Fixes systemd#8099.

v2:
- use "missing_" as the prefix instead of "_"

v3:
- rebase and update for statx()

  Unfortunately "statx" is also present in "struct statx", so the define
  causes issues. Work around this by using a typedef.

I checked that systemd compiles with current glibc
(glibc-devel-2.26-24.fc27.x86_64) if HAVE_MEMFD_CREATE, HAVE_GETTID,
HAVE_PIVOT_ROOT, HAVE_SETNS, HAVE_RENAMEAT2, HAVE_KCMP, HAVE_KEYCTL,
HAVE_COPY_FILE_RANGE, HAVE_BPF, HAVE_STATX are forced to 0.

Setting HAVE_NAME_TO_HANDLE_AT to 0 causes an issue, but it's not because of
the define, but because of struct file_handle.
poettering pushed a commit that referenced this issue Feb 21, 2018
#8229)

In meson.build we check that functions are available using:
    meson.get_compiler('c').has_function('foo')
which checks the following:
- if __stub_foo or __stub___foo are defined, return false
- if foo is declared (a pointer to the function can be taken), return true
- otherwise check for __builtin_memfd_create

_stub is documented by glibc as
   It defines a symbol '__stub_FUNCTION' for each function
   in the C library which is a stub, meaning it will fail
   every time called, usually setting errno to ENOSYS.

So if __stub is defined, we know we don't want to use the glibc version, but
this doesn't tell us if the name itself is defined or not. If it _is_ defined,
and we define our replacement as an inline static function, we get an error:

In file included from ../src/basic/missing.h:1358:0,
                 from ../src/basic/util.h:47,
                 from ../src/basic/calendarspec.h:29,
                 from ../src/basic/calendarspec.c:34:
../src/basic/missing_syscall.h:65:19: error: static declaration of 'memfd_create' follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
.../usr/include/bits/mman-shared.h:46:5: note: previous declaration of 'memfd_create' was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~

To avoid this problem, call our inline functions different than glibc,
and use a #define to map the official name to our replacement.

Fixes #8099.

v2:
- use "missing_" as the prefix instead of "_"

v3:
- rebase and update for statx()

  Unfortunately "statx" is also present in "struct statx", so the define
  causes issues. Work around this by using a typedef.

I checked that systemd compiles with current glibc
(glibc-devel-2.26-24.fc27.x86_64) if HAVE_MEMFD_CREATE, HAVE_GETTID,
HAVE_PIVOT_ROOT, HAVE_SETNS, HAVE_RENAMEAT2, HAVE_KCMP, HAVE_KEYCTL,
HAVE_COPY_FILE_RANGE, HAVE_BPF, HAVE_STATX are forced to 0.

Setting HAVE_NAME_TO_HANDLE_AT to 0 causes an issue, but it's not because of
the define, but because of struct file_handle.
@sonvirgo
Copy link

sonvirgo commented Mar 15, 2018

I am on systemd 238 and have the same issue while making pulseaudio-raop2.
Work around please.
Kali 2017.3
kernel 4.14.17

In file included from pulsecore/shm.c:48:0:
./pulsecore/memfd-wrappers.h:36:19: error: static declaration of ‘memfd_create’ follows non-static declaration
 static inline int memfd_create(const char *name, unsigned int flags) {
                   ^~~~~~~~~~~~
In file included from /usr/include/x86_64-linux-gnu/bits/mman-linux.h:115:0,
                 from /usr/include/x86_64-linux-gnu/bits/mman.h:45,
                 from /usr/include/x86_64-linux-gnu/sys/mman.h:41,
                 from pulsecore/shm.c:37:
/usr/include/x86_64-linux-gnu/bits/mman-shared.h:46:5: note: previous declaration of ‘memfd_create’ was here
 int memfd_create (const char *__name, unsigned int __flags) __THROW;
     ^~~~~~~~~~~~
Makefile:8048: recipe for target 'pulsecore/libpulsecommon_7.0_la-shm.lo' failed
make[3]: *** [pulsecore/libpulsecommon_7.0_la-shm.lo] Error 1
make[3]: *** Waiting for unfinished jobs....
make[3]: Leaving directory '/root/Downloads/pulseaudio-raop2/src'
Makefile:4920: recipe for target 'all' failed
make[2]: *** [all] Error 2
make[2]: Leaving directory '/root/Downloads/pulseaudio-raop2/src'
Makefile:807: recipe for target 'all-recursive' failed
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory '/root/Downloads/pulseaudio-raop2'
Makefile:622: recipe for target 'all' failed
make: *** [all] Error 2

@floppym
Copy link
Contributor

floppym commented Mar 15, 2018

I am on systemd 238 and have the same issue while making pulseaudio-raop2.

That's a problem you should report to the developers of "pulseaudio-raop2". It has nothing to do with systemd.

@sonvirgo
Copy link

sonvirgo commented Mar 15, 2018

@floppym Really? Becasue it makes fine with systemd 234, Ubuntu Zesty, so I suspect some thing wrong in systemd 238?

@floppym
Copy link
Contributor

floppym commented Mar 15, 2018

Ubuntu Zesty probably has an older version of glibc.

@sonvirgo
Copy link

@floppym I think it glibc 2.24-9ubuntu2.2

@floppym
Copy link
Contributor

floppym commented Mar 15, 2018

glibc-2.24 is obviously older than glibc-2.27, which is the version which triggered the bug reported in this systemd bug report.

Again, your pulseaudio-raop2 build failure has nothing to do with systemd, despite what your Google search may be returning.

@sonvirgo
Copy link

Ok Thanks!
By the way, as I am new to linux do you have any help to work around like patch or upgrade/downgrade glibc?

@floppym
Copy link
Contributor

floppym commented Mar 15, 2018

It will probably work if you remove the function definition from https://github.com/hfujita/pulseaudio-raop2/blob/hf/raop2-v7-next/src/pulsecore/memfd-wrappers.h#L36.

@sonvirgo
Copy link

@floppym Thank you! Although it is late, I will try your suggestion, tomorrow morning after the system finish upgrading with glibc 2.7.2
Regards!

@sonvirgo
Copy link

Your suggestion work, however it not makes it due to openssl 1.1.0 API backward incompatibility.
I will try upstream version 11.1. Thank you anyhow.

kraj added a commit to kraj/openembedded-core that referenced this issue Mar 20, 2018
Backport a fix that is needed for systemd to build with latest glibc
and kernel being old.

see
systemd/systemd#8099

Signed-off-by: Khem Raj <raj.khem@gmail.com>
halstead pushed a commit to openembedded/openembedded-core that referenced this issue Mar 25, 2018
Backport a fix that is needed for systemd to build with latest glibc
and kernel being old.

see
systemd/systemd#8099

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
gbionescu pushed a commit to gbionescu/poky that referenced this issue Mar 25, 2018
Backport a fix that is needed for systemd to build with latest glibc
and kernel being old.

see
systemd/systemd#8099

(From OE-Core rev: 169d061b313ebb91bf18f09d998a42c4ae165bf8)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
mikhailnov added a commit to mikhailnov/systemd that referenced this issue Aug 16, 2019
tunayan pushed a commit to tunayan/poky-mirror that referenced this issue Aug 2, 2023
Backport a fix that is needed for systemd to build with latest glibc
and kernel being old.

see
systemd/systemd#8099

(From OE-Core rev: 169d061)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

5 participants