forked from rpms/glibc
601650f878
* Tue May 31 2022 Arjun Shankar <arjun@redhat.com> - 2.34-35 - Sync with upstream branch release/2.34/master, commit ff450cdbdee0b8cb6b9d653d6d2fa892de29be31: - Fix deadlock when pthread_atfork handler calls pthread_atfork or dlclose - x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ #29127] - string.h: fix __fortified_attr_access macro call [BZ #29162] - linux: Add a getauxval test [BZ #23293] - rtld: Use generic argv adjustment in ld.so [BZ #23293] - S390: Enable static PIE * Thu May 19 2022 Florian Weimer <fweimer@redhat.com> - 2.34-34 - Sync with upstream branch release/2.34/master, commit ede8d94d154157d269b18f3601440ac576c1f96a: - csu: Implement and use _dl_early_allocate during static startup - Linux: Introduce __brk_call for invoking the brk system call - Linux: Implement a useful version of _startup_fatal - ia64: Always define IA64_USE_NEW_STUB as a flag macro - Linux: Define MMAP_CALL_INTERNAL - i386: Honor I386_USE_SYSENTER for 6-argument Linux system calls - i386: Remove OPTIMIZE_FOR_GCC_5 from Linux libc-do-syscall.S - elf: Remove __libc_init_secure - Linux: Consolidate auxiliary vector parsing (redo) - Linux: Include <dl-auxv.h> in dl-sysdep.c only for SHARED - Revert "Linux: Consolidate auxiliary vector parsing" - Linux: Consolidate auxiliary vector parsing - Linux: Assume that NEED_DL_SYSINFO_DSO is always defined - Linux: Remove DL_FIND_ARG_COMPONENTS - Linux: Remove HAVE_AUX_SECURE, HAVE_AUX_XID, HAVE_AUX_PAGESIZE - elf: Merge dl-sysdep.c into the Linux version - elf: Remove unused NEED_DL_BASE_ADDR and _dl_base_addr - x86: Optimize {str|wcs}rchr-evex - x86: Optimize {str|wcs}rchr-avx2 - x86: Optimize {str|wcs}rchr-sse2 - x86: Cleanup page cross code in memcmp-avx2-movbe.S - x86: Remove memcmp-sse4.S - x86: Small improvements for wcslen - x86: Remove AVX str{n}casecmp - x86: Add EVEX optimized str{n}casecmp - x86: Add AVX2 optimized str{n}casecmp - x86: Optimize str{n}casecmp TOLOWER logic in strcmp-sse42.S - x86: Optimize str{n}casecmp TOLOWER logic in strcmp.S - x86: Remove strspn-sse2.S and use the generic implementation - x86: Remove strpbrk-sse2.S and use the generic implementation - x87: Remove strcspn-sse2.S and use the generic implementation - x86: Optimize strspn in strspn-c.c - x86: Optimize strcspn and strpbrk in strcspn-c.c - x86: Code cleanup in strchr-evex and comment justifying branch - x86: Code cleanup in strchr-avx2 and comment justifying branch - x86_64: Remove bcopy optimizations - x86-64: Remove bzero weak alias in SS2 memset - x86_64/multiarch: Sort sysdep_routines and put one entry per line - x86: Improve L to support L(XXX_SYMBOL (YYY, ZZZ)) - fortify: Ensure that __glibc_fortify condition is a constant [BZ #29141] * Thu May 12 2022 Florian Weimer <fweimer@redhat.com> - 2.34-33 - Sync with upstream branch release/2.34/master, commit 91c2e6c3db44297bf4cb3a2e3c40236c5b6a0b23: - dlfcn: Implement the RTLD_DI_PHDR request type for dlinfo - manual: Document the dlinfo function - x86: Fix fallback for wcsncmp_avx2 in strcmp-avx2.S [BZ #28896] - x86: Fix bug in strncmp-evex and strncmp-avx2 [BZ #28895] - x86: Set .text section in memset-vec-unaligned-erms - x86-64: Optimize bzero - x86: Remove SSSE3 instruction for broadcast in memset.S (SSE2 Only) - x86: Improve vec generation in memset-vec-unaligned-erms.S - x86-64: Fix strcmp-evex.S - x86-64: Fix strcmp-avx2.S - x86: Optimize strcmp-evex.S - x86: Optimize strcmp-avx2.S - manual: Clarify that abbreviations of long options are allowed - Add HWCAP2_AFP, HWCAP2_RPRES from Linux 5.17 to AArch64 bits/hwcap.h - aarch64: Add HWCAP2_ECV from Linux 5.16 - Add SOL_MPTCP, SOL_MCTP from Linux 5.16 to bits/socket.h - Update kernel version to 5.17 in tst-mman-consts.py - Update kernel version to 5.16 in tst-mman-consts.py - Update syscall lists for Linux 5.17 - Add ARPHRD_CAN, ARPHRD_MCTP to net/if_arp.h - Update kernel version to 5.15 in tst-mman-consts.py - Add PF_MCTP, AF_MCTP from Linux 5.15 to bits/socket.h Resolves: #2091541
752 lines
23 KiB
Diff
752 lines
23 KiB
Diff
commit b0bd6a1323c3eccd16c45bae359a76877fa75639
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Thu May 19 11:43:53 2022 +0200
|
|
|
|
elf: Merge dl-sysdep.c into the Linux version
|
|
|
|
The generic version is the de-facto Linux implementation. It
|
|
requires an auxiliary vector, so Hurd does not use it.
|
|
|
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
(cherry picked from commit 91c0a47ffb66e7cd802de870686465db3b3976a0)
|
|
|
|
Conflicts:
|
|
elf/dl-sysdep.c
|
|
(missing ld.so dependency sorting optimization upstream)
|
|
|
|
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
|
|
index 1c78dc89c9cbe54d..7aa90ad6eeb35cad 100644
|
|
--- a/elf/dl-sysdep.c
|
|
+++ b/elf/dl-sysdep.c
|
|
@@ -1,5 +1,5 @@
|
|
-/* Operating system support for run-time dynamic linker. Generic Unix version.
|
|
- Copyright (C) 1995-2021 Free Software Foundation, Inc.
|
|
+/* Operating system support for run-time dynamic linker. Stub version.
|
|
+ Copyright (C) 1995-2022 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
|
|
@@ -16,352 +16,4 @@
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
-/* We conditionalize the whole of this file rather than simply eliding it
|
|
- from the static build, because other sysdeps/ versions of this file
|
|
- might define things needed by a static build. */
|
|
-
|
|
-#ifdef SHARED
|
|
-
|
|
-#include <assert.h>
|
|
-#include <elf.h>
|
|
-#include <errno.h>
|
|
-#include <fcntl.h>
|
|
-#include <libintl.h>
|
|
-#include <stdlib.h>
|
|
-#include <string.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
-#include <sys/mman.h>
|
|
-#include <ldsodefs.h>
|
|
-#include <_itoa.h>
|
|
-#include <fpu_control.h>
|
|
-
|
|
-#include <entry.h>
|
|
-#include <dl-machine.h>
|
|
-#include <dl-procinfo.h>
|
|
-#include <dl-osinfo.h>
|
|
-#include <libc-internal.h>
|
|
-#include <tls.h>
|
|
-
|
|
-#include <dl-tunables.h>
|
|
-#include <dl-auxv.h>
|
|
-#include <dl-hwcap-check.h>
|
|
-
|
|
-extern char **_environ attribute_hidden;
|
|
-extern char _end[] attribute_hidden;
|
|
-
|
|
-/* Protect SUID program against misuse of file descriptors. */
|
|
-extern void __libc_check_standard_fds (void);
|
|
-
|
|
-int __libc_enable_secure attribute_relro = 0;
|
|
-rtld_hidden_data_def (__libc_enable_secure)
|
|
-/* This variable contains the lowest stack address ever used. */
|
|
-void *__libc_stack_end attribute_relro = NULL;
|
|
-rtld_hidden_data_def(__libc_stack_end)
|
|
-void *_dl_random attribute_relro = NULL;
|
|
-
|
|
-#ifndef DL_FIND_ARG_COMPONENTS
|
|
-# define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
|
|
- do { \
|
|
- void **_tmp; \
|
|
- (argc) = *(long int *) cookie; \
|
|
- (argv) = (char **) ((long int *) cookie + 1); \
|
|
- (envp) = (argv) + (argc) + 1; \
|
|
- for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
|
|
- continue; \
|
|
- (auxp) = (void *) ++_tmp; \
|
|
- } while (0)
|
|
-#endif
|
|
-
|
|
-#ifndef DL_STACK_END
|
|
-# define DL_STACK_END(cookie) ((void *) (cookie))
|
|
-#endif
|
|
-
|
|
-ElfW(Addr)
|
|
-_dl_sysdep_start (void **start_argptr,
|
|
- void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
|
|
- ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
|
|
-{
|
|
- const ElfW(Phdr) *phdr = NULL;
|
|
- ElfW(Word) phnum = 0;
|
|
- ElfW(Addr) user_entry;
|
|
- ElfW(auxv_t) *av;
|
|
-#ifdef HAVE_AUX_SECURE
|
|
-# define set_seen(tag) (tag) /* Evaluate for the side effects. */
|
|
-# define set_seen_secure() ((void) 0)
|
|
-#else
|
|
- uid_t uid = 0;
|
|
- gid_t gid = 0;
|
|
- unsigned int seen = 0;
|
|
-# define set_seen_secure() (seen = -1)
|
|
-# ifdef HAVE_AUX_XID
|
|
-# define set_seen(tag) (tag) /* Evaluate for the side effects. */
|
|
-# else
|
|
-# define M(type) (1 << (type))
|
|
-# define set_seen(tag) seen |= M ((tag)->a_type)
|
|
-# endif
|
|
-#endif
|
|
-#ifdef NEED_DL_SYSINFO
|
|
- uintptr_t new_sysinfo = 0;
|
|
-#endif
|
|
-
|
|
- __libc_stack_end = DL_STACK_END (start_argptr);
|
|
- DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
|
|
- GLRO(dl_auxv));
|
|
-
|
|
- user_entry = (ElfW(Addr)) ENTRY_POINT;
|
|
- GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */
|
|
-
|
|
- /* NB: Default to a constant CONSTANT_MINSIGSTKSZ. */
|
|
- _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
|
|
- "CONSTANT_MINSIGSTKSZ is constant");
|
|
- GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
|
|
-
|
|
- for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
|
|
- switch (av->a_type)
|
|
- {
|
|
- case AT_PHDR:
|
|
- phdr = (void *) av->a_un.a_val;
|
|
- break;
|
|
- case AT_PHNUM:
|
|
- phnum = av->a_un.a_val;
|
|
- break;
|
|
- case AT_PAGESZ:
|
|
- GLRO(dl_pagesize) = av->a_un.a_val;
|
|
- break;
|
|
- case AT_ENTRY:
|
|
- user_entry = av->a_un.a_val;
|
|
- break;
|
|
-#ifndef HAVE_AUX_SECURE
|
|
- case AT_UID:
|
|
- case AT_EUID:
|
|
- uid ^= av->a_un.a_val;
|
|
- break;
|
|
- case AT_GID:
|
|
- case AT_EGID:
|
|
- gid ^= av->a_un.a_val;
|
|
- break;
|
|
-#endif
|
|
- case AT_SECURE:
|
|
-#ifndef HAVE_AUX_SECURE
|
|
- seen = -1;
|
|
-#endif
|
|
- __libc_enable_secure = av->a_un.a_val;
|
|
- break;
|
|
- case AT_PLATFORM:
|
|
- GLRO(dl_platform) = (void *) av->a_un.a_val;
|
|
- break;
|
|
- case AT_HWCAP:
|
|
- GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
|
|
- break;
|
|
- case AT_HWCAP2:
|
|
- GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
|
|
- break;
|
|
- case AT_CLKTCK:
|
|
- GLRO(dl_clktck) = av->a_un.a_val;
|
|
- break;
|
|
- case AT_FPUCW:
|
|
- GLRO(dl_fpu_control) = av->a_un.a_val;
|
|
- break;
|
|
-#ifdef NEED_DL_SYSINFO
|
|
- case AT_SYSINFO:
|
|
- new_sysinfo = av->a_un.a_val;
|
|
- break;
|
|
-#endif
|
|
-#ifdef NEED_DL_SYSINFO_DSO
|
|
- case AT_SYSINFO_EHDR:
|
|
- GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
|
|
- break;
|
|
-#endif
|
|
- case AT_RANDOM:
|
|
- _dl_random = (void *) av->a_un.a_val;
|
|
- break;
|
|
- case AT_MINSIGSTKSZ:
|
|
- GLRO(dl_minsigstacksize) = av->a_un.a_val;
|
|
- break;
|
|
- DL_PLATFORM_AUXV
|
|
- }
|
|
-
|
|
- dl_hwcap_check ();
|
|
-
|
|
-#ifndef HAVE_AUX_SECURE
|
|
- if (seen != -1)
|
|
- {
|
|
- /* Fill in the values we have not gotten from the kernel through the
|
|
- auxiliary vector. */
|
|
-# ifndef HAVE_AUX_XID
|
|
-# define SEE(UID, var, uid) \
|
|
- if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
|
|
- SEE (UID, uid, uid);
|
|
- SEE (EUID, uid, euid);
|
|
- SEE (GID, gid, gid);
|
|
- SEE (EGID, gid, egid);
|
|
-# endif
|
|
-
|
|
- /* If one of the two pairs of IDs does not match this is a setuid
|
|
- or setgid run. */
|
|
- __libc_enable_secure = uid | gid;
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifndef HAVE_AUX_PAGESIZE
|
|
- if (GLRO(dl_pagesize) == 0)
|
|
- GLRO(dl_pagesize) = __getpagesize ();
|
|
-#endif
|
|
-
|
|
-#ifdef NEED_DL_SYSINFO
|
|
- if (new_sysinfo != 0)
|
|
- {
|
|
-# ifdef NEED_DL_SYSINFO_DSO
|
|
- /* Only set the sysinfo value if we also have the vsyscall DSO. */
|
|
- if (GLRO(dl_sysinfo_dso) != 0)
|
|
-# endif
|
|
- GLRO(dl_sysinfo) = new_sysinfo;
|
|
- }
|
|
-#endif
|
|
-
|
|
- __tunables_init (_environ);
|
|
-
|
|
- /* Initialize DSO sorting algorithm after tunables. */
|
|
- _dl_sort_maps_init ();
|
|
-
|
|
-#ifdef DL_SYSDEP_INIT
|
|
- DL_SYSDEP_INIT;
|
|
-#endif
|
|
-
|
|
-#ifdef DL_PLATFORM_INIT
|
|
- DL_PLATFORM_INIT;
|
|
-#endif
|
|
-
|
|
- /* Determine the length of the platform name. */
|
|
- if (GLRO(dl_platform) != NULL)
|
|
- GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
|
|
-
|
|
- if (__sbrk (0) == _end)
|
|
- /* The dynamic linker was run as a program, and so the initial break
|
|
- starts just after our bss, at &_end. The malloc in dl-minimal.c
|
|
- will consume the rest of this page, so tell the kernel to move the
|
|
- break up that far. When the user program examines its break, it
|
|
- will see this new value and not clobber our data. */
|
|
- __sbrk (GLRO(dl_pagesize)
|
|
- - ((_end - (char *) 0) & (GLRO(dl_pagesize) - 1)));
|
|
-
|
|
- /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
|
|
- allocated. If necessary we are doing it ourself. If it is not
|
|
- possible we stop the program. */
|
|
- if (__builtin_expect (__libc_enable_secure, 0))
|
|
- __libc_check_standard_fds ();
|
|
-
|
|
- (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
|
|
- return user_entry;
|
|
-}
|
|
-
|
|
-void
|
|
-_dl_sysdep_start_cleanup (void)
|
|
-{
|
|
-}
|
|
-
|
|
-void
|
|
-_dl_show_auxv (void)
|
|
-{
|
|
- char buf[64];
|
|
- ElfW(auxv_t) *av;
|
|
-
|
|
- /* Terminate string. */
|
|
- buf[63] = '\0';
|
|
-
|
|
- /* The following code assumes that the AT_* values are encoded
|
|
- starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
|
|
- close by (otherwise the array will be too large). In case we have
|
|
- to support a platform where these requirements are not fulfilled
|
|
- some alternative implementation has to be used. */
|
|
- for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
|
|
- {
|
|
- static const struct
|
|
- {
|
|
- const char label[22];
|
|
- enum { unknown = 0, dec, hex, str, ignore } form : 8;
|
|
- } auxvars[] =
|
|
- {
|
|
- [AT_EXECFD - 2] = { "EXECFD: ", dec },
|
|
- [AT_EXECFN - 2] = { "EXECFN: ", str },
|
|
- [AT_PHDR - 2] = { "PHDR: 0x", hex },
|
|
- [AT_PHENT - 2] = { "PHENT: ", dec },
|
|
- [AT_PHNUM - 2] = { "PHNUM: ", dec },
|
|
- [AT_PAGESZ - 2] = { "PAGESZ: ", dec },
|
|
- [AT_BASE - 2] = { "BASE: 0x", hex },
|
|
- [AT_FLAGS - 2] = { "FLAGS: 0x", hex },
|
|
- [AT_ENTRY - 2] = { "ENTRY: 0x", hex },
|
|
- [AT_NOTELF - 2] = { "NOTELF: ", hex },
|
|
- [AT_UID - 2] = { "UID: ", dec },
|
|
- [AT_EUID - 2] = { "EUID: ", dec },
|
|
- [AT_GID - 2] = { "GID: ", dec },
|
|
- [AT_EGID - 2] = { "EGID: ", dec },
|
|
- [AT_PLATFORM - 2] = { "PLATFORM: ", str },
|
|
- [AT_HWCAP - 2] = { "HWCAP: ", hex },
|
|
- [AT_CLKTCK - 2] = { "CLKTCK: ", dec },
|
|
- [AT_FPUCW - 2] = { "FPUCW: ", hex },
|
|
- [AT_DCACHEBSIZE - 2] = { "DCACHEBSIZE: 0x", hex },
|
|
- [AT_ICACHEBSIZE - 2] = { "ICACHEBSIZE: 0x", hex },
|
|
- [AT_UCACHEBSIZE - 2] = { "UCACHEBSIZE: 0x", hex },
|
|
- [AT_IGNOREPPC - 2] = { "IGNOREPPC", ignore },
|
|
- [AT_SECURE - 2] = { "SECURE: ", dec },
|
|
- [AT_BASE_PLATFORM - 2] = { "BASE_PLATFORM: ", str },
|
|
- [AT_SYSINFO - 2] = { "SYSINFO: 0x", hex },
|
|
- [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex },
|
|
- [AT_RANDOM - 2] = { "RANDOM: 0x", hex },
|
|
- [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex },
|
|
- [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec },
|
|
- [AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec },
|
|
- [AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex },
|
|
- [AT_L1D_CACHESIZE - 2] = { "L1D_CACHESIZE: ", dec },
|
|
- [AT_L1D_CACHEGEOMETRY - 2] = { "L1D_CACHEGEOMETRY: 0x", hex },
|
|
- [AT_L2_CACHESIZE - 2] = { "L2_CACHESIZE: ", dec },
|
|
- [AT_L2_CACHEGEOMETRY - 2] = { "L2_CACHEGEOMETRY: 0x", hex },
|
|
- [AT_L3_CACHESIZE - 2] = { "L3_CACHESIZE: ", dec },
|
|
- [AT_L3_CACHEGEOMETRY - 2] = { "L3_CACHEGEOMETRY: 0x", hex },
|
|
- };
|
|
- unsigned int idx = (unsigned int) (av->a_type - 2);
|
|
-
|
|
- if ((unsigned int) av->a_type < 2u
|
|
- || (idx < sizeof (auxvars) / sizeof (auxvars[0])
|
|
- && auxvars[idx].form == ignore))
|
|
- continue;
|
|
-
|
|
- assert (AT_NULL == 0);
|
|
- assert (AT_IGNORE == 1);
|
|
-
|
|
- /* Some entries are handled in a special way per platform. */
|
|
- if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
|
|
- continue;
|
|
-
|
|
- if (idx < sizeof (auxvars) / sizeof (auxvars[0])
|
|
- && auxvars[idx].form != unknown)
|
|
- {
|
|
- const char *val = (char *) av->a_un.a_val;
|
|
-
|
|
- if (__builtin_expect (auxvars[idx].form, dec) == dec)
|
|
- val = _itoa ((unsigned long int) av->a_un.a_val,
|
|
- buf + sizeof buf - 1, 10, 0);
|
|
- else if (__builtin_expect (auxvars[idx].form, hex) == hex)
|
|
- val = _itoa ((unsigned long int) av->a_un.a_val,
|
|
- buf + sizeof buf - 1, 16, 0);
|
|
-
|
|
- _dl_printf ("AT_%s%s\n", auxvars[idx].label, val);
|
|
-
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* Unknown value: print a generic line. */
|
|
- char buf2[17];
|
|
- buf2[sizeof (buf2) - 1] = '\0';
|
|
- const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
|
|
- buf2 + sizeof buf2 - 1, 16, 0);
|
|
- const char *val = _itoa ((unsigned long int) av->a_type,
|
|
- buf + sizeof buf - 1, 16, 0);
|
|
- _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
|
|
- }
|
|
-}
|
|
-
|
|
-#endif
|
|
+#error dl-sysdep support missing.
|
|
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
|
|
index 144dc5ce5a1bba17..3e41469bcc395179 100644
|
|
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
|
|
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
|
|
@@ -16,29 +16,352 @@
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
-/* Linux needs some special initialization, but otherwise uses
|
|
- the generic dynamic linker system interface code. */
|
|
-
|
|
-#include <string.h>
|
|
+#include <_itoa.h>
|
|
+#include <assert.h>
|
|
+#include <dl-auxv.h>
|
|
+#include <dl-hwcap-check.h>
|
|
+#include <dl-osinfo.h>
|
|
+#include <dl-procinfo.h>
|
|
+#include <dl-tunables.h>
|
|
+#include <elf.h>
|
|
+#include <entry.h>
|
|
+#include <errno.h>
|
|
#include <fcntl.h>
|
|
-#include <unistd.h>
|
|
-#include <sys/param.h>
|
|
-#include <sys/utsname.h>
|
|
+#include <fpu_control.h>
|
|
#include <ldsodefs.h>
|
|
+#include <libc-internal.h>
|
|
+#include <libintl.h>
|
|
#include <not-cancel.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <string.h>
|
|
+#include <sys/mman.h>
|
|
+#include <sys/param.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/utsname.h>
|
|
+#include <tls.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+#include <dl-machine.h>
|
|
|
|
#ifdef SHARED
|
|
-# define DL_SYSDEP_INIT frob_brk ()
|
|
+extern char **_environ attribute_hidden;
|
|
+extern char _end[] attribute_hidden;
|
|
+
|
|
+/* Protect SUID program against misuse of file descriptors. */
|
|
+extern void __libc_check_standard_fds (void);
|
|
|
|
-static inline void
|
|
-frob_brk (void)
|
|
+int __libc_enable_secure attribute_relro = 0;
|
|
+rtld_hidden_data_def (__libc_enable_secure)
|
|
+/* This variable contains the lowest stack address ever used. */
|
|
+void *__libc_stack_end attribute_relro = NULL;
|
|
+rtld_hidden_data_def(__libc_stack_end)
|
|
+void *_dl_random attribute_relro = NULL;
|
|
+
|
|
+#ifndef DL_FIND_ARG_COMPONENTS
|
|
+# define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp) \
|
|
+ do { \
|
|
+ void **_tmp; \
|
|
+ (argc) = *(long int *) cookie; \
|
|
+ (argv) = (char **) ((long int *) cookie + 1); \
|
|
+ (envp) = (argv) + (argc) + 1; \
|
|
+ for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
|
|
+ continue; \
|
|
+ (auxp) = (void *) ++_tmp; \
|
|
+ } while (0)
|
|
+#endif
|
|
+
|
|
+#ifndef DL_STACK_END
|
|
+# define DL_STACK_END(cookie) ((void *) (cookie))
|
|
+#endif
|
|
+
|
|
+ElfW(Addr)
|
|
+_dl_sysdep_start (void **start_argptr,
|
|
+ void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
|
|
+ ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
|
|
{
|
|
+ const ElfW(Phdr) *phdr = NULL;
|
|
+ ElfW(Word) phnum = 0;
|
|
+ ElfW(Addr) user_entry;
|
|
+ ElfW(auxv_t) *av;
|
|
+#ifdef HAVE_AUX_SECURE
|
|
+# define set_seen(tag) (tag) /* Evaluate for the side effects. */
|
|
+# define set_seen_secure() ((void) 0)
|
|
+#else
|
|
+ uid_t uid = 0;
|
|
+ gid_t gid = 0;
|
|
+ unsigned int seen = 0;
|
|
+# define set_seen_secure() (seen = -1)
|
|
+# ifdef HAVE_AUX_XID
|
|
+# define set_seen(tag) (tag) /* Evaluate for the side effects. */
|
|
+# else
|
|
+# define M(type) (1 << (type))
|
|
+# define set_seen(tag) seen |= M ((tag)->a_type)
|
|
+# endif
|
|
+#endif
|
|
+#ifdef NEED_DL_SYSINFO
|
|
+ uintptr_t new_sysinfo = 0;
|
|
+#endif
|
|
+
|
|
+ __libc_stack_end = DL_STACK_END (start_argptr);
|
|
+ DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, _dl_argv, _environ,
|
|
+ GLRO(dl_auxv));
|
|
+
|
|
+ user_entry = (ElfW(Addr)) ENTRY_POINT;
|
|
+ GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */
|
|
+
|
|
+ /* NB: Default to a constant CONSTANT_MINSIGSTKSZ. */
|
|
+ _Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
|
|
+ "CONSTANT_MINSIGSTKSZ is constant");
|
|
+ GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
|
|
+
|
|
+ for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
|
|
+ switch (av->a_type)
|
|
+ {
|
|
+ case AT_PHDR:
|
|
+ phdr = (void *) av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_PHNUM:
|
|
+ phnum = av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_PAGESZ:
|
|
+ GLRO(dl_pagesize) = av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_ENTRY:
|
|
+ user_entry = av->a_un.a_val;
|
|
+ break;
|
|
+#ifndef HAVE_AUX_SECURE
|
|
+ case AT_UID:
|
|
+ case AT_EUID:
|
|
+ uid ^= av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_GID:
|
|
+ case AT_EGID:
|
|
+ gid ^= av->a_un.a_val;
|
|
+ break;
|
|
+#endif
|
|
+ case AT_SECURE:
|
|
+#ifndef HAVE_AUX_SECURE
|
|
+ seen = -1;
|
|
+#endif
|
|
+ __libc_enable_secure = av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_PLATFORM:
|
|
+ GLRO(dl_platform) = (void *) av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_HWCAP:
|
|
+ GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_HWCAP2:
|
|
+ GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_CLKTCK:
|
|
+ GLRO(dl_clktck) = av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_FPUCW:
|
|
+ GLRO(dl_fpu_control) = av->a_un.a_val;
|
|
+ break;
|
|
+#ifdef NEED_DL_SYSINFO
|
|
+ case AT_SYSINFO:
|
|
+ new_sysinfo = av->a_un.a_val;
|
|
+ break;
|
|
+#endif
|
|
+#ifdef NEED_DL_SYSINFO_DSO
|
|
+ case AT_SYSINFO_EHDR:
|
|
+ GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
|
|
+ break;
|
|
+#endif
|
|
+ case AT_RANDOM:
|
|
+ _dl_random = (void *) av->a_un.a_val;
|
|
+ break;
|
|
+ case AT_MINSIGSTKSZ:
|
|
+ GLRO(dl_minsigstacksize) = av->a_un.a_val;
|
|
+ break;
|
|
+ DL_PLATFORM_AUXV
|
|
+ }
|
|
+
|
|
+ dl_hwcap_check ();
|
|
+
|
|
+#ifndef HAVE_AUX_SECURE
|
|
+ if (seen != -1)
|
|
+ {
|
|
+ /* Fill in the values we have not gotten from the kernel through the
|
|
+ auxiliary vector. */
|
|
+# ifndef HAVE_AUX_XID
|
|
+# define SEE(UID, var, uid) \
|
|
+ if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
|
|
+ SEE (UID, uid, uid);
|
|
+ SEE (EUID, uid, euid);
|
|
+ SEE (GID, gid, gid);
|
|
+ SEE (EGID, gid, egid);
|
|
+# endif
|
|
+
|
|
+ /* If one of the two pairs of IDs does not match this is a setuid
|
|
+ or setgid run. */
|
|
+ __libc_enable_secure = uid | gid;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#ifndef HAVE_AUX_PAGESIZE
|
|
+ if (GLRO(dl_pagesize) == 0)
|
|
+ GLRO(dl_pagesize) = __getpagesize ();
|
|
+#endif
|
|
+
|
|
+#ifdef NEED_DL_SYSINFO
|
|
+ if (new_sysinfo != 0)
|
|
+ {
|
|
+# ifdef NEED_DL_SYSINFO_DSO
|
|
+ /* Only set the sysinfo value if we also have the vsyscall DSO. */
|
|
+ if (GLRO(dl_sysinfo_dso) != 0)
|
|
+# endif
|
|
+ GLRO(dl_sysinfo) = new_sysinfo;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ __tunables_init (_environ);
|
|
+
|
|
+ /* Initialize DSO sorting algorithm after tunables. */
|
|
+ _dl_sort_maps_init ();
|
|
+
|
|
__brk (0); /* Initialize the break. */
|
|
-}
|
|
|
|
-# include <elf/dl-sysdep.c>
|
|
+#ifdef DL_PLATFORM_INIT
|
|
+ DL_PLATFORM_INIT;
|
|
#endif
|
|
|
|
+ /* Determine the length of the platform name. */
|
|
+ if (GLRO(dl_platform) != NULL)
|
|
+ GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
|
|
+
|
|
+ if (__sbrk (0) == _end)
|
|
+ /* The dynamic linker was run as a program, and so the initial break
|
|
+ starts just after our bss, at &_end. The malloc in dl-minimal.c
|
|
+ will consume the rest of this page, so tell the kernel to move the
|
|
+ break up that far. When the user program examines its break, it
|
|
+ will see this new value and not clobber our data. */
|
|
+ __sbrk (GLRO(dl_pagesize)
|
|
+ - ((_end - (char *) 0) & (GLRO(dl_pagesize) - 1)));
|
|
+
|
|
+ /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
|
|
+ allocated. If necessary we are doing it ourself. If it is not
|
|
+ possible we stop the program. */
|
|
+ if (__builtin_expect (__libc_enable_secure, 0))
|
|
+ __libc_check_standard_fds ();
|
|
+
|
|
+ (*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
|
|
+ return user_entry;
|
|
+}
|
|
+
|
|
+void
|
|
+_dl_sysdep_start_cleanup (void)
|
|
+{
|
|
+}
|
|
+
|
|
+void
|
|
+_dl_show_auxv (void)
|
|
+{
|
|
+ char buf[64];
|
|
+ ElfW(auxv_t) *av;
|
|
+
|
|
+ /* Terminate string. */
|
|
+ buf[63] = '\0';
|
|
+
|
|
+ /* The following code assumes that the AT_* values are encoded
|
|
+ starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
|
|
+ close by (otherwise the array will be too large). In case we have
|
|
+ to support a platform where these requirements are not fulfilled
|
|
+ some alternative implementation has to be used. */
|
|
+ for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
|
|
+ {
|
|
+ static const struct
|
|
+ {
|
|
+ const char label[22];
|
|
+ enum { unknown = 0, dec, hex, str, ignore } form : 8;
|
|
+ } auxvars[] =
|
|
+ {
|
|
+ [AT_EXECFD - 2] = { "EXECFD: ", dec },
|
|
+ [AT_EXECFN - 2] = { "EXECFN: ", str },
|
|
+ [AT_PHDR - 2] = { "PHDR: 0x", hex },
|
|
+ [AT_PHENT - 2] = { "PHENT: ", dec },
|
|
+ [AT_PHNUM - 2] = { "PHNUM: ", dec },
|
|
+ [AT_PAGESZ - 2] = { "PAGESZ: ", dec },
|
|
+ [AT_BASE - 2] = { "BASE: 0x", hex },
|
|
+ [AT_FLAGS - 2] = { "FLAGS: 0x", hex },
|
|
+ [AT_ENTRY - 2] = { "ENTRY: 0x", hex },
|
|
+ [AT_NOTELF - 2] = { "NOTELF: ", hex },
|
|
+ [AT_UID - 2] = { "UID: ", dec },
|
|
+ [AT_EUID - 2] = { "EUID: ", dec },
|
|
+ [AT_GID - 2] = { "GID: ", dec },
|
|
+ [AT_EGID - 2] = { "EGID: ", dec },
|
|
+ [AT_PLATFORM - 2] = { "PLATFORM: ", str },
|
|
+ [AT_HWCAP - 2] = { "HWCAP: ", hex },
|
|
+ [AT_CLKTCK - 2] = { "CLKTCK: ", dec },
|
|
+ [AT_FPUCW - 2] = { "FPUCW: ", hex },
|
|
+ [AT_DCACHEBSIZE - 2] = { "DCACHEBSIZE: 0x", hex },
|
|
+ [AT_ICACHEBSIZE - 2] = { "ICACHEBSIZE: 0x", hex },
|
|
+ [AT_UCACHEBSIZE - 2] = { "UCACHEBSIZE: 0x", hex },
|
|
+ [AT_IGNOREPPC - 2] = { "IGNOREPPC", ignore },
|
|
+ [AT_SECURE - 2] = { "SECURE: ", dec },
|
|
+ [AT_BASE_PLATFORM - 2] = { "BASE_PLATFORM: ", str },
|
|
+ [AT_SYSINFO - 2] = { "SYSINFO: 0x", hex },
|
|
+ [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex },
|
|
+ [AT_RANDOM - 2] = { "RANDOM: 0x", hex },
|
|
+ [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex },
|
|
+ [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec },
|
|
+ [AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec },
|
|
+ [AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex },
|
|
+ [AT_L1D_CACHESIZE - 2] = { "L1D_CACHESIZE: ", dec },
|
|
+ [AT_L1D_CACHEGEOMETRY - 2] = { "L1D_CACHEGEOMETRY: 0x", hex },
|
|
+ [AT_L2_CACHESIZE - 2] = { "L2_CACHESIZE: ", dec },
|
|
+ [AT_L2_CACHEGEOMETRY - 2] = { "L2_CACHEGEOMETRY: 0x", hex },
|
|
+ [AT_L3_CACHESIZE - 2] = { "L3_CACHESIZE: ", dec },
|
|
+ [AT_L3_CACHEGEOMETRY - 2] = { "L3_CACHEGEOMETRY: 0x", hex },
|
|
+ };
|
|
+ unsigned int idx = (unsigned int) (av->a_type - 2);
|
|
+
|
|
+ if ((unsigned int) av->a_type < 2u
|
|
+ || (idx < sizeof (auxvars) / sizeof (auxvars[0])
|
|
+ && auxvars[idx].form == ignore))
|
|
+ continue;
|
|
+
|
|
+ assert (AT_NULL == 0);
|
|
+ assert (AT_IGNORE == 1);
|
|
+
|
|
+ /* Some entries are handled in a special way per platform. */
|
|
+ if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
|
|
+ continue;
|
|
+
|
|
+ if (idx < sizeof (auxvars) / sizeof (auxvars[0])
|
|
+ && auxvars[idx].form != unknown)
|
|
+ {
|
|
+ const char *val = (char *) av->a_un.a_val;
|
|
+
|
|
+ if (__builtin_expect (auxvars[idx].form, dec) == dec)
|
|
+ val = _itoa ((unsigned long int) av->a_un.a_val,
|
|
+ buf + sizeof buf - 1, 10, 0);
|
|
+ else if (__builtin_expect (auxvars[idx].form, hex) == hex)
|
|
+ val = _itoa ((unsigned long int) av->a_un.a_val,
|
|
+ buf + sizeof buf - 1, 16, 0);
|
|
+
|
|
+ _dl_printf ("AT_%s%s\n", auxvars[idx].label, val);
|
|
+
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* Unknown value: print a generic line. */
|
|
+ char buf2[17];
|
|
+ buf2[sizeof (buf2) - 1] = '\0';
|
|
+ const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
|
|
+ buf2 + sizeof buf2 - 1, 16, 0);
|
|
+ const char *val = _itoa ((unsigned long int) av->a_type,
|
|
+ buf + sizeof buf - 1, 16, 0);
|
|
+ _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
|
|
+ }
|
|
+}
|
|
+
|
|
+#endif /* SHARED */
|
|
+
|
|
|
|
int
|
|
attribute_hidden
|