Summary: | Configuring with --disable-hidden-plt on x86_64 and arm64 makes built fail | ||
---|---|---|---|
Product: | glibc | Reporter: | Robert Henry <rrh.henry> |
Component: | build | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | carlos, hjl.tools, nsz, rnewman, rrh.henry |
Priority: | P2 | ||
Version: | 2.33 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Robert Henry
2021-04-02 17:27:58 UTC
On x86_64, ubuntu 21.04. Configuring out-of-the-box glibc 2.33 build with --disable-hidden-plt results in a build-time failure (there may be more errors like this) ./sysdeps/x86_64/multiarch/strcat.c:32:1: error: data definition has no type or storage class [-Werror] 32 | __hidden_ver1 (strcat, __GI_strcat, __redirect_strcat) | ^~~~~~~~~~~~~ ../sysdeps/x86_64/multiarch/strcat.c:32:1: error: type defaults to ‘int’ in declaration of ‘__hidden_ver1’ [-Werror=implicit-int] ../sysdeps/x86_64/multiarch/strcat.c:33:3: error: parameter names (without types) in function declaration [-Werror] 33 | __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcat); | ^~~~~~~~~~~~~ ../sysdeps/x86_64/multiarch/strcat.c:33:3: error: ‘nonnull’ attribute without arguments on a non-prototype cc1: all warnings being treated as errors On ARM64, ubuntu 21.04, configuring the same way, results in a similar error at a different location (there may be more errors; make stopped on first fail) ../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: data definition has no type or storage class [-Werror] 53 | __hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64); | ^~~~~~~~~~~~~ ../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: type defaults to ‘int’ in declaration of ‘__hidden_ver1’ [-Werror=implicit-int] ../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: parameter names (without types) in function declaration [-Werror] cc1: all warnings being treated as errors ------------ Is the flag --disable-hidden-plt checked on a regular basis? This option was added by commit 749a9a4fbfd261e2d9811d9bc4507478c2f7cc58 Author: Roland McGrath <roland@gnu.org> Date: Tue Oct 1 08:45:44 2002 +0000 2002-10-01 Roland McGrath <roland@frob.com> * config.h.in (NO_HIDDEN): New #undef. * include/libc-symbols.h [! NO_HIDDEN]: Add this condition to nonempty definitions of hidden_proto et al. * configure.in: Grok --disable-hidden-plt to define NO_HIDDEN. * configure: Regenerated. * sysdeps/mach/hurd/configure.in: Always define NO_HIDDEN. * sysdeps/mach/hurd/configure: Regenerated. I have no idea what it was used for. I think it should be removed. I was hoping the flag would make all intra-libc function calls use the same dynamic linkage mechanisms that are used for functions calling into libc. I would then use LD_PRELOAD mechanisms to wrap (interpose) some functions in libc, and the same mechanisms then intercept both calls into libc as well as calls from within libc. See https://jayconrod.com/posts/23/tutorial-function-interposition-in-linux Yes, there's potential for cycles and catastrophe. I'm interested in mem* and str* functions, which I think would be low risk. (In reply to Robert Henry from comment #3) > I was hoping the flag would make all intra-libc function calls use the same > dynamic linkage mechanisms that are used for functions calling into libc. I > would then use LD_PRELOAD mechanisms to wrap (interpose) some functions in > libc, and the same mechanisms then intercept both calls into libc as well as > calls from within libc. See > https://jayconrod.com/posts/23/tutorial-function-interposition-in-linux > > Yes, there's potential for cycles and catastrophe. I'm interested in mem* > and str* functions, which I think would be low risk. You can add --disable-multi-arch with --disable-hidden-plt. But it may not work. Adding --disable-multi-arch to the configure invocation, when run on an x86_64, does not show the problem with strcat I initially reported. This is progress, I suppose. It does then trip up on the same setrlimit issue I saw on arm64. On x86_64, commenting out line 53 of the commonly-offending file /sysdeps/unix/sysv/linux/setrlimit64.c, and configuring --disable-hidden-plt --disable-multi-arch compiles OK, but when linking build/libc.so fails with many unresolved references to __GI_memset, __GI_memcpy and perhaps more. On ARM64, commenting out line 53 of setrlimit64.c and configuring --disable-hidden-plt, and both with and without --disable-multi-arch, the link of build/elf/ld.so.new fails: /usr/bin/ld: /mnt/robhenry/glibc/2.33/build/elf/librtld.os: in function `_dl_start_user': (.text+0x68): undefined reference to `__GI__dl_argv' /usr/bin/ld: /mnt/robhenry/glibc/2.33/build/elf/librtld.os: relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `__GI__dl_argv' which may bind externally can not be used when making a shared object; recompile with -fPIC (.text+0x68): dangerous relocation: unsupported relocation /usr/bin/ld: (.text+0x6c): undefined reference to `__GI__dl_argv' collect2: error: ld returned 1 exit status Again, my goal is to send all libc-internal (intra-libc) function calls through a PLT. There's some troubling commentary about this goal in sysdeps/aarch64/multiarch/memcpy_generic.S which enigmatically says that "It doesn't make sense to send libc-internal memcpy calls through a PLT" (In reply to Robert Henry from comment #6) > Again, my goal is to send all libc-internal (intra-libc) function calls > through a PLT. There's some troubling commentary about this goal in > sysdeps/aarch64/multiarch/memcpy_generic.S which enigmatically says that "It > doesn't make sense to send libc-internal memcpy calls through a PLT" that comment is mainly for performance reasons. note that calls in the dynamic linker (ld.so) would still not be interposable (that would create cycles e.g. during module loading or lazy symbol resolution. it has its own copy of str*/mem* functions.) and libc internal calls may assume different (stricter) interface contract than the public api (which your interposer does not know about), e.g. memmove may call memcpy if that handles the overlap case so if you only interpose memcpy with the usual api contract that can be an issue (this is not a realistic example since in such case memmove would just be an alias, not doing plt calls). there are also problems about what libc calls are valid to do from a memcpy implementation (even some as-safe apis may not work if they create a cycle). This behavior started at version 2.18, 2.17 can be compiled w/ --disable-hidden-plt, but 2.18 and beyond cannot, (at least not without some significant patching.) See also: commit 5e5b3b886635b52d9baa87414b97965190035e46 Author: Stefan Liebler <stli@linux.vnet.ibm.com> Date: Mon Jun 19 11:06:49 2017 +0200 and commit 9ac3b5047e6bbea03437d020fab9a728e123445b Author: Siddhesh Poyarekar <siddhesh@redhat.com> Date: Thu Apr 4 19:43:56 2013 +0530 The problem revolves around use of the __hidden_ver1 macro, which doesn't protect against --disable-hidden-plt, whereas libc_hidden_def does. |