mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
156
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
529cfa039a | ||
|
|
b7f913c052 | ||
|
|
1d1466e7c4 | ||
|
|
e798a21fef | ||
|
|
faedaa0f9a | ||
|
|
b8d11f9551 | ||
|
|
6c5ae75031 | ||
|
|
e206033c27 | ||
|
|
3723319805 | ||
|
|
09c5dcf73b | ||
|
|
696f66660b | ||
|
|
d04bba58a2 | ||
|
|
e6e3d4cd26 | ||
|
|
416fbda1c1 | ||
|
|
5e7f59255b | ||
|
|
2e1f6346b6 | ||
|
|
59da7f4ccb | ||
|
|
737eb83549 | ||
|
|
e135c4a918 | ||
|
|
41348211d4 | ||
|
|
ef2c249cbd | ||
|
|
87bb97efa2 | ||
|
|
d53b9cc391 | ||
|
|
738ee53f0c | ||
|
|
224d8c1890 | ||
|
|
f8c2f620f1 | ||
|
|
d6a58bd81d | ||
|
|
10f7bdebe5 | ||
|
|
98ea9372cc | ||
|
|
536910724d | ||
|
|
0e6ebf06e4 | ||
|
|
c82bdf033f | ||
|
|
54b1273395 | ||
|
|
b53f0c11de | ||
|
|
b5032c3d37 | ||
|
|
6c9c230765 | ||
|
|
40fc6a74ee | ||
|
|
f610d2935f | ||
|
|
c6f9085ee4 | ||
|
|
3be79b72d5 | ||
|
|
852361b5a3 | ||
|
|
d5d1c95aaf | ||
|
|
15b00d2af0 | ||
|
|
d093b677c3 | ||
|
|
38e0d24794 | ||
|
|
04d60ce0f2 | ||
|
|
007e054d78 | ||
|
|
d64b08d5ba | ||
|
|
0351c75c5f | ||
|
|
6eaf10cbb7 | ||
|
|
d8302ba2da | ||
|
|
ad615b59c7 | ||
|
|
05c83ccaf5 | ||
|
|
008003dc6e | ||
|
|
489d0b8b32 | ||
|
|
e098446037 | ||
|
|
e09e7b1492 | ||
|
|
aa601d0244 | ||
|
|
b952c25dc7 | ||
|
|
948ebc098e | ||
|
|
de6cdd6875 | ||
|
|
511b244cc5 | ||
|
|
31186e2cb7 | ||
|
|
72123e1b56 | ||
|
|
08beb3a3f4 | ||
|
|
b50d5b746c | ||
|
|
1b9cd6a721 | ||
|
|
3438bbca90 | ||
|
|
d084965adc | ||
|
|
472e799a5f | ||
|
|
8c8a71c85f | ||
|
|
f7a79879c0 | ||
|
|
73c362840c | ||
|
|
269eb9d930 | ||
|
|
062ff490c1 | ||
|
|
82b1acd9de | ||
|
|
1d401d1fcc | ||
|
|
6890b8a3ae | ||
|
|
1081f1d3dd | ||
|
|
7b5d433fd0 | ||
|
|
5575daae50 | ||
|
|
03e6e02e6a | ||
|
|
705f1e4606 | ||
|
|
2fe2af88ab | ||
|
|
73558ffe84 | ||
|
|
e64235ff42 | ||
|
|
d5ba02f67d | ||
|
|
85b24f9694 | ||
|
|
515a6f53cd | ||
|
|
217b84127b | ||
|
|
41fddc064d | ||
|
|
8ad6d6d8ed | ||
|
|
1d9764aba8 | ||
|
|
e94544c82f | ||
|
|
4029747c59 | ||
|
|
aa3a97496c | ||
|
|
9de8011c32 | ||
|
|
5daf13b1e6 | ||
|
|
03de6917bd | ||
|
|
dc9b69d533 | ||
|
|
93aabf891e | ||
|
|
4db172a54d | ||
|
|
7af07fe795 | ||
|
|
0686586515 | ||
|
|
1fe4b8d693 | ||
|
|
0dcbf4c870 | ||
|
|
e9f81c261a | ||
|
|
387bff63dc | ||
|
|
f988b7f228 | ||
|
|
bfe68fe3c4 | ||
|
|
a4f3bc2346 | ||
|
|
cf8c6a634c | ||
|
|
f411207a83 | ||
|
|
6548a9bdba | ||
|
|
5f36e5c701 | ||
|
|
f42373f911 | ||
|
|
01bffc013c | ||
|
|
024a7640ab | ||
|
|
cb9b8b5d76 | ||
|
|
76843f3b3e | ||
|
|
79528414dc | ||
|
|
cb44a620ef | ||
|
|
558168c78e | ||
|
|
a996d13b8a | ||
|
|
80a009119b | ||
|
|
822662cf2a | ||
|
|
cda99af14e | ||
|
|
e870aac897 | ||
|
|
40bade26d5 | ||
|
|
4bf7251998 | ||
|
|
33adeaa3e2 | ||
|
|
772e33411b | ||
|
|
5ad589d63b | ||
|
|
8b8a1d0b73 | ||
|
|
73c7f5a879 | ||
|
|
433ec4f14a | ||
|
|
4ed990e5b9 | ||
|
|
114581bf53 | ||
|
|
005bafcf5b | ||
|
|
007d699d0e | ||
|
|
ae925404a1 | ||
|
|
3fc51f35b4 | ||
|
|
a8ac8c4725 | ||
|
|
3abf3bd4ed | ||
|
|
addc9d62d6 | ||
|
|
52d0119743 | ||
|
|
f2413f2710 | ||
|
|
9acab0bba6 | ||
|
|
7c987a5ccb | ||
|
|
7947430322 | ||
|
|
31902ae639 | ||
|
|
9995d0588f | ||
|
|
7ff4da3dc2 | ||
|
|
a5bd2e10e0 | ||
|
|
3a48da47a9 | ||
|
|
0b03996304 |
+16
-7
@@ -412,12 +412,13 @@ link-extra-libs-tests = $(libsupport)
|
||||
|
||||
# Command for linking PIE programs with the C library.
|
||||
ifndef +link-pie
|
||||
+link-pie-before-libc = $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
||||
-Wl,-O1 -nostdlib -nostartfiles -o $@ \
|
||||
+link-pie-before-inputs = $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \
|
||||
-Wl,-O1 -nostdlib -nostartfiles \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)S$(start-installed-name)) \
|
||||
$(+preinit) $(+prectorS) \
|
||||
$(+preinit) $(+prectorS)
|
||||
+link-pie-before-libc = -o $@ $(+link-pie-before-inputs) \
|
||||
$(filter-out $(addprefix $(csu-objpfx),start.o \
|
||||
S$(start-installed-name))\
|
||||
$(+preinit) $(link-extra-libs) \
|
||||
@@ -442,11 +443,12 @@ endef
|
||||
endif
|
||||
# Command for statically linking programs with the C library.
|
||||
ifndef +link-static
|
||||
+link-static-before-libc = -nostdlib -nostartfiles -static -o $@ \
|
||||
+link-static-before-inputs = -nostdlib -nostartfiles -static \
|
||||
$(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \
|
||||
$(+preinit) $(+prectorT) \
|
||||
$(+preinit) $(+prectorT)
|
||||
+link-static-before-libc = -o $@ $(+link-static-before-inputs) \
|
||||
$(filter-out $(addprefix $(csu-objpfx),start.o \
|
||||
$(start-installed-name))\
|
||||
$(+preinit) $(link-extra-libs-static) \
|
||||
@@ -473,13 +475,16 @@ endif
|
||||
ifeq (yes,$(build-pie-default))
|
||||
+link = $(+link-pie)
|
||||
+link-tests = $(+link-pie-tests)
|
||||
+link-tests-before-inputs = $(+link-pie-before-inputs) $(rtld-tests-LDFLAGS)
|
||||
+link-tests-after-inputs = $(link-libc-tests) $(+link-pie-after-libc)
|
||||
+link-printers-tests = $(+link-pie-printers-tests)
|
||||
else # not build-pie-default
|
||||
+link-before-libc = -nostdlib -nostartfiles -o $@ \
|
||||
+link-before-inputs = -nostdlib -nostartfiles \
|
||||
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
|
||||
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
|
||||
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-installed-name)) \
|
||||
$(+preinit) $(+prector) \
|
||||
$(+preinit) $(+prector)
|
||||
+link-before-libc = -o $@ $(+link-before-inputs) \
|
||||
$(filter-out $(addprefix $(csu-objpfx),start.o \
|
||||
$(start-installed-name))\
|
||||
$(+preinit) $(link-extra-libs) \
|
||||
@@ -491,6 +496,8 @@ $(CC) $(link-libc-rpath-link) $(+link-before-libc) $(rtld-LDFLAGS) \
|
||||
$(link-extra-flags) $(link-libc) $(+link-after-libc)
|
||||
$(call after-link,$@)
|
||||
endef
|
||||
+link-tests-before-inputs = $(+link-before-inputs) $(rtld-tests-LDFLAGS)
|
||||
+link-tests-after-inputs = $(link-libc-tests) $(+link-after-libc)
|
||||
define +link-tests
|
||||
$(CC) $(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
|
||||
$(+link-after-libc)
|
||||
@@ -505,6 +512,8 @@ endif # build-pie-default
|
||||
else # build-static
|
||||
+link = $(+link-static)
|
||||
+link-tests = $(+link-static-tests)
|
||||
+link-tests-before-inputs = $(+link-static-before-inputs)
|
||||
+link-tests-after-inputs = $(link-libc-static-tests) $(+link-static-after-libc)
|
||||
+link-printers-tests = $(+link-static-tests)
|
||||
endif # build-shared
|
||||
endif # +link
|
||||
|
||||
@@ -424,6 +424,12 @@ $(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c)
|
||||
endef
|
||||
object-suffixes-left := $(all-object-suffixes)
|
||||
include $(o-iterator)
|
||||
|
||||
define o-iterator-doit
|
||||
$(objpfx)%$o: $(objpfx)%.cc $(before-compile); $$(compile-command.cc)
|
||||
endef
|
||||
object-suffixes-left := $(all-object-suffixes)
|
||||
include $(o-iterator)
|
||||
endif
|
||||
|
||||
# Generate .dT files as we compile.
|
||||
|
||||
@@ -4,6 +4,86 @@ See the end for copying conditions.
|
||||
|
||||
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.34.1
|
||||
|
||||
Major new features:
|
||||
|
||||
* The audit libraries will avoid unnecessary slowdown if it is not required
|
||||
PLT tracking (by not implementing the la_pltenter or la_pltexit callbacks).
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
* The audit module interface version LAV_CURRENT is increased to enable
|
||||
proper bind-now support. The loader now advertises via the la_symbind
|
||||
flags that PLT trace is not possible.
|
||||
|
||||
* The audit interface on aarch64 is extended to support both the indirect
|
||||
result location register (x8) and NEON Q register. Old audit modules are
|
||||
rejected by the loader.
|
||||
|
||||
Security related changes:
|
||||
|
||||
CVE-2022-23219: Passing an overlong file name to the clnt_create
|
||||
legacy function could result in a stack-based buffer overflow when
|
||||
using the "unix" protocol. Reported by Martin Sebor.
|
||||
|
||||
CVE-2022-23218: Passing an overlong file name to the svcunix_create
|
||||
legacy function could result in a stack-based buffer overflow.
|
||||
|
||||
CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath
|
||||
function could result in a memory leak and potential access of
|
||||
uninitialized memory. Reported by Qualys.
|
||||
|
||||
CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd
|
||||
function may result in an off-by-one buffer underflow and overflow
|
||||
when the current working directory is longer than PATH_MAX and also
|
||||
corresponds to the / directory through an unprivileged mount
|
||||
namespace. Reported by Qualys.
|
||||
|
||||
The following bugs are resolved with this release:
|
||||
|
||||
[12889] nptl: Fix race between pthread_kill and thread exit
|
||||
[19193] nptl: pthread_kill, pthread_cancel should not fail after exit
|
||||
[22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
|
||||
[28036] Incorrect types for pthread_mutexattr_set/getrobust_np
|
||||
[28182] _TIME_BITS=64 in C++ has issues with fcntl, ioctl, prctl
|
||||
[28223] mips: clone does not align stack
|
||||
[28310] Do not use affinity mask for sysconf (_SC_NPROCESSORS_CONF)
|
||||
[28338] undefined behavior in __tzfile_compute with oddball TZif file
|
||||
[28340] ld.so crashes while loading a DSO with a read-only dynamic section
|
||||
[28349] libc: Segfault for ping -R on qemux86 caused by recvmsg()
|
||||
[28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by
|
||||
recvmsg()
|
||||
[28353] Race condition in __opensock
|
||||
[28357] deadlock between pthread_create and ELF constructors
|
||||
[28361] nptl: Avoid setxid deadlock with blocked signals in thread exit
|
||||
[28407] pthread_kill assumes that kill and tgkill are equivalent
|
||||
[28524] Conversion from ISO-2022-JP-3 with iconv may emit spurious NULs
|
||||
[28532] powerpc64[le]: CFI for assembly templated syscalls is incorrect
|
||||
[28607] Masked signals are delivered on thread exit
|
||||
[28678] nptl/tst-create1 hangs sporadically
|
||||
[28700] "dns [!UNAVAIL=return] files" NSS default for hosts is not useful
|
||||
[28702] RISC-V: clone does not align stack
|
||||
[28703] RISC-V: _dl_init might be called with unaligned stack
|
||||
[28704] elf/tst-cpu-features-cpuinfo fails for KVM guests on some AMD systems
|
||||
[28707] assert in tzfile.c __tzfile_read striking with truncated timezones
|
||||
[28744] A64FX string functions are selected without SVE HWCAP
|
||||
[28755] overflow bug in wcsncmp_avx2 and wcsncmp_evex
|
||||
[28771] %ebx optimization macros are incompatible with .altmacro
|
||||
[28768] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create
|
||||
[28769] CVE-2021-3999: Off-by-one buffer overflow/underflow in getcwd()
|
||||
[28770] CVE-2021-3998: Unexpected return value from realpath() for too long results
|
||||
[28784] x86: crash in 32bit memset-sse2.s when the cache size can not be determined
|
||||
[28850] linux: __get_nprocs_sched reads uninitialized memory from the stack
|
||||
[28860] build: --enable-kernel=5.1.0 build fails because of missing
|
||||
__convert_scm_timestamps
|
||||
[28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate
|
||||
without /sys and /proc
|
||||
[28896] strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on non-rtm
|
||||
variants when avoiding overflow
|
||||
[28953] nss: Protect against errno changes in function lookup
|
||||
|
||||
|
||||
Version 2.34
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Data structure for communication from the run-time dynamic linker for
|
||||
loaded ELF shared objects. LAV_CURRENT definition.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LINK_H
|
||||
# error "Never include <bits/link_lavcurrent.h> directly; use <link.h> instead."
|
||||
#endif
|
||||
|
||||
/* Version numbers for la_version handshake interface. */
|
||||
#define LAV_CURRENT 2
|
||||
+11
-2
@@ -29,14 +29,23 @@ bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
|
||||
while (__l < __u)
|
||||
{
|
||||
__idx = (__l + __u) / 2;
|
||||
__p = (void *) (((const char *) __base) + (__idx * __size));
|
||||
__p = (const void *) (((const char *) __base) + (__idx * __size));
|
||||
__comparison = (*__compar) (__key, __p);
|
||||
if (__comparison < 0)
|
||||
__u = __idx;
|
||||
else if (__comparison > 0)
|
||||
__l = __idx + 1;
|
||||
else
|
||||
return (void *) __p;
|
||||
{
|
||||
#if __GNUC_PREREQ(4, 6)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
return (void *) __p;
|
||||
#if __GNUC_PREREQ(4, 6)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -283,10 +283,6 @@
|
||||
/* Define if static PIE is enabled. */
|
||||
#define ENABLE_STATIC_PIE 0
|
||||
|
||||
/* Some compiler options may now allow to use ebp in __asm__ (used mainly
|
||||
in i386 6 argument syscall issue). */
|
||||
#define CAN_USE_REGISTER_ASM_EBP 0
|
||||
|
||||
/* The default value of x86 CET control. */
|
||||
#define DEFAULT_DL_X86_CET_CONTROL cet_elf_property
|
||||
|
||||
|
||||
+5
-1
@@ -175,7 +175,11 @@ $(conformtest-header-tests): $(objpfx)%/conform.out: \
|
||||
conformtest.py $(conformtest-headers-data)
|
||||
(set -e; std_hdr=$*; std=$${std_hdr%%/*}; hdr=$${std_hdr#*/}; \
|
||||
mkdir -p $(@D); \
|
||||
$(PYTHON) $< --cc='$(CC)' --flags='$(conformtest-cc-flags)' \
|
||||
$(PYTHON) $< --cc='$(CC) $(pie-default)' \
|
||||
--flags='$(conformtest-cc-flags)' \
|
||||
--ldflags='$(+link-tests-before-inputs)' \
|
||||
--libs='$(+link-tests-after-inputs)' \
|
||||
--run-program-prefix='$(run-program-prefix)' \
|
||||
--standard=$$std --header=$$hdr $(conformtest-xfail) \
|
||||
$(conformtest-cross) \
|
||||
> $@ 2>&1); \
|
||||
|
||||
+17
-3
@@ -381,12 +381,16 @@ class MacroStrTest(object):
|
||||
class HeaderTests(object):
|
||||
"""The set of tests run for a header."""
|
||||
|
||||
def __init__(self, header, standard, cc, flags, cross, xfail):
|
||||
def __init__(self, header, standard, cc, flags, ldflags, libs,
|
||||
run_program_prefix, cross, xfail):
|
||||
"""Initialize a HeaderTests object."""
|
||||
self.header = header
|
||||
self.standard = standard
|
||||
self.cc = cc
|
||||
self.flags = flags
|
||||
self.ldflags = ldflags
|
||||
self.libs = libs
|
||||
self.run_program_prefix = run_program_prefix
|
||||
self.cross = cross
|
||||
self.xfail_str = xfail
|
||||
self.cflags_namespace = ('%s -fno-builtin %s -D_ISOMAC'
|
||||
@@ -590,7 +594,8 @@ class HeaderTests(object):
|
||||
exe_file = os.path.join(self.temp_dir, 'test')
|
||||
with open(c_file, 'w') as c_file_out:
|
||||
c_file_out.write('#include <%s>\n%s' % (self.header, text))
|
||||
cmd = ('%s %s %s -o %s' % (self.cc, self.cflags, c_file, exe_file))
|
||||
cmd = ('%s %s %s %s %s -o %s' % (self.cc, self.cflags, self.ldflags,
|
||||
c_file, self.libs, exe_file))
|
||||
try:
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
except subprocess.CalledProcessError:
|
||||
@@ -600,7 +605,9 @@ class HeaderTests(object):
|
||||
self.note_skip(name)
|
||||
return
|
||||
try:
|
||||
subprocess.check_call(exe_file, shell=True)
|
||||
subprocess.check_call('%s %s' % (self.run_program_prefix,
|
||||
exe_file),
|
||||
shell=True)
|
||||
except subprocess.CalledProcessError:
|
||||
self.note_error(name, self.group_xfail)
|
||||
return
|
||||
@@ -719,12 +726,19 @@ def main():
|
||||
help='C compiler to use')
|
||||
parser.add_argument('--flags', metavar='CFLAGS',
|
||||
help='Compiler flags to use with CC')
|
||||
parser.add_argument('--ldflags', metavar='LDFLAGS',
|
||||
help='Compiler arguments for linking before inputs')
|
||||
parser.add_argument('--libs', metavar='LIBS',
|
||||
help='Compiler arguments for linking after inputs')
|
||||
parser.add_argument('--run-program-prefix', metavar='RUN-PROGRAM-PREFIX',
|
||||
help='Wrapper for running newly built program')
|
||||
parser.add_argument('--cross', action='store_true',
|
||||
help='Do not run compiled test programs')
|
||||
parser.add_argument('--xfail', metavar='COND',
|
||||
help='Name of condition for XFAILs')
|
||||
args = parser.parse_args()
|
||||
tests = HeaderTests(args.header, args.standard, args.cc, args.flags,
|
||||
args.ldflags, args.libs, args.run_program_prefix,
|
||||
args.cross, args.xfail)
|
||||
tests.run()
|
||||
|
||||
|
||||
+3
-20
@@ -377,32 +377,15 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
/* This is a current program. Use the dynamic segment to find
|
||||
constructors. */
|
||||
call_init (argc, argv, __environ);
|
||||
#else /* !SHARED */
|
||||
call_init (argc, argv, __environ);
|
||||
#endif /* SHARED */
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have a new object. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->preinit != NULL)
|
||||
afct->preinit (&link_map_audit_state (head, cnt)->cookie);
|
||||
_dl_audit_preinit (GL(dl_ns)[LM_ID_BASE]._ns_loaded);
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
|
||||
GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
|
||||
#endif
|
||||
#else /* !SHARED */
|
||||
call_init (argc, argv, __environ);
|
||||
|
||||
#ifndef SHARED
|
||||
_dl_debug_initialize (0, LM_ID_BASE);
|
||||
#endif
|
||||
|
||||
|
||||
+75
-38
@@ -1,4 +1,5 @@
|
||||
# Copyright (C) 1998-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1998-2022 Free Software Foundation, Inc.
|
||||
# Copyright The GNU Toolchain Authors.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -108,30 +109,68 @@ CFLAGS-tst-longjmp_chk2.c += -fexceptions -fasynchronous-unwind-tables
|
||||
CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1
|
||||
CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables
|
||||
CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1
|
||||
CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2
|
||||
|
||||
# _FORTIFY_SOURCE tests.
|
||||
# Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and
|
||||
# preprocessor conditions based on tst-fortify.c.
|
||||
#
|
||||
# To add a new test condition, define a cflags-$(cond) make variable to set
|
||||
# CFLAGS for the file.
|
||||
|
||||
tests-all-chk = tst-fortify
|
||||
tests-c-chk =
|
||||
tests-cc-chk =
|
||||
|
||||
CFLAGS-tst-fortify.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
|
||||
# No additional flags for the default tests.
|
||||
define cflags-default
|
||||
endef
|
||||
|
||||
define cflags-lfs
|
||||
CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64
|
||||
endef
|
||||
|
||||
define cflags-nongnu
|
||||
CFLAGS-tst-fortify-$(1)-nongnu-$(2).$(1) += -D_LARGEFILE64_SOURCE=1
|
||||
endef
|
||||
|
||||
src-chk-nongnu = \#undef _GNU_SOURCE
|
||||
|
||||
# We know these tests have problems with format strings, this is what
|
||||
# we are testing. Disable that warning. They are also testing
|
||||
# deprecated functions (notably gets) so disable that warning as well.
|
||||
# And they also generate warnings from warning attributes, which
|
||||
# cannot be disabled via pragmas, so require -Wno-error to be used.
|
||||
CFLAGS-tst-chk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-chk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error
|
||||
LDLIBS-tst-chk4 = -lstdc++
|
||||
LDLIBS-tst-chk5 = -lstdc++
|
||||
LDLIBS-tst-chk6 = -lstdc++
|
||||
LDLIBS-tst-lfschk4 = -lstdc++
|
||||
LDLIBS-tst-lfschk5 = -lstdc++
|
||||
LDLIBS-tst-lfschk6 = -lstdc++
|
||||
define gen-chk-test
|
||||
tests-$(1)-chk += tst-fortify-$(1)-$(2)-$(3)
|
||||
CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \
|
||||
-Wno-deprecated-declarations \
|
||||
-Wno-error
|
||||
$(eval $(call cflags-$(2),$(1),$(3)))
|
||||
$(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile
|
||||
( echo "/* Autogenerated from Makefile. */"; \
|
||||
echo "$(src-chk-$(2))"; \
|
||||
echo "#include \"tst-fortify.c\"" ) > $$@.tmp
|
||||
mv $$@.tmp $$@
|
||||
endef
|
||||
|
||||
chk-extensions = c cc
|
||||
chk-types = default lfs nongnu
|
||||
chk-levels = 1 2 3
|
||||
|
||||
$(foreach e,$(chk-extensions), \
|
||||
$(foreach t,$(chk-types), \
|
||||
$(foreach l,$(chk-levels), \
|
||||
$(eval $(call gen-chk-test,$(e),$(t),$(l))))))
|
||||
|
||||
tests-all-chk += $(tests-c-chk) $(tests-cc-chk)
|
||||
|
||||
define link-cc
|
||||
LDLIBS-$(1) = -lstdc++
|
||||
endef
|
||||
$(foreach t,$(tests-cc-chk), $(eval $(call link-cc,$(t))))
|
||||
|
||||
# backtrace_symbols only works if we link with -rdynamic. backtrace
|
||||
# requires unwind tables on most architectures.
|
||||
@@ -148,19 +187,25 @@ LDFLAGS-tst-backtrace6 = -rdynamic
|
||||
|
||||
CFLAGS-tst-ssp-1.c += -fstack-protector-all
|
||||
|
||||
tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
|
||||
tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
|
||||
tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
|
||||
tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
|
||||
tst-backtrace5 tst-backtrace6
|
||||
tests = backtrace-tst \
|
||||
tst-longjmp_chk \
|
||||
test-strcpy_chk \
|
||||
test-stpcpy_chk \
|
||||
tst-longjmp_chk2 \
|
||||
tst-backtrace2 \
|
||||
tst-backtrace3 \
|
||||
tst-backtrace4 \
|
||||
tst-backtrace5 \
|
||||
tst-backtrace6 \
|
||||
tst-realpath-chk \
|
||||
$(tests-all-chk)
|
||||
|
||||
ifeq ($(have-ssp),yes)
|
||||
tests += tst-ssp-1
|
||||
endif
|
||||
|
||||
ifeq (,$(CXX))
|
||||
tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \
|
||||
tst-lfschk4 tst-lfschk5 tst-lfschk6
|
||||
tests-unsupported = $(tests-cc-chk)
|
||||
endif
|
||||
|
||||
extra-libs = libSegFault libpcprofile
|
||||
@@ -187,18 +232,10 @@ ifeq ($(run-built-tests),yes)
|
||||
LOCALES := de_DE.UTF-8
|
||||
include ../gen-locales.mk
|
||||
|
||||
$(objpfx)tst-chk1.out: $(gen-locales)
|
||||
$(objpfx)tst-chk2.out: $(gen-locales)
|
||||
$(objpfx)tst-chk3.out: $(gen-locales)
|
||||
$(objpfx)tst-chk4.out: $(gen-locales)
|
||||
$(objpfx)tst-chk5.out: $(gen-locales)
|
||||
$(objpfx)tst-chk6.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk1.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk2.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk3.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk4.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk5.out: $(gen-locales)
|
||||
$(objpfx)tst-lfschk6.out: $(gen-locales)
|
||||
define chk-gen-locales
|
||||
$(objpfx)$(1).out: $(gen-locales)
|
||||
endef
|
||||
$(foreach t, $(tests-all-chk), $(eval $(call chk-gen-locales,$(t))))
|
||||
endif
|
||||
|
||||
sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FORTIFY_SOURCE 1
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FORTIFY_SOURCE 2
|
||||
#include "tst-chk1.c"
|
||||
@@ -1 +0,0 @@
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FORTIFY_SOURCE 1
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FORTIFY_SOURCE 2
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2004-2021 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2004-2022 Free Software Foundation, Inc.
|
||||
Copyright The GNU Toolchain Authors.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
|
||||
|
||||
@@ -37,6 +38,17 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
# define MEMPCPY memcpy
|
||||
# define WMEMPCPY wmemcpy
|
||||
# define MEMPCPY_RET(x) 0
|
||||
# define WMEMPCPY_RET(x) 0
|
||||
#else
|
||||
# define MEMPCPY mempcpy
|
||||
# define WMEMPCPY wmempcpy
|
||||
# define MEMPCPY_RET(x) __builtin_strlen (x)
|
||||
# define WMEMPCPY_RET(x) wcslen (x)
|
||||
#endif
|
||||
|
||||
#define obstack_chunk_alloc malloc
|
||||
#define obstack_chunk_free free
|
||||
@@ -83,8 +95,14 @@ handler (int sig)
|
||||
_exit (127);
|
||||
}
|
||||
|
||||
#if __USE_FORTIFY_LEVEL == 3
|
||||
volatile size_t buf_size = 10;
|
||||
#else
|
||||
char buf[10];
|
||||
wchar_t wbuf[10];
|
||||
#define buf_size sizeof (buf)
|
||||
#endif
|
||||
|
||||
volatile size_t l0;
|
||||
volatile char *p;
|
||||
volatile wchar_t *wp;
|
||||
@@ -123,6 +141,10 @@ int num2 = 987654;
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#if __USE_FORTIFY_LEVEL == 3
|
||||
char *buf = (char *) malloc (buf_size);
|
||||
wchar_t *wbuf = (wchar_t *) malloc (buf_size * sizeof (wchar_t));
|
||||
#endif
|
||||
set_fortify_handler (handler);
|
||||
|
||||
struct A { char buf1[9]; char buf2[1]; } a;
|
||||
@@ -153,7 +175,7 @@ do_test (void)
|
||||
if (memcmp (buf, "aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (mempcpy (buf + 5, "abcde", 5) != buf + 10
|
||||
if (MEMPCPY (buf + 5, "abcde", 5) != buf + 5 + MEMPCPY_RET ("abcde")
|
||||
|| memcmp (buf, "aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -198,7 +220,7 @@ do_test (void)
|
||||
if (memcmp (buf, "aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10
|
||||
if (MEMPCPY (buf + 5, "abcde", l0 + 5) != buf + 5 + MEMPCPY_RET ("abcde")
|
||||
|| memcmp (buf, "aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -257,7 +279,8 @@ do_test (void)
|
||||
if (memcmp (a.buf1, "aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10
|
||||
if (MEMPCPY (a.buf1 + 5, "abcde", l0 + 5)
|
||||
!= a.buf1 + 5 + MEMPCPY_RET ("abcde")
|
||||
|| memcmp (a.buf1, "aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -338,6 +361,7 @@ do_test (void)
|
||||
bcopy (buf + 1, buf + 2, l0 + 9);
|
||||
CHK_FAIL_END
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
CHK_FAIL_START
|
||||
p = (char *) mempcpy (buf + 6, "abcde", 5);
|
||||
CHK_FAIL_END
|
||||
@@ -345,6 +369,7 @@ do_test (void)
|
||||
CHK_FAIL_START
|
||||
p = (char *) mempcpy (buf + 6, "abcde", l0 + 5);
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
CHK_FAIL_START
|
||||
memset (buf + 9, 'j', 2);
|
||||
@@ -455,6 +480,7 @@ do_test (void)
|
||||
bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9);
|
||||
CHK_FAIL_END
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
CHK_FAIL_START
|
||||
p = (char *) mempcpy (a.buf1 + 6, "abcde", 5);
|
||||
CHK_FAIL_END
|
||||
@@ -462,6 +488,7 @@ do_test (void)
|
||||
CHK_FAIL_START
|
||||
p = (char *) mempcpy (a.buf1 + 6, "abcde", l0 + 5);
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
CHK_FAIL_START
|
||||
memset (a.buf1 + 9, 'j', 2);
|
||||
@@ -541,7 +568,7 @@ do_test (void)
|
||||
if (wmemcmp (wbuf, L"aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10
|
||||
if (WMEMPCPY (wbuf + 5, L"abcde", 5) != wbuf + 5 + WMEMPCPY_RET (L"abcde")
|
||||
|| wmemcmp (wbuf, L"aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -574,7 +601,8 @@ do_test (void)
|
||||
if (wmemcmp (wbuf, L"aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10
|
||||
if (WMEMPCPY (wbuf + 5, L"abcde", l0 + 5)
|
||||
!= wbuf + 5 + WMEMPCPY_RET (L"abcde")
|
||||
|| wmemcmp (wbuf, L"aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -616,7 +644,8 @@ do_test (void)
|
||||
if (wmemcmp (wa.buf1, L"aabcdefghi", 10))
|
||||
FAIL ();
|
||||
|
||||
if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10
|
||||
if (WMEMPCPY (wa.buf1 + 5, L"abcde", l0 + 5)
|
||||
!= wa.buf1 + 5 + WMEMPCPY_RET (L"abcde")
|
||||
|| wmemcmp (wa.buf1, L"aabcdabcde", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -685,6 +714,7 @@ do_test (void)
|
||||
wmemmove (wbuf + 2, wbuf + 1, l0 + 9);
|
||||
CHK_FAIL_END
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
CHK_FAIL_START
|
||||
wp = wmempcpy (wbuf + 6, L"abcde", 5);
|
||||
CHK_FAIL_END
|
||||
@@ -692,6 +722,7 @@ do_test (void)
|
||||
CHK_FAIL_START
|
||||
wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5);
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
CHK_FAIL_START
|
||||
wmemset (wbuf + 9, L'j', 2);
|
||||
@@ -759,6 +790,7 @@ do_test (void)
|
||||
wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9);
|
||||
CHK_FAIL_END
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
CHK_FAIL_START
|
||||
wp = wmempcpy (wa.buf1 + 6, L"abcde", 5);
|
||||
CHK_FAIL_END
|
||||
@@ -766,6 +798,7 @@ do_test (void)
|
||||
CHK_FAIL_START
|
||||
wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5);
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
CHK_FAIL_START
|
||||
wmemset (wa.buf1 + 9, L'j', 2);
|
||||
@@ -897,6 +930,7 @@ do_test (void)
|
||||
if (fprintf (fp, buf2 + 4, str5) != 7)
|
||||
FAIL ();
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
char *my_ptr = NULL;
|
||||
strcpy (buf2 + 2, "%n%s%n");
|
||||
/* When the format string is writable and contains %n,
|
||||
@@ -926,6 +960,7 @@ do_test (void)
|
||||
if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14)
|
||||
FAIL ();
|
||||
obstack_free (&obs, NULL);
|
||||
#endif
|
||||
|
||||
if (freopen (temp_filename, "r", stdin) == NULL)
|
||||
{
|
||||
@@ -947,93 +982,95 @@ do_test (void)
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fgets (buf, sizeof (buf), stdin) != buf
|
||||
if (fgets (buf, buf_size, stdin) != buf
|
||||
|| memcmp (buf, "abcdefgh\n", 10))
|
||||
FAIL ();
|
||||
if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
|
||||
if (fgets (buf, buf_size, stdin) != buf || memcmp (buf, "ABCDEFGHI", 10))
|
||||
FAIL ();
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fgets (buf, l0 + sizeof (buf), stdin) != buf
|
||||
if (fgets (buf, l0 + buf_size, stdin) != buf
|
||||
|| memcmp (buf, "abcdefgh\n", 10))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (fgets (buf, sizeof (buf) + 1, stdin) != buf)
|
||||
if (fgets (buf, buf_size + 1, stdin) != buf)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf)
|
||||
if (fgets (buf, l0 + buf_size + 1, stdin) != buf)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
|
||||
#ifdef _GNU_SOURCE
|
||||
if (fgets_unlocked (buf, buf_size, stdin) != buf
|
||||
|| memcmp (buf, "abcdefgh\n", 10))
|
||||
FAIL ();
|
||||
if (fgets_unlocked (buf, sizeof (buf), stdin) != buf
|
||||
if (fgets_unlocked (buf, buf_size, stdin) != buf
|
||||
|| memcmp (buf, "ABCDEFGHI", 10))
|
||||
FAIL ();
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf
|
||||
if (fgets_unlocked (buf, l0 + buf_size, stdin) != buf
|
||||
|| memcmp (buf, "abcdefgh\n", 10))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf)
|
||||
if (fgets_unlocked (buf, buf_size + 1, stdin) != buf)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf)
|
||||
if (fgets_unlocked (buf, l0 + buf_size + 1, stdin) != buf)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
rewind (stdin);
|
||||
#endif
|
||||
|
||||
if (fread (buf, 1, sizeof (buf), stdin) != sizeof (buf)
|
||||
if (fread (buf, 1, buf_size, stdin) != buf_size
|
||||
|| memcmp (buf, "abcdefgh\nA", 10))
|
||||
FAIL ();
|
||||
if (fread (buf, sizeof (buf), 1, stdin) != 1
|
||||
if (fread (buf, buf_size, 1, stdin) != 1
|
||||
|| memcmp (buf, "BCDEFGHI\na", 10))
|
||||
FAIL ();
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fread (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
|
||||
if (fread (buf, l0 + 1, buf_size, stdin) != buf_size
|
||||
|| memcmp (buf, "abcdefgh\nA", 10))
|
||||
FAIL ();
|
||||
if (fread (buf, sizeof (buf), l0 + 1, stdin) != 1
|
||||
if (fread (buf, buf_size, l0 + 1, stdin) != 1
|
||||
|| memcmp (buf, "BCDEFGHI\na", 10))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (fread (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
|
||||
if (fread (buf, 1, buf_size + 1, stdin) != buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (fread (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
|
||||
if (fread (buf, buf_size + 1, l0 + 1, stdin) != 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fread_unlocked (buf, 1, sizeof (buf), stdin) != sizeof (buf)
|
||||
if (fread_unlocked (buf, 1, buf_size, stdin) != buf_size
|
||||
|| memcmp (buf, "abcdefgh\nA", 10))
|
||||
FAIL ();
|
||||
if (fread_unlocked (buf, sizeof (buf), 1, stdin) != 1
|
||||
if (fread_unlocked (buf, buf_size, 1, stdin) != 1
|
||||
|| memcmp (buf, "BCDEFGHI\na", 10))
|
||||
FAIL ();
|
||||
|
||||
@@ -1048,100 +1085,100 @@ do_test (void)
|
||||
|
||||
rewind (stdin);
|
||||
|
||||
if (fread_unlocked (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
|
||||
if (fread_unlocked (buf, l0 + 1, buf_size, stdin) != buf_size
|
||||
|| memcmp (buf, "abcdefgh\nA", 10))
|
||||
FAIL ();
|
||||
if (fread_unlocked (buf, sizeof (buf), l0 + 1, stdin) != 1
|
||||
if (fread_unlocked (buf, buf_size, l0 + 1, stdin) != 1
|
||||
|| memcmp (buf, "BCDEFGHI\na", 10))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (fread_unlocked (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
|
||||
if (fread_unlocked (buf, 1, buf_size + 1, stdin) != buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (fread_unlocked (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
|
||||
if (fread_unlocked (buf, buf_size + 1, l0 + 1, stdin) != 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
lseek (fileno (stdin), 0, SEEK_SET);
|
||||
|
||||
if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
|
||||
if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
|
||||
|| memcmp (buf, "abcdefgh\n", 9))
|
||||
FAIL ();
|
||||
if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1
|
||||
if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1
|
||||
|| memcmp (buf, "ABCDEFGHI", 9))
|
||||
FAIL ();
|
||||
|
||||
lseek (fileno (stdin), 0, SEEK_SET);
|
||||
|
||||
if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1
|
||||
if (read (fileno (stdin), buf, l0 + buf_size - 1) != buf_size - 1
|
||||
|| memcmp (buf, "abcdefgh\n", 9))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1)
|
||||
if (read (fileno (stdin), buf, buf_size + 1) != buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (read (fileno (stdin), buf, l0 + sizeof (buf) + 1) != sizeof (buf) + 1)
|
||||
if (read (fileno (stdin), buf, l0 + buf_size + 1) != buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
|
||||
!= sizeof (buf) - 1
|
||||
if (pread (fileno (stdin), buf, buf_size - 1, buf_size - 2)
|
||||
!= buf_size - 1
|
||||
|| memcmp (buf, "\nABCDEFGH", 9))
|
||||
FAIL ();
|
||||
if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
|
||||
if (pread (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
|
||||
|| memcmp (buf, "abcdefgh\n", 9))
|
||||
FAIL ();
|
||||
if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
|
||||
!= sizeof (buf) - 1
|
||||
if (pread (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
|
||||
!= buf_size - 1
|
||||
|| memcmp (buf, "h\nABCDEFG", 9))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
|
||||
!= sizeof (buf) + 1)
|
||||
if (pread (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
|
||||
!= buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (pread (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf))
|
||||
!= sizeof (buf) + 1)
|
||||
if (pread (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
|
||||
!= buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
|
||||
if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2)
|
||||
!= sizeof (buf) - 1
|
||||
if (pread64 (fileno (stdin), buf, buf_size - 1, buf_size - 2)
|
||||
!= buf_size - 1
|
||||
|| memcmp (buf, "\nABCDEFGH", 9))
|
||||
FAIL ();
|
||||
if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1
|
||||
if (pread64 (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1
|
||||
|| memcmp (buf, "abcdefgh\n", 9))
|
||||
FAIL ();
|
||||
if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3)
|
||||
!= sizeof (buf) - 1
|
||||
if (pread64 (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3)
|
||||
!= buf_size - 1
|
||||
|| memcmp (buf, "h\nABCDEFG", 9))
|
||||
FAIL ();
|
||||
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf))
|
||||
!= sizeof (buf) + 1)
|
||||
if (pread64 (fileno (stdin), buf, buf_size + 1, 2 * buf_size)
|
||||
!= buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
|
||||
CHK_FAIL_START
|
||||
if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf))
|
||||
!= sizeof (buf) + 1)
|
||||
if (pread64 (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size)
|
||||
!= buf_size + 1)
|
||||
FAIL ();
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
@@ -1179,7 +1216,7 @@ do_test (void)
|
||||
CHK_FAIL2_END
|
||||
|
||||
CHK_FAIL2_START
|
||||
snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4);
|
||||
snprintf (buf, buf_size, "%3$d\n", 1, 2, 3, 4);
|
||||
CHK_FAIL2_END
|
||||
|
||||
int sp[2];
|
||||
@@ -1569,7 +1606,10 @@ do_test (void)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
int fd = posix_openpt (O_RDWR);
|
||||
int fd;
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
fd = posix_openpt (O_RDWR);
|
||||
if (fd != -1)
|
||||
{
|
||||
char enough[1000];
|
||||
@@ -1585,6 +1625,7 @@ do_test (void)
|
||||
#endif
|
||||
close (fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PATH_MAX > 0
|
||||
confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf));
|
||||
@@ -1702,8 +1743,9 @@ do_test (void)
|
||||
poll (fds, l0 + 2, 0);
|
||||
CHK_FAIL_END
|
||||
#endif
|
||||
#ifdef _GNU_SOURCE
|
||||
ppoll (fds, 1, NULL, NULL);
|
||||
#if __USE_FORTIFY_LEVEL >= 1
|
||||
# if __USE_FORTIFY_LEVEL >= 1
|
||||
CHK_FAIL_START
|
||||
ppoll (fds, 2, NULL, NULL);
|
||||
CHK_FAIL_END
|
||||
@@ -1711,6 +1753,7 @@ do_test (void)
|
||||
CHK_FAIL_START
|
||||
ppoll (fds, l0 + 2, NULL, NULL);
|
||||
CHK_FAIL_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk2.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk3.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk1.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk2.c"
|
||||
@@ -1,2 +0,0 @@
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include "tst-chk3.c"
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Smoke test to verify that realpath does not cause spurious warnings.
|
||||
Copyright The GNU Toolchain Authors.
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifdef PATH_MAX
|
||||
char buf[PATH_MAX + 1];
|
||||
char *res = realpath (".", buf);
|
||||
TEST_VERIFY (res == buf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
+840
-215
File diff suppressed because it is too large
Load Diff
@@ -48,6 +48,9 @@ ld {
|
||||
# stack canary
|
||||
__stack_chk_guard;
|
||||
}
|
||||
GLIBC_2.34 {
|
||||
__rtld_version_placeholder;
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
# Those are in the dynamic linker, but used by libc.so.
|
||||
__libc_enable_secure;
|
||||
@@ -55,6 +58,7 @@ ld {
|
||||
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
|
||||
_dl_deallocate_tls; _dl_make_stack_executable;
|
||||
_dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf;
|
||||
_dl_audit_symbind_alt; _dl_audit_preinit;
|
||||
_rtld_global; _rtld_global_ro;
|
||||
|
||||
# Only here for gdb while a better method is developed.
|
||||
|
||||
+381
@@ -0,0 +1,381 @@
|
||||
/* Audit common functions.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <link.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-machine.h>
|
||||
#include <dl-runtime.h>
|
||||
#include <dl-fixup-attribute.h>
|
||||
|
||||
void
|
||||
_dl_audit_activity_map (struct link_map *l, int action)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
afct->activity (&link_map_audit_state (l, cnt)->cookie, action);
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_activity_nsid (Lmid_t nsid, int action)
|
||||
{
|
||||
/* If head is NULL, the namespace has become empty, and the audit interface
|
||||
does not give us a way to signal LA_ACT_CONSISTENT for it because the
|
||||
first loaded module is used to identify the namespace. */
|
||||
struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
|
||||
if (__glibc_likely (GLRO(dl_naudit) == 0)
|
||||
|| head == NULL || head->l_auditing)
|
||||
return;
|
||||
|
||||
_dl_audit_activity_map (head, action);
|
||||
}
|
||||
|
||||
const char *
|
||||
_dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code)
|
||||
{
|
||||
if (l == NULL || l->l_auditing || code == 0)
|
||||
return name;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objsearch != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (l, cnt);
|
||||
name = afct->objsearch (name, &state->cookie, code);
|
||||
if (name == NULL)
|
||||
return NULL;
|
||||
}
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_objopen (struct link_map *l, Lmid_t nsid)
|
||||
{
|
||||
if (__glibc_likely (GLRO(dl_naudit) == 0))
|
||||
return;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objopen != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (l, cnt);
|
||||
state->bindflags = afct->objopen (l, nsid, &state->cookie);
|
||||
l->l_audit_any_plt |= state->bindflags != 0;
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_objclose (struct link_map *l)
|
||||
{
|
||||
if (__glibc_likely (GLRO(dl_naudit) == 0)
|
||||
|| GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
|
||||
return;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objclose != NULL)
|
||||
{
|
||||
struct auditstate *state= link_map_audit_state (l, cnt);
|
||||
/* Return value is ignored. */
|
||||
afct->objclose (&state->cookie);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_preinit (struct link_map *l)
|
||||
{
|
||||
if (__glibc_likely (GLRO(dl_naudit) == 0))
|
||||
return;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->preinit != NULL)
|
||||
afct->preinit (&link_map_audit_state (l, cnt)->cookie);
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
|
||||
lookup_t result)
|
||||
{
|
||||
if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
|
||||
return;
|
||||
|
||||
const char *strtab = (const char *) D_PTR (result, l_info[DT_STRTAB]);
|
||||
/* Compute index of the symbol entry in the symbol table of the DSO with
|
||||
the definition. */
|
||||
unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, l_info[DT_SYMTAB]));
|
||||
|
||||
unsigned int altvalue = 0;
|
||||
/* Synthesize a symbol record where the st_value field is the result. */
|
||||
ElfW(Sym) sym = *ref;
|
||||
sym.st_value = (ElfW(Addr)) *value;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
struct auditstate *match_audit = link_map_audit_state (l, cnt);
|
||||
struct auditstate *result_audit = link_map_audit_state (result, cnt);
|
||||
if (afct->symbind != NULL
|
||||
&& ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
|
||||
|| ((result_audit->bindflags & LA_FLG_BINDTO)
|
||||
!= 0)))
|
||||
{
|
||||
unsigned int flags = altvalue | LA_SYMB_DLSYM;
|
||||
uintptr_t new_value = afct->symbind (&sym, ndx,
|
||||
&match_audit->cookie,
|
||||
&result_audit->cookie,
|
||||
&flags, strtab + ref->st_name);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
altvalue = LA_SYMB_ALTVALUE;
|
||||
sym.st_value = new_value;
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
*value = (void *) sym.st_value;
|
||||
}
|
||||
}
|
||||
rtld_hidden_def (_dl_audit_symbind_alt)
|
||||
|
||||
void
|
||||
_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
|
||||
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
|
||||
lookup_t result)
|
||||
{
|
||||
bool for_jmp_slot = reloc_result == NULL;
|
||||
|
||||
/* Compute index of the symbol entry in the symbol table of the DSO
|
||||
with the definition. */
|
||||
unsigned int boundndx = defsym - (ElfW(Sym) *) D_PTR (result,
|
||||
l_info[DT_SYMTAB]);
|
||||
if (!for_jmp_slot)
|
||||
{
|
||||
reloc_result->bound = result;
|
||||
reloc_result->boundndx = boundndx;
|
||||
}
|
||||
|
||||
if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
|
||||
{
|
||||
/* Set all bits since this symbol binding is not interesting. */
|
||||
if (!for_jmp_slot)
|
||||
reloc_result->enterexit = (1u << DL_NNS) - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Synthesize a symbol record where the st_value field is the result. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
|
||||
|
||||
/* Keep track whether there is any interest in tracing the call in the lower
|
||||
two bits. */
|
||||
assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
|
||||
assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
|
||||
uint32_t enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
|
||||
|
||||
const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
|
||||
|
||||
unsigned int flags = 0;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
uintptr_t new_value = (uintptr_t) sym.st_value;
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
/* XXX Check whether both DSOs must request action or only one */
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *result_state = link_map_audit_state (result, cnt);
|
||||
if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
|
||||
&& (result_state->bindflags & LA_FLG_BINDTO) != 0)
|
||||
{
|
||||
if (afct->symbind != NULL)
|
||||
{
|
||||
flags |= for_jmp_slot ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT
|
||||
: 0;
|
||||
new_value = afct->symbind (&sym, boundndx,
|
||||
&l_state->cookie,
|
||||
&result_state->cookie, &flags,
|
||||
strtab2 + defsym->st_name);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
flags |= LA_SYMB_ALTVALUE;
|
||||
sym.st_value = for_jmp_slot
|
||||
? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the results for every audit library and store a summary
|
||||
in the first two bits. */
|
||||
enterexit &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
|
||||
enterexit |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
|
||||
<< ((cnt + 1) * 2));
|
||||
}
|
||||
else
|
||||
/* If the bind flags say this auditor is not interested, set the bits
|
||||
manually. */
|
||||
enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
|
||||
<< ((cnt + 1) * 2));
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
if (!for_jmp_slot)
|
||||
{
|
||||
reloc_result->enterexit = enterexit;
|
||||
reloc_result->flags = flags;
|
||||
}
|
||||
|
||||
DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
|
||||
}
|
||||
|
||||
void
|
||||
_dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
|
||||
DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize)
|
||||
{
|
||||
/* Don't do anything if no auditor wants to intercept this call. */
|
||||
if (GLRO(dl_naudit) == 0
|
||||
|| (reloc_result->enterexit & LA_SYMB_NOPLTENTER))
|
||||
return;
|
||||
|
||||
/* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
|
||||
initialized earlier in this function or in another thread. */
|
||||
assert (DL_FIXUP_VALUE_CODE_ADDR (*value) != 0);
|
||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_SYMTAB])
|
||||
+ reloc_result->boundndx);
|
||||
|
||||
/* Set up the sym parameter. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
|
||||
|
||||
/* Get the symbol name. */
|
||||
const char *strtab = (const void *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_STRTAB]);
|
||||
const char *symname = strtab + sym.st_name;
|
||||
|
||||
/* Keep track of overwritten addresses. */
|
||||
unsigned int flags = reloc_result->flags;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->ARCH_LA_PLTENTER != NULL
|
||||
&& (reloc_result->enterexit
|
||||
& (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
|
||||
{
|
||||
long int new_framesize = -1;
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *bound_state
|
||||
= link_map_audit_state (reloc_result->bound, cnt);
|
||||
uintptr_t new_value
|
||||
= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
|
||||
&l_state->cookie, &bound_state->cookie,
|
||||
regs, &flags, symname, &new_framesize);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
flags |= LA_SYMB_ALTVALUE;
|
||||
sym.st_value = new_value;
|
||||
}
|
||||
|
||||
/* Remember the results for every audit library and store a summary
|
||||
in the first two bits. */
|
||||
reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER
|
||||
| LA_SYMB_NOPLTEXIT))
|
||||
<< (2 * (cnt + 1)));
|
||||
|
||||
if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
|
||||
<< (2 * (cnt + 1))))
|
||||
== 0 && new_framesize != -1 && *framesize != -2)
|
||||
{
|
||||
/* If this is the first call providing information, use it. */
|
||||
if (*framesize == -1)
|
||||
*framesize = new_framesize;
|
||||
/* If two pltenter calls provide conflicting information, use
|
||||
the larger value. */
|
||||
else if (new_framesize != *framesize)
|
||||
*framesize = MAX (new_framesize, *framesize);
|
||||
}
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
*value = DL_FIXUP_ADDR_VALUE (sym.st_value);
|
||||
}
|
||||
|
||||
void
|
||||
DL_ARCH_FIXUP_ATTRIBUTE
|
||||
_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
|
||||
const void *inregs, void *outregs)
|
||||
{
|
||||
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
|
||||
|
||||
/* This is the address in the array where we store the result of previous
|
||||
relocations. */
|
||||
// XXX Maybe the bound information must be stored on the stack since
|
||||
// XXX with bind_not a new value could have been stored in the meantime.
|
||||
struct reloc_result *reloc_result =
|
||||
&l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
|
||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_SYMTAB])
|
||||
+ reloc_result->boundndx);
|
||||
|
||||
/* Set up the sym parameter. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
|
||||
|
||||
/* Get the symbol name. */
|
||||
const char *strtab = (const void *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_STRTAB]);
|
||||
const char *symname = strtab + sym.st_name;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->ARCH_LA_PLTEXIT != NULL
|
||||
&& (reloc_result->enterexit
|
||||
& (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
|
||||
{
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *bound_state
|
||||
= link_map_audit_state (reloc_result->bound, cnt);
|
||||
afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
|
||||
&l_state->cookie, &bound_state->cookie,
|
||||
inregs, outregs, symname);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
+11
-64
@@ -266,9 +266,6 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
used + (nsid == LM_ID_BASE), true);
|
||||
|
||||
/* Call all termination functions at once. */
|
||||
#ifdef SHARED
|
||||
bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
|
||||
#endif
|
||||
bool unload_any = false;
|
||||
bool scope_mem_left = false;
|
||||
unsigned int unload_global = 0;
|
||||
@@ -302,22 +299,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we remove an object. */
|
||||
if (__glibc_unlikely (do_audit))
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objclose != NULL)
|
||||
{
|
||||
struct auditstate *state
|
||||
= link_map_audit_state (imap, cnt);
|
||||
/* Return value is ignored. */
|
||||
(void) afct->objclose (&state->cookie);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
_dl_audit_objclose (imap);
|
||||
#endif
|
||||
|
||||
/* This object must not be used anymore. */
|
||||
@@ -478,25 +460,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we will start deleting objects. */
|
||||
if (__glibc_unlikely (do_audit))
|
||||
{
|
||||
struct link_map *head = ns->_ns_loaded;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
{
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (head, cnt);
|
||||
afct->activity (&state->cookie, LA_ACT_DELETE);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
_dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
|
||||
#endif
|
||||
|
||||
/* Notify the debugger we are about to remove some loaded objects. */
|
||||
@@ -549,6 +513,9 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
size_t tls_free_end;
|
||||
tls_free_start = tls_free_end = NO_TLS_OFFSET;
|
||||
|
||||
/* Protects global and module specitic TLS state. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
/* We modify the list of loaded objects. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_write_lock));
|
||||
|
||||
@@ -784,33 +751,13 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
GL(dl_tls_static_used) = tls_free_start;
|
||||
}
|
||||
|
||||
/* TLS is cleaned up for the unloaded modules. */
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have deleted all objects. */
|
||||
if (__glibc_unlikely (do_audit))
|
||||
{
|
||||
struct link_map *head = ns->_ns_loaded;
|
||||
/* If head is NULL, the namespace has become empty, and the
|
||||
audit interface does not give us a way to signal
|
||||
LA_ACT_CONSISTENT for it because the first loaded module is
|
||||
used to identify the namespace.
|
||||
|
||||
Furthermore, do not notify auditors of the cleanup of a
|
||||
failed audit module loading attempt. */
|
||||
if (head != NULL && head->l_auditing == 0)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (head, cnt);
|
||||
afct->activity (&state->cookie, LA_ACT_CONSISTENT);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Auditing checkpoint: we have deleted all objects. Also, do not notify
|
||||
auditors of the cleanup of a failed audit module loading attempt. */
|
||||
_dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT);
|
||||
#endif
|
||||
|
||||
if (__builtin_expect (ns->_ns_loaded == NULL, 0)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Placeholder compatibility symbols.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <shlib-compat.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/* GLIBC_2.34 placeholder for future symbol moves. */
|
||||
|
||||
void
|
||||
attribute_compat_text_section
|
||||
__attribute_used__
|
||||
__rtld_version_placeholder_1 (void)
|
||||
{
|
||||
}
|
||||
|
||||
compat_symbol (ld, __rtld_version_placeholder_1,
|
||||
__rtld_version_placeholder, GLIBC_2_34);
|
||||
+22
-18
@@ -17,6 +17,7 @@
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If
|
||||
not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
@@ -27,6 +28,24 @@
|
||||
#include <sys/types.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
/* Used at loading time solely for prelink executable. It is not called
|
||||
concurrently so it is be safe to defined as static. */
|
||||
static struct link_map *resolve_conflict_map __attribute__ ((__unused__));
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(map, scope, ref, version, flags) (*ref = NULL, NULL)
|
||||
#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
|
||||
#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
|
||||
do { \
|
||||
while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset)) \
|
||||
|| (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset))) \
|
||||
resolve_conflict_map = resolve_conflict_map->l_next; \
|
||||
\
|
||||
(map) = resolve_conflict_map; \
|
||||
} while (0)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
void
|
||||
_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
ElfW(Rela) *conflictend)
|
||||
@@ -39,24 +58,9 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
/* Do the conflict relocation of the object and library GOT and other
|
||||
data. */
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL)
|
||||
#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
|
||||
#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
|
||||
do { \
|
||||
while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset)) \
|
||||
|| (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset))) \
|
||||
resolve_conflict_map = resolve_conflict_map->l_next; \
|
||||
\
|
||||
(map) = resolve_conflict_map; \
|
||||
} while (0)
|
||||
|
||||
/* Prelinking makes no sense for anything but the main namespace. */
|
||||
assert (l->l_ns == LM_ID_BASE);
|
||||
struct link_map *resolve_conflict_map __attribute__ ((__unused__))
|
||||
= GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
#include "dynamic-link.h"
|
||||
resolve_conflict_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
/* Override these, defined in dynamic-link.h. */
|
||||
#undef CHECK_STATIC_TLS
|
||||
@@ -67,8 +71,8 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
GL(dl_num_cache_relocations) += conflictend - conflict;
|
||||
|
||||
for (; conflict < conflictend; ++conflict)
|
||||
elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset,
|
||||
0);
|
||||
elf_machine_rela (l, NULL, conflict, NULL, NULL,
|
||||
(void *) conflict->r_offset, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+9
-15
@@ -64,6 +64,10 @@ _dl_fini (void)
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
else
|
||||
{
|
||||
#ifdef SHARED
|
||||
_dl_audit_activity_nsid (ns, LA_ACT_DELETE);
|
||||
#endif
|
||||
|
||||
/* Now we can allocate an array to hold all the pointers and
|
||||
copy the pointers in. */
|
||||
struct link_map *maps[nloaded];
|
||||
@@ -147,27 +151,17 @@ _dl_fini (void)
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: another object closed. */
|
||||
if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0))
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objclose != NULL)
|
||||
{
|
||||
struct auditstate *state
|
||||
= link_map_audit_state (l, cnt);
|
||||
/* Return value is ignored. */
|
||||
(void) afct->objclose (&state->cookie);
|
||||
}
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
_dl_audit_objclose (l);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Correct the previous increment. */
|
||||
--l->l_direct_opencount;
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
||||
_dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+57
-112
@@ -58,6 +58,7 @@ struct filebuf
|
||||
};
|
||||
|
||||
#include "dynamic-link.h"
|
||||
#include "get-dynamic-info.h"
|
||||
#include <abi-tag.h>
|
||||
#include <stackinfo.h>
|
||||
#include <sysdep.h>
|
||||
@@ -1053,42 +1054,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
/* This is the ELF header. We read it in `open_verify'. */
|
||||
header = (void *) fbp->buf;
|
||||
|
||||
/* Signal that we are going to add new objects. */
|
||||
if (r->r_state == RT_CONSISTENT)
|
||||
{
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we are going to add new objects. */
|
||||
if ((mode & __RTLD_AUDIT) == 0
|
||||
&& __glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
afct->activity (&link_map_audit_state (head, cnt)->cookie,
|
||||
LA_ACT_ADD);
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Notify the debugger we have added some objects. We need to
|
||||
call _dl_debug_initialize in a static program in case dynamic
|
||||
linking has not been used before. */
|
||||
r->r_state = RT_ADD;
|
||||
_dl_debug_state ();
|
||||
LIBC_PROBE (map_start, 2, nsid, r);
|
||||
make_consistent = true;
|
||||
}
|
||||
else
|
||||
assert (r->r_state == RT_ADD);
|
||||
|
||||
/* Enter the new object in the list of loaded objects. */
|
||||
l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
|
||||
if (__glibc_unlikely (l == NULL))
|
||||
@@ -1130,6 +1095,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
struct loadcmd loadcmds[l->l_phnum];
|
||||
size_t nloadcmds = 0;
|
||||
bool has_holes = false;
|
||||
bool empty_dynamic = false;
|
||||
|
||||
/* The struct is initialized to zero so this is not necessary:
|
||||
l->l_ld = 0;
|
||||
@@ -1142,13 +1108,16 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
segments are mapped in. We record the addresses it says
|
||||
verbatim, and later correct for the run-time load address. */
|
||||
case PT_DYNAMIC:
|
||||
if (ph->p_filesz)
|
||||
if (ph->p_filesz == 0)
|
||||
empty_dynamic = true; /* Usually separate debuginfo. */
|
||||
else
|
||||
{
|
||||
/* Debuginfo only files from "objcopy --only-keep-debug"
|
||||
contain a PT_DYNAMIC segment with p_filesz == 0. Skip
|
||||
such a segment to avoid a crash later. */
|
||||
l->l_ld = (void *) ph->p_vaddr;
|
||||
l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
|
||||
l->l_ld_readonly = (ph->p_flags & PF_W) == 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1264,6 +1233,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
goto lose;
|
||||
}
|
||||
|
||||
/* This check recognizes most separate debuginfo files. */
|
||||
if (__glibc_unlikely ((l->l_ld == 0 && type == ET_DYN) || empty_dynamic))
|
||||
{
|
||||
errstring = N_("object file has no dynamic section");
|
||||
goto lose;
|
||||
}
|
||||
|
||||
/* Length of the sections to be loaded. */
|
||||
maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
|
||||
|
||||
@@ -1281,18 +1257,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||
}
|
||||
}
|
||||
|
||||
if (l->l_ld == 0)
|
||||
{
|
||||
if (__glibc_unlikely (type == ET_DYN))
|
||||
{
|
||||
errstring = N_("object file has no dynamic section");
|
||||
goto lose;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (l->l_ld != 0)
|
||||
l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
|
||||
|
||||
elf_get_dynamic_info (l, NULL);
|
||||
elf_get_dynamic_info (l);
|
||||
|
||||
/* Make sure we are not dlopen'ing an object that has the
|
||||
DF_1_NOOPEN flag set, or a PIE object. */
|
||||
@@ -1507,24 +1475,32 @@ cannot enable executable stack as shared object requires");
|
||||
/* Now that the object is fully initialized add it to the object list. */
|
||||
_dl_add_to_namespace_list (l, nsid);
|
||||
|
||||
/* Signal that we are going to add new objects. */
|
||||
if (r->r_state == RT_CONSISTENT)
|
||||
{
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we are going to add new objects. Since this
|
||||
is called after _dl_add_to_namespace_list the namespace is guaranteed
|
||||
to not be empty. */
|
||||
if ((mode & __RTLD_AUDIT) == 0)
|
||||
_dl_audit_activity_nsid (nsid, LA_ACT_ADD);
|
||||
#endif
|
||||
|
||||
/* Notify the debugger we have added some objects. We need to
|
||||
call _dl_debug_initialize in a static program in case dynamic
|
||||
linking has not been used before. */
|
||||
r->r_state = RT_ADD;
|
||||
_dl_debug_state ();
|
||||
LIBC_PROBE (map_start, 2, nsid, r);
|
||||
make_consistent = true;
|
||||
}
|
||||
else
|
||||
assert (r->r_state == RT_ADD);
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have a new object. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0)
|
||||
&& !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objopen != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (l, cnt);
|
||||
state->bindflags = afct->objopen (l, nsid, &state->cookie);
|
||||
l->l_audit_any_plt |= state->bindflags != 0;
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
|
||||
_dl_audit_objopen (l, nsid);
|
||||
#endif
|
||||
|
||||
return l;
|
||||
@@ -1620,32 +1596,20 @@ open_verify (const char *name, int fd,
|
||||
|
||||
#ifdef SHARED
|
||||
/* Give the auditing libraries a chance. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0
|
||||
&& loader->l_auditing == 0)
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
const char *original_name = name;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objsearch != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (loader, cnt);
|
||||
name = afct->objsearch (name, &state->cookie, whatcode);
|
||||
if (name == NULL)
|
||||
/* Ignore the path. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
name = _dl_audit_objsearch (name, loader, whatcode);
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
|
||||
if (fd != -1 && name != original_name && strcmp (name, original_name))
|
||||
{
|
||||
/* An audit library changed what we're supposed to open,
|
||||
so FD no longer matches it. */
|
||||
__close_nocancel (fd);
|
||||
fd = -1;
|
||||
}
|
||||
{
|
||||
/* An audit library changed what we're supposed to open,
|
||||
so FD no longer matches it. */
|
||||
__close_nocancel (fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2084,36 +2048,17 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
#ifdef SHARED
|
||||
/* Give the auditing libraries a chance to change the name before we
|
||||
try anything. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0)
|
||||
&& (loader == NULL || loader->l_auditing == 0))
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
const char *before = name;
|
||||
name = _dl_audit_objsearch (name, loader, LA_SER_ORIG);
|
||||
if (name == NULL)
|
||||
{
|
||||
if (afct->objsearch != NULL)
|
||||
{
|
||||
const char *before = name;
|
||||
struct auditstate *state = link_map_audit_state (loader, cnt);
|
||||
name = afct->objsearch (name, &state->cookie, LA_SER_ORIG);
|
||||
if (name == NULL)
|
||||
{
|
||||
/* Do not try anything further. */
|
||||
fd = -1;
|
||||
goto no_file;
|
||||
}
|
||||
if (before != name && strcmp (before, name) != 0)
|
||||
{
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
|
||||
_dl_debug_printf ("audit changed filename %s -> %s\n",
|
||||
before, name);
|
||||
|
||||
if (origname == NULL)
|
||||
origname = before;
|
||||
}
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
fd = -1;
|
||||
goto no_file;
|
||||
}
|
||||
if (before != name && strcmp (before, name) != 0)
|
||||
origname = before;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+10
-7
@@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||
{
|
||||
#ifdef SHARED
|
||||
unsigned int naudit;
|
||||
if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
|
||||
if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
|
||||
{
|
||||
assert (type == lt_executable);
|
||||
assert (nsid == LM_ID_BASE);
|
||||
if (mode & __RTLD_OPENEXEC)
|
||||
{
|
||||
assert (type == lt_executable);
|
||||
assert (nsid == LM_ID_BASE);
|
||||
|
||||
/* Ignore the specified libname for the main executable. It is
|
||||
only known with an explicit loader invocation. */
|
||||
libname = "";
|
||||
/* Ignore the specified libname for the main executable. It is
|
||||
only known with an explicit loader invocation. */
|
||||
libname = "";
|
||||
}
|
||||
|
||||
/* We create the map for the executable before we know whether
|
||||
/* We create the map for the executable and vDSO before we know whether
|
||||
we have auditing libraries and if yes, how many. Assume the
|
||||
worst. */
|
||||
naudit = DL_NNS;
|
||||
|
||||
+36
-23
@@ -66,6 +66,9 @@ struct dl_open_args
|
||||
libc_map value in the namespace in case of a dlopen failure. */
|
||||
bool libc_already_loaded;
|
||||
|
||||
/* Set to true if the end of dl_open_worker_begin was reached. */
|
||||
bool worker_continue;
|
||||
|
||||
/* Original parameters to the program and the current environment. */
|
||||
int argc;
|
||||
char **argv;
|
||||
@@ -482,7 +485,7 @@ call_dl_init (void *closure)
|
||||
}
|
||||
|
||||
static void
|
||||
dl_open_worker (void *a)
|
||||
dl_open_worker_begin (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
const char *file = args->file;
|
||||
@@ -608,25 +611,7 @@ dl_open_worker (void *a)
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have added all objects. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (head, cnt);
|
||||
afct->activity (&state->cookie, LA_ACT_CONSISTENT);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
_dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
|
||||
#endif
|
||||
|
||||
/* Notify the debugger all new objects are now ready to go. */
|
||||
@@ -774,6 +759,36 @@ dl_open_worker (void *a)
|
||||
_dl_call_libc_early_init (libc_map, false);
|
||||
}
|
||||
|
||||
args->worker_continue = true;
|
||||
}
|
||||
|
||||
static void
|
||||
dl_open_worker (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
|
||||
args->worker_continue = false;
|
||||
|
||||
{
|
||||
/* Protects global and module specific TLS state. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
struct dl_exception ex;
|
||||
int err = _dl_catch_exception (&ex, dl_open_worker_begin, args);
|
||||
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
if (__glibc_unlikely (ex.errstring != NULL))
|
||||
/* Reraise the error. */
|
||||
_dl_signal_exception (err, &ex, NULL);
|
||||
}
|
||||
|
||||
if (!args->worker_continue)
|
||||
return;
|
||||
|
||||
int mode = args->mode;
|
||||
struct link_map *new = args->map;
|
||||
|
||||
/* Run the initializer functions of new objects. Temporarily
|
||||
disable the exception handler, so that lazy binding failures are
|
||||
fatal. */
|
||||
@@ -886,7 +901,7 @@ no more namespaces available for dlmopen()"));
|
||||
/* Avoid keeping around a dangling reference to the libc.so link
|
||||
map in case it has been cached in libc_map. */
|
||||
if (!args.libc_already_loaded)
|
||||
GL(dl_ns)[nsid].libc_map = NULL;
|
||||
GL(dl_ns)[args.nsid].libc_map = NULL;
|
||||
|
||||
/* Remove the object from memory. It may be in an inconsistent
|
||||
state if relocation failed, for example. */
|
||||
@@ -899,8 +914,6 @@ no more namespaces available for dlmopen()"));
|
||||
the flag here. */
|
||||
}
|
||||
|
||||
assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
|
||||
|
||||
/* Release the lock. */
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
|
||||
|
||||
@@ -19,9 +19,16 @@
|
||||
#if ENABLE_STATIC_PIE
|
||||
/* Mark symbols hidden in static PIE for early self relocation to work. */
|
||||
# pragma GCC visibility push(hidden)
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#include <dl-machine.h>
|
||||
|
||||
#define STATIC_PIE_BOOTSTRAP
|
||||
#define RESOLVE_MAP(map, scope, sym, version, flags) map
|
||||
#include "dynamic-link.h"
|
||||
#include "get-dynamic-info.h"
|
||||
|
||||
/* Relocate static executable with PIE. */
|
||||
|
||||
@@ -30,25 +37,30 @@ _dl_relocate_static_pie (void)
|
||||
{
|
||||
struct link_map *main_map = _dl_get_dl_main_map ();
|
||||
|
||||
# define STATIC_PIE_BOOTSTRAP
|
||||
# define BOOTSTRAP_MAP (main_map)
|
||||
# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
|
||||
# include "dynamic-link.h"
|
||||
|
||||
/* Figure out the run-time load address of static PIE. */
|
||||
main_map->l_addr = elf_machine_load_address ();
|
||||
|
||||
/* Read our own dynamic section and fill in the info array. */
|
||||
main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
|
||||
elf_get_dynamic_info (main_map, NULL);
|
||||
|
||||
const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
|
||||
size_t phnum = GL(dl_phnum);
|
||||
for (ph = phdr; ph < &phdr[phnum]; ++ph)
|
||||
if (ph->p_type == PT_DYNAMIC)
|
||||
{
|
||||
main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
|
||||
break;
|
||||
}
|
||||
|
||||
elf_get_dynamic_info (main_map);
|
||||
|
||||
# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info);
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (main_map, main_map->l_info);
|
||||
# endif
|
||||
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0);
|
||||
ELF_DYNAMIC_RELOCATE (main_map, NULL, 0, 0, 0);
|
||||
main_map->l_relocated = 1;
|
||||
|
||||
/* Initialize _r_debug. */
|
||||
|
||||
+45
-32
@@ -162,6 +162,32 @@ _dl_nothread_init_static_tls (struct link_map *map)
|
||||
}
|
||||
#endif /* !THREAD_GSCOPE_IN_TCB */
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(l, scope, ref, version, r_type) \
|
||||
((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||
&& __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \
|
||||
? ((__glibc_unlikely ((*ref) == l->l_lookup_cache.sym) \
|
||||
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
|
||||
? (bump_num_cache_relocations (), \
|
||||
(*ref) = l->l_lookup_cache.ret, \
|
||||
l->l_lookup_cache.value) \
|
||||
: ({ lookup_t _lr; \
|
||||
int _tc = elf_machine_type_class (r_type); \
|
||||
l->l_lookup_cache.type_class = _tc; \
|
||||
l->l_lookup_cache.sym = (*ref); \
|
||||
const struct r_found_version *v = NULL; \
|
||||
if ((version) != NULL && (version)->hash != 0) \
|
||||
v = (version); \
|
||||
_lr = _dl_lookup_symbol_x ((const char *) D_PTR (l, l_info[DT_STRTAB]) + (*ref)->st_name, \
|
||||
l, (ref), scope, v, _tc, \
|
||||
DL_LOOKUP_ADD_DEPENDENCY \
|
||||
| DL_LOOKUP_FOR_RELOCATE, NULL); \
|
||||
l->l_lookup_cache.ret = (*ref); \
|
||||
l->l_lookup_cache.value = _lr; })) \
|
||||
: l)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
void
|
||||
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
int reloc_mode, int consider_profiling)
|
||||
@@ -179,12 +205,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
|
||||
|
||||
#ifdef SHARED
|
||||
bool consider_symbind = false;
|
||||
/* If we are auditing, install the same handlers we need for profiling. */
|
||||
if ((reloc_mode & __RTLD_AUDIT) == 0)
|
||||
consider_profiling |= GLRO(dl_audit) != NULL;
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
/* Profiling is needed only if PLT hooks are provided. */
|
||||
if (afct->ARCH_LA_PLTENTER != NULL
|
||||
|| afct->ARCH_LA_PLTEXIT != NULL)
|
||||
consider_profiling = 1;
|
||||
if (afct->symbind != NULL)
|
||||
consider_symbind = true;
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
#elif defined PROF
|
||||
/* Never use dynamic linker profiling for gprof profiling code. */
|
||||
# define consider_profiling 0
|
||||
#else
|
||||
# define consider_symbind 0
|
||||
#endif
|
||||
|
||||
if (l->l_relocated)
|
||||
@@ -243,39 +285,10 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
{
|
||||
/* Do the actual relocation of the object's GOT and other data. */
|
||||
|
||||
/* String table object symbols. */
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, r_type) \
|
||||
((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||
&& __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \
|
||||
? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
|
||||
&& elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
|
||||
? (bump_num_cache_relocations (), \
|
||||
(*ref) = l->l_lookup_cache.ret, \
|
||||
l->l_lookup_cache.value) \
|
||||
: ({ lookup_t _lr; \
|
||||
int _tc = elf_machine_type_class (r_type); \
|
||||
l->l_lookup_cache.type_class = _tc; \
|
||||
l->l_lookup_cache.sym = (*ref); \
|
||||
const struct r_found_version *v = NULL; \
|
||||
if ((version) != NULL && (version)->hash != 0) \
|
||||
v = (version); \
|
||||
_lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
|
||||
scope, v, _tc, \
|
||||
DL_LOOKUP_ADD_DEPENDENCY \
|
||||
| DL_LOOKUP_FOR_RELOCATE, NULL); \
|
||||
l->l_lookup_cache.ret = (*ref); \
|
||||
l->l_lookup_cache.value = _lr; })) \
|
||||
: l)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
|
||||
ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
|
||||
|
||||
#ifndef PROF
|
||||
if (__glibc_unlikely (consider_profiling)
|
||||
if ((consider_profiling || consider_symbind)
|
||||
&& l->l_info[DT_PLTRELSZ] != NULL)
|
||||
{
|
||||
/* Allocate the array which will contain the already found
|
||||
|
||||
+37
-216
@@ -16,9 +16,8 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
@@ -30,19 +29,6 @@
|
||||
#include <dl-runtime.h>
|
||||
|
||||
|
||||
#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|
||||
|| ELF_MACHINE_NO_REL
|
||||
# define PLTREL ElfW(Rela)
|
||||
#else
|
||||
# define PLTREL ElfW(Rel)
|
||||
#endif
|
||||
|
||||
/* The fixup functions might have need special attributes. If none
|
||||
are provided define the macro as empty. */
|
||||
#ifndef ARCH_FIXUP_ATTRIBUTE
|
||||
# define ARCH_FIXUP_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
/* This function is called through a special trampoline from the PLT the
|
||||
first time each PLT entry is called. We must perform the relocation
|
||||
specified in the PLT of the given shared object, and return the resolved
|
||||
@@ -51,7 +37,7 @@
|
||||
function. */
|
||||
|
||||
DL_FIXUP_VALUE_TYPE
|
||||
attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
|
||||
attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE
|
||||
_dl_fixup (
|
||||
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
@@ -138,6 +124,37 @@ _dl_fixup (
|
||||
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
|
||||
value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have a new binding. Provide the auditing
|
||||
libraries the possibility to change the value and tell us whether further
|
||||
auditing is wanted.
|
||||
The l_reloc_result is only allocated if there is an audit module which
|
||||
provides a la_symbind. */
|
||||
if (l->l_reloc_result != NULL)
|
||||
{
|
||||
/* This is the address in the array where we store the result of previous
|
||||
relocations. */
|
||||
struct reloc_result *reloc_result
|
||||
= &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
|
||||
unsigned int init = atomic_load_acquire (&reloc_result->init);
|
||||
if (init == 0)
|
||||
{
|
||||
_dl_audit_symbind (l, reloc_result, sym, &value, result);
|
||||
|
||||
/* Store the result for later runs. */
|
||||
if (__glibc_likely (! GLRO(dl_bind_not)))
|
||||
{
|
||||
reloc_result->addr = value;
|
||||
/* Guarantee all previous writes complete before init is
|
||||
updated. See CONCURRENCY NOTES below. */
|
||||
atomic_store_release (&reloc_result->init, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
value = reloc_result->addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Finally, fix up the plt itself. */
|
||||
if (__glibc_unlikely (GLRO(dl_bind_not)))
|
||||
return value;
|
||||
@@ -147,7 +164,8 @@ _dl_fixup (
|
||||
|
||||
#ifndef PROF
|
||||
DL_FIXUP_VALUE_TYPE
|
||||
__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
|
||||
__attribute ((noinline))
|
||||
DL_ARCH_FIXUP_ATTRIBUTE
|
||||
_dl_profile_fixup (
|
||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||
@@ -296,84 +314,7 @@ _dl_profile_fixup (
|
||||
auditing libraries the possibility to change the value and
|
||||
tell us whether further auditing is wanted. */
|
||||
if (defsym != NULL && GLRO(dl_naudit) > 0)
|
||||
{
|
||||
reloc_result->bound = result;
|
||||
/* Compute index of the symbol entry in the symbol table of
|
||||
the DSO with the definition. */
|
||||
reloc_result->boundndx = (defsym
|
||||
- (ElfW(Sym) *) D_PTR (result,
|
||||
l_info[DT_SYMTAB]));
|
||||
|
||||
/* Determine whether any of the two participating DSOs is
|
||||
interested in auditing. */
|
||||
if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
/* Synthesize a symbol record where the st_value field is
|
||||
the result. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (value);
|
||||
|
||||
/* Keep track whether there is any interest in tracing
|
||||
the call in the lower two bits. */
|
||||
assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
|
||||
assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
|
||||
reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
|
||||
|
||||
const char *strtab2 = (const void *) D_PTR (result,
|
||||
l_info[DT_STRTAB]);
|
||||
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
/* XXX Check whether both DSOs must request action or
|
||||
only one */
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *result_state
|
||||
= link_map_audit_state (result, cnt);
|
||||
if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
|
||||
&& (result_state->bindflags & LA_FLG_BINDTO) != 0)
|
||||
{
|
||||
if (afct->symbind != NULL)
|
||||
{
|
||||
uintptr_t new_value
|
||||
= afct->symbind (&sym, reloc_result->boundndx,
|
||||
&l_state->cookie,
|
||||
&result_state->cookie,
|
||||
&flags,
|
||||
strtab2 + defsym->st_name);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
flags |= LA_SYMB_ALTVALUE;
|
||||
sym.st_value = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the results for every audit library and
|
||||
store a summary in the first two bits. */
|
||||
reloc_result->enterexit
|
||||
&= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
|
||||
reloc_result->enterexit
|
||||
|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
|
||||
<< ((cnt + 1) * 2));
|
||||
}
|
||||
else
|
||||
/* If the bind flags say this auditor is not interested,
|
||||
set the bits manually. */
|
||||
reloc_result->enterexit
|
||||
|= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
|
||||
<< ((cnt + 1) * 2));
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
reloc_result->flags = flags;
|
||||
value = DL_FIXUP_ADDR_VALUE (sym.st_value);
|
||||
}
|
||||
else
|
||||
/* Set all bits since this symbol binding is not interesting. */
|
||||
reloc_result->enterexit = (1u << DL_NNS) - 1;
|
||||
}
|
||||
_dl_audit_symbind (l, reloc_result, defsym, &value, result);
|
||||
#endif
|
||||
|
||||
/* Store the result for later runs. */
|
||||
@@ -396,78 +337,7 @@ _dl_profile_fixup (
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: report the PLT entering and allow the
|
||||
auditors to change the value. */
|
||||
if (GLRO(dl_naudit) > 0
|
||||
/* Don't do anything if no auditor wants to intercept this call. */
|
||||
&& (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
|
||||
{
|
||||
/* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
|
||||
initialized earlier in this function or in another thread. */
|
||||
assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
|
||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_SYMTAB])
|
||||
+ reloc_result->boundndx);
|
||||
|
||||
/* Set up the sym parameter. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (value);
|
||||
|
||||
/* Get the symbol name. */
|
||||
const char *strtab = (const void *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_STRTAB]);
|
||||
const char *symname = strtab + sym.st_name;
|
||||
|
||||
/* Keep track of overwritten addresses. */
|
||||
unsigned int flags = reloc_result->flags;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->ARCH_LA_PLTENTER != NULL
|
||||
&& (reloc_result->enterexit
|
||||
& (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
|
||||
{
|
||||
long int new_framesize = -1;
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *bound_state
|
||||
= link_map_audit_state (reloc_result->bound, cnt);
|
||||
uintptr_t new_value
|
||||
= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
|
||||
&l_state->cookie,
|
||||
&bound_state->cookie,
|
||||
regs, &flags, symname,
|
||||
&new_framesize);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
flags |= LA_SYMB_ALTVALUE;
|
||||
sym.st_value = new_value;
|
||||
}
|
||||
|
||||
/* Remember the results for every audit library and
|
||||
store a summary in the first two bits. */
|
||||
reloc_result->enterexit
|
||||
|= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
|
||||
<< (2 * (cnt + 1)));
|
||||
|
||||
if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
|
||||
<< (2 * (cnt + 1))))
|
||||
== 0 && new_framesize != -1 && framesize != -2)
|
||||
{
|
||||
/* If this is the first call providing information,
|
||||
use it. */
|
||||
if (framesize == -1)
|
||||
framesize = new_framesize;
|
||||
/* If two pltenter calls provide conflicting information,
|
||||
use the larger value. */
|
||||
else if (new_framesize != framesize)
|
||||
framesize = MAX (new_framesize, framesize);
|
||||
}
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
value = DL_FIXUP_ADDR_VALUE (sym.st_value);
|
||||
}
|
||||
_dl_audit_pltenter (l, reloc_result, &value, regs, &framesize);
|
||||
#endif
|
||||
|
||||
/* Store the frame size information. */
|
||||
@@ -479,52 +349,3 @@ _dl_profile_fixup (
|
||||
}
|
||||
|
||||
#endif /* PROF */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
void
|
||||
ARCH_FIXUP_ATTRIBUTE
|
||||
_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
|
||||
const void *inregs, void *outregs)
|
||||
{
|
||||
#ifdef SHARED
|
||||
const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
|
||||
|
||||
/* This is the address in the array where we store the result of previous
|
||||
relocations. */
|
||||
// XXX Maybe the bound information must be stored on the stack since
|
||||
// XXX with bind_not a new value could have been stored in the meantime.
|
||||
struct reloc_result *reloc_result =
|
||||
&l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
|
||||
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_SYMTAB])
|
||||
+ reloc_result->boundndx);
|
||||
|
||||
/* Set up the sym parameter. */
|
||||
ElfW(Sym) sym = *defsym;
|
||||
sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
|
||||
|
||||
/* Get the symbol name. */
|
||||
const char *strtab = (const void *) D_PTR (reloc_result->bound,
|
||||
l_info[DT_STRTAB]);
|
||||
const char *symname = strtab + sym.st_name;
|
||||
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->ARCH_LA_PLTEXIT != NULL
|
||||
&& (reloc_result->enterexit
|
||||
& (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
|
||||
{
|
||||
struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||
struct auditstate *bound_state
|
||||
= link_map_audit_state (reloc_result->bound, cnt);
|
||||
afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
|
||||
&l_state->cookie, &bound_state->cookie,
|
||||
inregs, outregs, symname);
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Inline functions for dynamic linking.
|
||||
Copyright (C) 1995-2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _DL_STATIC_TLS_H
|
||||
#define _DL_STATIC_TLS_H
|
||||
|
||||
/* This macro is used as a callback from elf_machine_rel{a,} when a
|
||||
static TLS reloc is about to be performed. Since (in dl-load.c) we
|
||||
permit dynamic loading of objects that might use such relocs, we
|
||||
have to check whether each use is actually doable. If the object
|
||||
whose TLS segment the reference resolves to was allocated space in
|
||||
the static TLS block at startup, then it's ok. Otherwise, we make
|
||||
an attempt to allocate it in surplus space on the fly. If that
|
||||
can't be done, we fall back to the error that DF_STATIC_TLS is
|
||||
intended to produce. */
|
||||
#define HAVE_STATIC_TLS(map, sym_map) \
|
||||
(__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET \
|
||||
&& ((sym_map)->l_tls_offset \
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET), 1))
|
||||
|
||||
#define CHECK_STATIC_TLS(map, sym_map) \
|
||||
do { \
|
||||
if (!HAVE_STATIC_TLS (map, sym_map)) \
|
||||
_dl_allocate_static_tls (sym_map); \
|
||||
} while (0)
|
||||
|
||||
#define TRY_STATIC_TLS(map, sym_map) \
|
||||
(__builtin_expect ((sym_map)->l_tls_offset \
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET, 1) \
|
||||
&& (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \
|
||||
|| _dl_try_allocate_static_tls (sym_map, true) == 0))
|
||||
|
||||
int _dl_try_allocate_static_tls (struct link_map *map, bool optional)
|
||||
attribute_hidden;
|
||||
|
||||
#endif
|
||||
@@ -229,6 +229,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock)
|
||||
list of loaded objects while an object is added to or removed from
|
||||
that list. */
|
||||
__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
|
||||
/* This lock protects global and module specific TLS related data.
|
||||
E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
|
||||
GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
|
||||
accessed and when TLS related relocations are processed for a
|
||||
module. It was introduced to keep pthread_create accessing TLS
|
||||
state that is being set up. */
|
||||
__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
|
||||
|
||||
|
||||
#ifdef HAVE_AUX_VECTOR
|
||||
@@ -428,3 +435,11 @@ _dl_get_dl_main_map (void)
|
||||
return &_dl_main_map;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is used by _dl_runtime_profile, not used on static code. */
|
||||
void
|
||||
DL_ARCH_FIXUP_ATTRIBUTE
|
||||
_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
|
||||
const void *inregs, void *outregs)
|
||||
{
|
||||
}
|
||||
|
||||
+1
-46
@@ -52,54 +52,9 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
|
||||
tell us whether further auditing is wanted. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
const char *strtab = (const char *) D_PTR (result,
|
||||
l_info[DT_STRTAB]);
|
||||
/* Compute index of the symbol entry in the symbol table of
|
||||
the DSO with the definition. */
|
||||
unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
|
||||
l_info[DT_SYMTAB]));
|
||||
|
||||
if (match == NULL)
|
||||
match = _dl_sym_find_caller_link_map (caller);
|
||||
|
||||
if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
|
||||
{
|
||||
unsigned int altvalue = 0;
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
/* Synthesize a symbol record where the st_value field is
|
||||
the result. */
|
||||
ElfW(Sym) sym = *ref;
|
||||
sym.st_value = (ElfW(Addr)) value;
|
||||
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
struct auditstate *match_audit
|
||||
= link_map_audit_state (match, cnt);
|
||||
struct auditstate *result_audit
|
||||
= link_map_audit_state (result, cnt);
|
||||
if (afct->symbind != NULL
|
||||
&& ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
|
||||
|| ((result_audit->bindflags & LA_FLG_BINDTO)
|
||||
!= 0)))
|
||||
{
|
||||
unsigned int flags = altvalue | LA_SYMB_DLSYM;
|
||||
uintptr_t new_value
|
||||
= afct->symbind (&sym, ndx,
|
||||
&match_audit->cookie,
|
||||
&result_audit->cookie,
|
||||
&flags, strtab + ref->st_name);
|
||||
if (new_value != (uintptr_t) sym.st_value)
|
||||
{
|
||||
altvalue = LA_SYMB_ALTVALUE;
|
||||
sym.st_value = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
|
||||
value = (void *) sym.st_value;
|
||||
}
|
||||
_dl_audit_symbind_alt (match, ref, &value, result);
|
||||
}
|
||||
#endif
|
||||
return value;
|
||||
|
||||
+1
-1
@@ -317,7 +317,7 @@ _dl_show_auxv (void)
|
||||
[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_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 },
|
||||
|
||||
+22
-11
@@ -519,8 +519,12 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
|
||||
}
|
||||
|
||||
|
||||
/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage
|
||||
for the TLS space. The DTV may be resized, and so this function may
|
||||
call malloc to allocate that space. The loader's GL(dl_load_tls_lock)
|
||||
is taken when manipulating global TLS-related data in the loader. */
|
||||
void *
|
||||
_dl_allocate_tls_init (void *result)
|
||||
_dl_allocate_tls_init (void *result, bool init_tls)
|
||||
{
|
||||
if (result == NULL)
|
||||
/* The memory allocation failed. */
|
||||
@@ -532,7 +536,7 @@ _dl_allocate_tls_init (void *result)
|
||||
size_t maxgen = 0;
|
||||
|
||||
/* Protects global dynamic TLS related state. */
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
/* Check if the current dtv is big enough. */
|
||||
if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
|
||||
@@ -593,7 +597,14 @@ _dl_allocate_tls_init (void *result)
|
||||
some platforms use in static programs requires it. */
|
||||
dtv[map->l_tls_modid].pointer.val = dest;
|
||||
|
||||
/* Copy the initialization image and clear the BSS part. */
|
||||
/* Copy the initialization image and clear the BSS part. For
|
||||
audit modules or dependencies with initial-exec TLS, we can not
|
||||
set the initial TLS image on default loader initialization
|
||||
because it would already be set by the audit setup. However,
|
||||
subsequent thread creation would need to follow the default
|
||||
behaviour. */
|
||||
if (map->l_ns != LM_ID_BASE && !init_tls)
|
||||
continue;
|
||||
memset (__mempcpy (dest, map->l_tls_initimage,
|
||||
map->l_tls_initimage_size), '\0',
|
||||
map->l_tls_blocksize - map->l_tls_initimage_size);
|
||||
@@ -606,7 +617,7 @@ _dl_allocate_tls_init (void *result)
|
||||
listp = listp->next;
|
||||
assert (listp != NULL);
|
||||
}
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
/* The DTV version is up-to-date now. */
|
||||
dtv[0].counter = maxgen;
|
||||
@@ -620,7 +631,7 @@ _dl_allocate_tls (void *mem)
|
||||
{
|
||||
return _dl_allocate_tls_init (mem == NULL
|
||||
? _dl_allocate_tls_storage ()
|
||||
: allocate_dtv (mem));
|
||||
: allocate_dtv (mem), true);
|
||||
}
|
||||
rtld_hidden_def (_dl_allocate_tls)
|
||||
|
||||
@@ -745,7 +756,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
|
||||
Here the dtv needs to be updated to new_gen generation count.
|
||||
|
||||
This code may be called during TLS access when GL(dl_load_lock)
|
||||
This code may be called during TLS access when GL(dl_load_tls_lock)
|
||||
is not held. In that case the user code has to synchronize with
|
||||
dlopen and dlclose calls of relevant modules. A module m is
|
||||
relevant if the generation of m <= new_gen and dlclose of m is
|
||||
@@ -867,11 +878,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
if (__glibc_unlikely (the_map->l_tls_offset
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET))
|
||||
{
|
||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_lock_recursive (GL(dl_load_tls_lock));
|
||||
if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
|
||||
{
|
||||
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
}
|
||||
else if (__glibc_likely (the_map->l_tls_offset
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET))
|
||||
@@ -883,7 +894,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
#else
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
|
||||
dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
|
||||
dtv[GET_ADDR_MODULE].pointer.val = p;
|
||||
@@ -891,7 +902,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
return (char *) p + GET_ADDR_OFFSET;
|
||||
}
|
||||
else
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
|
||||
}
|
||||
struct dtv_pointer result = allocate_and_init (the_map);
|
||||
dtv[GET_ADDR_MODULE].pointer = result;
|
||||
@@ -962,7 +973,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
|
||||
return NULL;
|
||||
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
/* This may be called without holding the GL(dl_load_lock). Reading
|
||||
/* This may be called without holding the GL(dl_load_tls_lock). Reading
|
||||
arbitrary gen value is fine since this is best effort code. */
|
||||
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
|
||||
+50
-19
@@ -16,6 +16,8 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <ldsodefs.h>
|
||||
|
||||
/* This file may be included twice, to define both
|
||||
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
|
||||
|
||||
@@ -37,8 +39,8 @@
|
||||
relocations; they should be set up to call _dl_runtime_resolve, rather
|
||||
than fully resolved now. */
|
||||
|
||||
auto inline void __attribute__ ((always_inline))
|
||||
elf_dynamic_do_Rel (struct link_map *map,
|
||||
static inline void __attribute__ ((always_inline))
|
||||
elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
ElfW(Addr) reladdr, ElfW(Addr) relsize,
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
|
||||
int lazy, int skip_ifunc)
|
||||
@@ -68,13 +70,13 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
}
|
||||
else
|
||||
# endif
|
||||
elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
|
||||
elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
|
||||
|
||||
# ifdef ELF_MACHINE_IRELATIVE
|
||||
if (r2 != NULL)
|
||||
for (; r2 <= end2; ++r2)
|
||||
if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc);
|
||||
elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
@@ -123,6 +125,10 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
|
||||
for (; r < end; ++r)
|
||||
{
|
||||
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
|
||||
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
|
||||
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
|
||||
const struct r_found_version *rversion = &map->l_versions[ndx];
|
||||
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
|
||||
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
{
|
||||
@@ -133,10 +139,19 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
}
|
||||
#endif
|
||||
|
||||
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
|
||||
&map->l_versions[ndx],
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
|
||||
skip_ifunc);
|
||||
#if defined SHARED && !defined RTLD_BOOTSTRAP
|
||||
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
|
||||
&& GLRO(dl_naudit) > 0)
|
||||
{
|
||||
struct link_map *sym_map
|
||||
= RESOLVE_MAP (map, scope, &sym, rversion,
|
||||
ELF_MACHINE_JMP_SLOT);
|
||||
if (sym != NULL)
|
||||
_dl_audit_symbind (map, NULL, sym, r_addr_arg, sym_map);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
|
||||
@@ -146,7 +161,7 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
{
|
||||
ElfW(Half) ndx
|
||||
= version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
|
||||
elf_machine_rel (map, r2,
|
||||
elf_machine_rel (map, scope, r2,
|
||||
&symtab[ELFW(R_SYM) (r2->r_info)],
|
||||
&map->l_versions[ndx],
|
||||
(void *) (l_addr + r2->r_offset),
|
||||
@@ -158,23 +173,39 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
else
|
||||
{
|
||||
for (; r < end; ++r)
|
||||
{
|
||||
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
|
||||
void *const r_addr_arg = (void *) (l_addr + r->r_offset);
|
||||
# ifdef ELF_MACHINE_IRELATIVE
|
||||
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
{
|
||||
if (r2 == NULL)
|
||||
r2 = r;
|
||||
end2 = r;
|
||||
}
|
||||
else
|
||||
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
{
|
||||
if (r2 == NULL)
|
||||
r2 = r;
|
||||
end2 = r;
|
||||
continue;
|
||||
}
|
||||
# endif
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
|
||||
skip_ifunc);
|
||||
# if defined SHARED && !defined RTLD_BOOTSTRAP
|
||||
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
|
||||
&& GLRO(dl_naudit) > 0)
|
||||
{
|
||||
struct link_map *sym_map
|
||||
= RESOLVE_MAP (map, scope, &sym,
|
||||
(struct r_found_version *) NULL,
|
||||
ELF_MACHINE_JMP_SLOT);
|
||||
if (sym != NULL)
|
||||
_dl_audit_symbind (map, NULL , sym,r_addr_arg, sym_map);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef ELF_MACHINE_IRELATIVE
|
||||
if (r2 != NULL)
|
||||
for (; r2 <= end2; ++r2)
|
||||
if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
|
||||
elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
|
||||
NULL, (void *) (l_addr + r2->r_offset),
|
||||
skip_ifunc);
|
||||
# endif
|
||||
|
||||
+31
-61
@@ -16,35 +16,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This macro is used as a callback from elf_machine_rel{a,} when a
|
||||
static TLS reloc is about to be performed. Since (in dl-load.c) we
|
||||
permit dynamic loading of objects that might use such relocs, we
|
||||
have to check whether each use is actually doable. If the object
|
||||
whose TLS segment the reference resolves to was allocated space in
|
||||
the static TLS block at startup, then it's ok. Otherwise, we make
|
||||
an attempt to allocate it in surplus space on the fly. If that
|
||||
can't be done, we fall back to the error that DF_STATIC_TLS is
|
||||
intended to produce. */
|
||||
#define HAVE_STATIC_TLS(map, sym_map) \
|
||||
(__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET \
|
||||
&& ((sym_map)->l_tls_offset \
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET), 1))
|
||||
|
||||
#define CHECK_STATIC_TLS(map, sym_map) \
|
||||
do { \
|
||||
if (!HAVE_STATIC_TLS (map, sym_map)) \
|
||||
_dl_allocate_static_tls (sym_map); \
|
||||
} while (0)
|
||||
|
||||
#define TRY_STATIC_TLS(map, sym_map) \
|
||||
(__builtin_expect ((sym_map)->l_tls_offset \
|
||||
!= FORCED_DYNAMIC_TLS_OFFSET, 1) \
|
||||
&& (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \
|
||||
|| _dl_try_allocate_static_tls (sym_map, true) == 0))
|
||||
|
||||
int _dl_try_allocate_static_tls (struct link_map *map, bool optional)
|
||||
attribute_hidden;
|
||||
|
||||
#include <dl-machine.h>
|
||||
#include <elf.h>
|
||||
|
||||
#ifdef RESOLVE_MAP
|
||||
@@ -59,40 +31,38 @@ int _dl_try_allocate_static_tls (struct link_map *map, bool optional)
|
||||
copying memory, breaking the very code written to handle the
|
||||
unaligned cases. */
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
|
||||
const ElfW(Sym) *sym, const struct r_found_version *version,
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
const ElfW(Rel) *reloc, const ElfW(Sym) *sym,
|
||||
const struct r_found_version *version,
|
||||
void *const reloc_addr, int skip_ifunc);
|
||||
auto inline void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
|
||||
void *const reloc_addr);
|
||||
# endif
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
const ElfW(Sym) *sym, const struct r_found_version *version,
|
||||
void *const reloc_addr, int skip_ifunc);
|
||||
auto inline void __attribute__((always_inline))
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
|
||||
const struct r_found_version *version, void *const reloc_addr,
|
||||
int skip_ifunc);
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
|
||||
void *const reloc_addr);
|
||||
# endif
|
||||
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_lazy_rel (struct link_map *map,
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
|
||||
int skip_ifunc);
|
||||
# else
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_lazy_rel (struct link_map *map,
|
||||
static inline void __attribute__((always_inline))
|
||||
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
|
||||
int skip_ifunc);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <dl-machine.h>
|
||||
|
||||
#include "get-dynamic-info.h"
|
||||
|
||||
#ifdef RESOLVE_MAP
|
||||
|
||||
# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
|
||||
@@ -114,7 +84,7 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
|
||||
are completely separate and there is a gap between them. */
|
||||
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; \
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
|
||||
@@ -152,18 +122,18 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
} \
|
||||
\
|
||||
if (ELF_DURING_STARTUP) \
|
||||
elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, \
|
||||
ranges[0].nrelative, 0, skip_ifunc); \
|
||||
elf_dynamic_do_##reloc ((map), scope, ranges[0].start, ranges[0].size, \
|
||||
ranges[0].nrelative, 0, skip_ifunc); \
|
||||
else \
|
||||
{ \
|
||||
int ranges_index; \
|
||||
for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc ((map), \
|
||||
elf_dynamic_do_##reloc ((map), scope, \
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].nrelative, \
|
||||
ranges[ranges_index].lazy, \
|
||||
skip_ifunc); \
|
||||
skip_ifunc); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -175,29 +145,29 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
# define DO_RELA
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
/* This can't just be an inline function because GCC is too dumb
|
||||
to inline functions containing inlines themselves. */
|
||||
# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \
|
||||
# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
|
||||
do { \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
|
||||
(consider_profile)); \
|
||||
ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
+14
-38
@@ -16,19 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This file is included multiple times and therefore lacks a header
|
||||
file inclusion guard. */
|
||||
/* Populate dynamic tags in l_info. */
|
||||
|
||||
#ifndef _GET_DYNAMIC_INFO_H
|
||||
#define _GET_DYNAMIC_INFO_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <dl-machine-rel.h>
|
||||
#include <libc-diag.h>
|
||||
|
||||
#ifndef RESOLVE_MAP
|
||||
static
|
||||
#else
|
||||
auto
|
||||
#endif
|
||||
inline void __attribute__ ((unused, always_inline))
|
||||
elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
static inline void __attribute__ ((unused, always_inline))
|
||||
elf_get_dynamic_info (struct link_map *l)
|
||||
{
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
typedef Elf32_Word d_tag_utype;
|
||||
@@ -36,7 +34,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
typedef Elf64_Xword d_tag_utype;
|
||||
#endif
|
||||
|
||||
#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP
|
||||
#ifndef STATIC_PIE_BOOTSTRAP
|
||||
if (l->l_ld == NULL)
|
||||
return;
|
||||
#endif
|
||||
@@ -69,28 +67,15 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
info[i] = dyn;
|
||||
}
|
||||
|
||||
#define DL_RO_DYN_TEMP_CNT 8
|
||||
|
||||
#ifndef DL_RO_DYN_SECTION
|
||||
/* Don't adjust .dynamic unnecessarily. */
|
||||
if (l->l_addr != 0)
|
||||
if (l->l_addr != 0 && dl_relocate_ld (l))
|
||||
{
|
||||
ElfW(Addr) l_addr = l->l_addr;
|
||||
int cnt = 0;
|
||||
|
||||
# define ADJUST_DYN_INFO(tag) \
|
||||
do \
|
||||
if (info[tag] != NULL) \
|
||||
{ \
|
||||
if (temp) \
|
||||
{ \
|
||||
temp[cnt].d_tag = info[tag]->d_tag; \
|
||||
temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \
|
||||
info[tag] = temp + cnt++; \
|
||||
} \
|
||||
else \
|
||||
info[tag]->d_un.d_ptr += l_addr; \
|
||||
} \
|
||||
info[tag]->d_un.d_ptr += l_addr; \
|
||||
while (0)
|
||||
|
||||
ADJUST_DYN_INFO (DT_HASH);
|
||||
@@ -107,9 +92,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
|
||||
ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
|
||||
# undef ADJUST_DYN_INFO
|
||||
assert (cnt <= DL_RO_DYN_TEMP_CNT);
|
||||
}
|
||||
#endif
|
||||
if (info[DT_PLTREL] != NULL)
|
||||
{
|
||||
#if ELF_MACHINE_NO_RELA
|
||||
@@ -129,18 +112,10 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
if (info[DT_REL] != NULL)
|
||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
||||
#endif
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
/* Only the bind now flags are allowed. */
|
||||
assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
|
||||
|| (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
|
||||
/* Flags must not be set for ld.so. */
|
||||
assert (info[DT_FLAGS] == NULL
|
||||
|| (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
|
||||
#endif
|
||||
#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
|
||||
#ifdef STATIC_PIE_BOOTSTRAP
|
||||
assert (info[DT_RUNPATH] == NULL);
|
||||
assert (info[DT_RPATH] == NULL);
|
||||
#else
|
||||
#endif
|
||||
if (info[DT_FLAGS] != NULL)
|
||||
{
|
||||
/* Flags are used. Translate to the old form where available.
|
||||
@@ -178,5 +153,6 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
if (info[DT_RUNPATH] != NULL)
|
||||
/* If both RUNPATH and RPATH are given, the latter is ignored. */
|
||||
info[DT_RPATH] = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+5
-1
@@ -503,7 +503,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||
entry->path[--i] = '\0';
|
||||
|
||||
if (i == 0)
|
||||
return;
|
||||
{
|
||||
free (entry->path);
|
||||
free (entry);
|
||||
return;
|
||||
}
|
||||
|
||||
char *path = entry->path;
|
||||
if (opt_chroot != NULL)
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ struct link_map
|
||||
#ifdef __USE_GNU
|
||||
|
||||
/* Version numbers for la_version handshake interface. */
|
||||
#define LAV_CURRENT 1
|
||||
#include <bits/link_lavcurrent.h>
|
||||
|
||||
/* Activity types signaled through la_activity. */
|
||||
enum
|
||||
|
||||
+38
-80
@@ -32,7 +32,6 @@
|
||||
#include <fpu_control.h>
|
||||
#include <hp-timing.h>
|
||||
#include <libc-lock.h>
|
||||
#include "dynamic-link.h"
|
||||
#include <dl-librecon.h>
|
||||
#include <unsecvars.h>
|
||||
#include <dl-cache.h>
|
||||
@@ -50,9 +49,19 @@
|
||||
#include <dl-main.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <dl-tunables.h>
|
||||
#include <get-dynamic-info.h>
|
||||
#include <dl-audit-check.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation.
|
||||
Since ld.so must not have any undefined symbols the result
|
||||
is trivial: always the map of ld.so itself. */
|
||||
#define RTLD_BOOTSTRAP
|
||||
#define RESOLVE_MAP(map, scope, sym, version, flags) map
|
||||
#include "dynamic-link.h"
|
||||
|
||||
/* Only enables rtld profiling for architectures which provides non generic
|
||||
hp-timing support. The generic support requires either syscall
|
||||
(clock_gettime), which will incur in extra overhead on loading time.
|
||||
@@ -322,6 +331,7 @@ struct rtld_global _rtld_global =
|
||||
#ifdef _LIBC_REENTRANT
|
||||
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||
#endif
|
||||
._dl_nns = 1,
|
||||
._dl_ns =
|
||||
@@ -463,6 +473,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||
#ifndef DONT_USE_BOOTSTRAP_MAP
|
||||
GL(dl_rtld_map).l_addr = info->l.l_addr;
|
||||
GL(dl_rtld_map).l_ld = info->l.l_ld;
|
||||
GL(dl_rtld_map).l_ld_readonly = info->l.l_ld_readonly;
|
||||
memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
|
||||
sizeof GL(dl_rtld_map).l_info);
|
||||
GL(dl_rtld_map).l_mach = info->l.l_mach;
|
||||
@@ -499,28 +510,19 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
# define bootstrap_map GL(dl_rtld_map)
|
||||
#else
|
||||
# define bootstrap_map info.l
|
||||
#endif
|
||||
|
||||
static ElfW(Addr) __attribute_used__
|
||||
_dl_start (void *arg)
|
||||
{
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
# define bootstrap_map GL(dl_rtld_map)
|
||||
#else
|
||||
struct dl_start_final_info info;
|
||||
# define bootstrap_map info.l
|
||||
#endif
|
||||
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation.
|
||||
Since ld.so must not have any undefined symbols the result
|
||||
is trivial: always the map of ld.so itself. */
|
||||
#define RTLD_BOOTSTRAP
|
||||
#define BOOTSTRAP_MAP (&bootstrap_map)
|
||||
#define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
|
||||
#include "dynamic-link.h"
|
||||
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
rtld_timer_start (&start_time);
|
||||
#else
|
||||
struct dl_start_final_info info;
|
||||
rtld_timer_start (&info.start_time);
|
||||
#endif
|
||||
|
||||
@@ -546,14 +548,15 @@ _dl_start (void *arg)
|
||||
|
||||
/* Read our own dynamic section and fill in the info array. */
|
||||
bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
|
||||
elf_get_dynamic_info (&bootstrap_map, NULL);
|
||||
bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION;
|
||||
elf_get_dynamic_info (&bootstrap_map);
|
||||
|
||||
#if NO_TLS_OFFSET != 0
|
||||
bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
|
||||
#endif
|
||||
|
||||
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (&bootstrap_map, bootstrap_map.l_info);
|
||||
#endif
|
||||
|
||||
if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
|
||||
@@ -561,7 +564,7 @@ _dl_start (void *arg)
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, NULL, 0, 0, 0);
|
||||
}
|
||||
bootstrap_map.l_relocated = 1;
|
||||
|
||||
@@ -988,7 +991,7 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
|
||||
return;
|
||||
}
|
||||
|
||||
if (lav > LAV_CURRENT)
|
||||
if (!_dl_audit_check_version (lav))
|
||||
{
|
||||
_dl_debug_printf ("\
|
||||
ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
|
||||
@@ -1013,13 +1016,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
|
||||
"la_objsearch\0"
|
||||
"la_objopen\0"
|
||||
"la_preinit\0"
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
"la_symbind32\0"
|
||||
#elif __ELF_NATIVE_CLASS == 64
|
||||
"la_symbind64\0"
|
||||
#else
|
||||
# error "__ELF_NATIVE_CLASS must be defined"
|
||||
#endif
|
||||
LA_SYMBIND "\0"
|
||||
#define STRING(s) __STRING (s)
|
||||
"la_" STRING (ARCH_LA_PLTENTER) "\0"
|
||||
"la_" STRING (ARCH_LA_PLTEXIT) "\0"
|
||||
@@ -1061,25 +1058,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
|
||||
dlmargs.map->l_auditing = 1;
|
||||
}
|
||||
|
||||
/* Notify the the audit modules that the object MAP has already been
|
||||
loaded. */
|
||||
static void
|
||||
notify_audit_modules_of_loaded_object (struct link_map *map)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->objopen != NULL)
|
||||
{
|
||||
struct auditstate *state = link_map_audit_state (map, cnt);
|
||||
state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie);
|
||||
map->l_audit_any_plt |= state->bindflags != 0;
|
||||
}
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load all audit modules. */
|
||||
static void
|
||||
load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
|
||||
@@ -1098,8 +1076,8 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
|
||||
program and the dynamic linker itself). */
|
||||
if (GLRO(dl_naudit) > 0)
|
||||
{
|
||||
notify_audit_modules_of_loaded_object (main_map);
|
||||
notify_audit_modules_of_loaded_object (&GL(dl_rtld_map));
|
||||
_dl_audit_objopen (main_map, LM_ID_BASE);
|
||||
_dl_audit_objopen (&GL(dl_rtld_map), LM_ID_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1468,6 +1446,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* This tells us where to find the dynamic section,
|
||||
which tells us everything we need to do. */
|
||||
main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr;
|
||||
main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
|
||||
break;
|
||||
case PT_INTERP:
|
||||
/* This "interpreter segment" was used by the program loader to
|
||||
@@ -1613,7 +1592,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
if (! rtld_is_main)
|
||||
{
|
||||
/* Extract the contents of the dynamic section for easy access. */
|
||||
elf_get_dynamic_info (main_map, NULL);
|
||||
elf_get_dynamic_info (main_map);
|
||||
|
||||
/* If the main map is libc.so, update the base namespace to
|
||||
refer to this map. If libc.so is loaded later, this happens
|
||||
@@ -1783,18 +1762,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
/* Auditing checkpoint: we are ready to signal that the initial map
|
||||
is being constructed. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
afct->activity (&link_map_audit_state (main_map, cnt)->cookie,
|
||||
LA_ACT_ADD);
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
_dl_audit_activity_map (main_map, LA_ACT_ADD);
|
||||
|
||||
/* We have two ways to specify objects to preload: via environment
|
||||
variable and via the file /etc/ld.so.preload. The latter can also
|
||||
@@ -1918,6 +1886,12 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
assert (i == npreloads);
|
||||
}
|
||||
|
||||
#ifdef NEED_DL_SYSINFO_DSO
|
||||
/* Now that the audit modules are opened, call la_objopen for the vDSO. */
|
||||
if (GLRO(dl_sysinfo_map) != NULL)
|
||||
_dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE);
|
||||
#endif
|
||||
|
||||
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
|
||||
specified some libraries to load, these are inserted before the actual
|
||||
dependencies in the executable's searchlist for symbol resolution. */
|
||||
@@ -2419,7 +2393,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
into the main thread's TLS area, which we allocated above.
|
||||
Note: thread-local variables must only be accessed after completing
|
||||
the next step. */
|
||||
_dl_allocate_tls_init (tcbp);
|
||||
_dl_allocate_tls_init (tcbp, false);
|
||||
|
||||
/* And finally install it for the main thread. */
|
||||
if (! tls_init_tp_called)
|
||||
@@ -2475,23 +2449,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
#ifdef SHARED
|
||||
/* Auditing checkpoint: we have added all objects. */
|
||||
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||
{
|
||||
struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
/* Do not call the functions for any auditing object. */
|
||||
if (head->l_auditing == 0)
|
||||
{
|
||||
struct audit_ifaces *afct = GLRO(dl_audit);
|
||||
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||
{
|
||||
if (afct->activity != NULL)
|
||||
afct->activity (&link_map_audit_state (head, cnt)->cookie,
|
||||
LA_ACT_CONSISTENT);
|
||||
|
||||
afct = afct->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
|
||||
#endif
|
||||
|
||||
/* Notify the debugger all new objects are now ready to go. We must re-get
|
||||
|
||||
+3
-4
@@ -30,11 +30,9 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
|
||||
We just want our data structures to describe it as if we had just
|
||||
mapped and relocated it normally. */
|
||||
struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
|
||||
0, LM_ID_BASE);
|
||||
__RTLD_VDSO, LM_ID_BASE);
|
||||
if (__glibc_likely (l != NULL))
|
||||
{
|
||||
static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
|
||||
|
||||
l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
|
||||
+ GLRO(dl_sysinfo_dso)->e_phoff);
|
||||
l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
|
||||
@@ -45,6 +43,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
|
||||
{
|
||||
l->l_ld = (void *) ph->p_vaddr;
|
||||
l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
|
||||
l->l_ld_readonly = (ph->p_flags & PF_W) == 0;
|
||||
}
|
||||
else if (ph->p_type == PT_LOAD)
|
||||
{
|
||||
@@ -65,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
|
||||
l->l_map_end += l->l_addr;
|
||||
l->l_text_end += l->l_addr;
|
||||
l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
|
||||
elf_get_dynamic_info (l, dyn_temp);
|
||||
elf_get_dynamic_info (l);
|
||||
_dl_setup_hash (l);
|
||||
l->l_relocated = 1;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <err.h>
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
@@ -232,6 +233,12 @@ uintptr_t
|
||||
la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||
{
|
||||
if (*flags & LA_SYMB_NOPLTENTER)
|
||||
warnx ("cannot trace PLT enter (bind-now enabled)");
|
||||
|
||||
if (do_exit && *flags & LA_SYMB_NOPLTEXIT)
|
||||
warnx ("cannot trace PLT exit (bind-now enabled)");
|
||||
|
||||
if (!do_exit)
|
||||
*flags = LA_SYMB_NOPLTEXIT;
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/* DT_AUDIT with modules with TLSDESC.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
#include <support/xdlfcn.h>
|
||||
|
||||
static void *
|
||||
thr_func (void *mod)
|
||||
{
|
||||
int* (*get_global1)(void) = xdlsym (mod, "get_global1");
|
||||
int* (*get_global2)(void) = xdlsym (mod, "get_global2");
|
||||
void (*set_global2)(int) = xdlsym (mod, "set_global2");
|
||||
int* (*get_local1)(void) = xdlsym (mod, "get_local1");
|
||||
int* (*get_local2)(void) = xdlsym (mod, "get_local2");
|
||||
|
||||
int *global1 = get_global1 ();
|
||||
TEST_COMPARE (*global1, 0);
|
||||
++*global1;
|
||||
|
||||
int *global2 = get_global2 ();
|
||||
TEST_COMPARE (*global2, 0);
|
||||
++*global2;
|
||||
TEST_COMPARE (*global2, 1);
|
||||
|
||||
set_global2 (10);
|
||||
TEST_COMPARE (*global2, 10);
|
||||
|
||||
int *local1 = get_local1 ();
|
||||
TEST_COMPARE (*local1, 0);
|
||||
++*local1;
|
||||
|
||||
int *local2 = get_local2 ();
|
||||
TEST_COMPARE (*local2, 0);
|
||||
++*local2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *mod = xdlopen ("tst-audit-tlsdesc-mod1.so", RTLD_LAZY);
|
||||
|
||||
pthread_t thr = xpthread_create (NULL, thr_func, mod);
|
||||
void *r = xpthread_join (thr);
|
||||
TEST_VERIFY (r == NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,41 @@
|
||||
/* DT_AUDIT with modules with TLSDESC.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
__thread int global1;
|
||||
|
||||
int *
|
||||
get_global1 (void)
|
||||
{
|
||||
return &global1;
|
||||
}
|
||||
|
||||
static __thread int local1;
|
||||
|
||||
void *
|
||||
get_local1 (void)
|
||||
{
|
||||
return &local1;
|
||||
}
|
||||
|
||||
extern __thread int global2;
|
||||
|
||||
void
|
||||
set_global2 (int v)
|
||||
{
|
||||
global2 = v;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* DT_AUDIT with modules with TLSDESC.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
__thread int global2;
|
||||
|
||||
int *
|
||||
get_global2 (void)
|
||||
{
|
||||
return &global2;
|
||||
}
|
||||
|
||||
static __thread int local2;
|
||||
|
||||
void *
|
||||
get_local2 (void)
|
||||
{
|
||||
return &local2;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/* DT_AUDIT with modules with TLSDESC.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/xthread.h>
|
||||
|
||||
extern __thread int global1;
|
||||
extern __thread int global2;
|
||||
void *get_local1 (void);
|
||||
void set_global2 (int v);
|
||||
void *get_local2 (void);
|
||||
|
||||
static void *
|
||||
thr_func (void *clousure)
|
||||
{
|
||||
TEST_COMPARE (global1, 0);
|
||||
++global1;
|
||||
TEST_COMPARE (global2, 0);
|
||||
++global2;
|
||||
TEST_COMPARE (global2, 1);
|
||||
|
||||
set_global2 (10);
|
||||
TEST_COMPARE (global2, 10);
|
||||
|
||||
int *local1 = get_local1 ();
|
||||
TEST_COMPARE (*local1, 0);
|
||||
++*local1;
|
||||
|
||||
int *local2 = get_local2 ();
|
||||
TEST_COMPARE (*local2, 0);
|
||||
++*local2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pthread_t thr = xpthread_create (NULL, thr_func, NULL);
|
||||
void *r = xpthread_join (thr);
|
||||
TEST_VERIFY (r == NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,129 @@
|
||||
/* Check DT_AUDIT with dlmopen.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <array_length.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/support.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
{
|
||||
void *h = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
|
||||
|
||||
pid_t (*s) (void) = xdlsym (h, "getpid");
|
||||
TEST_COMPARE (s (), getpid ());
|
||||
|
||||
xdlclose (h);
|
||||
}
|
||||
|
||||
{
|
||||
void *h = xdlmopen (LM_ID_NEWLM, "tst-audit18mod.so", RTLD_NOW);
|
||||
|
||||
int (*foo) (void) = xdlsym (h, "foo");
|
||||
TEST_COMPARE (foo (), 10);
|
||||
|
||||
xdlclose (h);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
/* We must have either:
|
||||
- One our fource parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
char *spargv[9];
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod18.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit18", 0, sc_allow_stderr);
|
||||
|
||||
struct
|
||||
{
|
||||
const char *name;
|
||||
bool found;
|
||||
} audit_iface[] =
|
||||
{
|
||||
{ "la_version", false },
|
||||
{ "la_objsearch", false },
|
||||
{ "la_activity", false },
|
||||
{ "la_objopen", false },
|
||||
{ "la_objclose", false },
|
||||
{ "la_preinit", false },
|
||||
#if __WORDSIZE == 32
|
||||
{ "la_symbind32", false },
|
||||
#elif __WORDSIZE == 64
|
||||
{ "la_symbind64", false },
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Some hooks are called more than once but the test only check if any
|
||||
is called at least once. */
|
||||
FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
|
||||
TEST_VERIFY (out != NULL);
|
||||
char *buffer = NULL;
|
||||
size_t buffer_length = 0;
|
||||
while (xgetline (&buffer, &buffer_length, out))
|
||||
{
|
||||
for (int i = 0; i < array_length (audit_iface); i++)
|
||||
if (strncmp (buffer, audit_iface[i].name,
|
||||
strlen (audit_iface[i].name)) == 0)
|
||||
audit_iface[i].found = true;
|
||||
}
|
||||
free (buffer);
|
||||
xfclose (out);
|
||||
|
||||
for (int i = 0; i < array_length (audit_iface); i++)
|
||||
TEST_COMPARE (audit_iface[i].found, true);
|
||||
|
||||
support_capture_subprocess_free (&result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Check DT_AUDIT with dlmopen.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int
|
||||
foo (void)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Check if DT_AUDIT a module without la_plt{enter,exit} symbols does not incur
|
||||
in profiling (BZ#15533).
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/check.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *h = xdlopen ("tst-auditmod19a.so", RTLD_NOW);
|
||||
|
||||
struct link_map *lmap;
|
||||
TEST_VERIFY_EXIT (dlinfo (h, RTLD_DI_LINKMAP, &lmap) == 0);
|
||||
|
||||
/* The internal array is only allocated if profiling is enabled. */
|
||||
TEST_VERIFY (lmap->l_reloc_result == NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Check if DT_AUDIT a module with la_plt{enter,exit} call la_symbind
|
||||
for lazy resolution.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
int tst_audit18bmod1_func (void);
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
TEST_COMPARE (tst_audit18bmod1_func (), 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
/* We must have either:
|
||||
- One our fource parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
char *spargv[9];
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod18b.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit18b", 0, sc_allow_stderr);
|
||||
|
||||
bool find_symbind = false;
|
||||
|
||||
FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
|
||||
TEST_VERIFY (out != NULL);
|
||||
char *buffer = NULL;
|
||||
size_t buffer_length = 0;
|
||||
while (xgetline (&buffer, &buffer_length, out))
|
||||
if (startswith (buffer, "la_symbind: tst_audit18bmod1_func") == 0)
|
||||
find_symbind = true;
|
||||
|
||||
TEST_COMPARE (find_symbind, true);
|
||||
|
||||
free (buffer);
|
||||
xfclose (out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Extra module for tst-audit18b.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int
|
||||
tst_audit18bmod1_func (void)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Check dlopen failure on audit modules.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Check LD_AUDIT with static TLS.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <support/xthread.h>
|
||||
#include <support/check.h>
|
||||
|
||||
static volatile __thread int out __attribute__ ((tls_model ("initial-exec")));
|
||||
|
||||
static void *
|
||||
tf (void *arg)
|
||||
{
|
||||
TEST_COMPARE (out, 0);
|
||||
out = isspace (' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
TEST_COMPARE (out, 0);
|
||||
out = isspace (' ');
|
||||
|
||||
pthread_t t = xpthread_create (NULL, tf, NULL);
|
||||
xpthread_join (t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* Check DTAUDIT and vDSO interaction.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/support.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
static uintptr_t vdso_addr;
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
fprintf (stderr, "vdso: %p\n", (void*) vdso_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr_t
|
||||
parse_address (const char *str)
|
||||
{
|
||||
void *r;
|
||||
TEST_COMPARE (sscanf (str, "%p\n", &r), 1);
|
||||
return (uintptr_t) r;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
vdso_addr = getauxval (AT_SYSINFO_EHDR);
|
||||
if (vdso_addr == 0)
|
||||
FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0");
|
||||
|
||||
/* We must have either:
|
||||
- One our fource parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
char *spargv[9];
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod22.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
|
||||
|
||||
/* The respawned process should always print the vDSO address (otherwise it
|
||||
will fails as unsupported). However, on some architectures the audit
|
||||
module might see the vDSO with l_addr being 0, meaning a fixed mapping
|
||||
(linux-gate.so). In this case we don't check its value against
|
||||
AT_SYSINFO_EHDR one. */
|
||||
uintptr_t vdso_process = 0;
|
||||
bool vdso_audit_found = false;
|
||||
uintptr_t vdso_audit = 0;
|
||||
|
||||
FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
|
||||
TEST_VERIFY (out != NULL);
|
||||
char *buffer = NULL;
|
||||
size_t buffer_length = 0;
|
||||
while (xgetline (&buffer, &buffer_length, out))
|
||||
{
|
||||
if (startswith (buffer, "vdso: "))
|
||||
vdso_process = parse_address (buffer + strlen ("vdso: "));
|
||||
else if (startswith (buffer, "vdso found: "))
|
||||
{
|
||||
vdso_audit = parse_address (buffer + strlen ("vdso found: "));
|
||||
vdso_audit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_COMPARE (vdso_audit_found, true);
|
||||
if (vdso_audit != 0)
|
||||
TEST_COMPARE (vdso_process, vdso_audit);
|
||||
|
||||
free (buffer);
|
||||
xfclose (out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,239 @@
|
||||
/* Check for expected la_objopen and la_objeclose for all objects.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <array_length.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <link.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/support.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
xdlopen ("tst-audit23mod.so", RTLD_NOW);
|
||||
xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_vdso (const char *str)
|
||||
{
|
||||
return startswith (str, "linux-gate")
|
||||
|| startswith (str, "linux-vdso");
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
/* We must have either:
|
||||
- One or four parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
char *spargv[9];
|
||||
TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv));
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod23.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
|
||||
|
||||
/* The expected la_objopen/la_objclose:
|
||||
1. executable
|
||||
2. loader
|
||||
3. libc.so
|
||||
4. tst-audit23mod.so
|
||||
5. libc.so (LM_ID_NEWLM).
|
||||
6. vdso (optional and ignored). */
|
||||
enum { max_objs = 6 };
|
||||
struct la_obj_t
|
||||
{
|
||||
char *lname;
|
||||
uintptr_t laddr;
|
||||
Lmid_t lmid;
|
||||
bool closed;
|
||||
} objs[max_objs] = { [0 ... max_objs-1] = { .closed = false } };
|
||||
size_t nobjs = 0;
|
||||
|
||||
/* The expected namespaces are one for the audit module, one for the
|
||||
application, and another for the dlmopen on handle_restart. */
|
||||
enum { max_ns = 3 };
|
||||
uintptr_t acts[max_ns] = { 0 };
|
||||
size_t nacts = 0;
|
||||
int last_act = -1;
|
||||
uintptr_t last_act_cookie = -1;
|
||||
bool seen_first_objclose = false;
|
||||
|
||||
FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
|
||||
TEST_VERIFY (out != NULL);
|
||||
char *buffer = NULL;
|
||||
size_t buffer_length = 0;
|
||||
while (xgetline (&buffer, &buffer_length, out))
|
||||
{
|
||||
if (startswith (buffer, "la_activity: "))
|
||||
{
|
||||
uintptr_t cookie;
|
||||
int this_act;
|
||||
int r = sscanf (buffer, "la_activity: %d %"SCNxPTR"", &this_act,
|
||||
&cookie);
|
||||
TEST_COMPARE (r, 2);
|
||||
|
||||
/* The cookie identifies the object at the head of the link map,
|
||||
so we only add a new namespace if it changes from the previous
|
||||
one. This works since dlmopen is the last in the test body. */
|
||||
if (cookie != last_act_cookie && last_act_cookie != -1)
|
||||
TEST_COMPARE (last_act, LA_ACT_CONSISTENT);
|
||||
|
||||
if (this_act == LA_ACT_ADD && acts[nacts] != cookie)
|
||||
{
|
||||
acts[nacts++] = cookie;
|
||||
last_act_cookie = cookie;
|
||||
}
|
||||
/* The LA_ACT_DELETE is called in the reverse order of LA_ACT_ADD
|
||||
at program termination (if the tests adds a dlclose or a library
|
||||
with extra dependencies this will need to be adapted). */
|
||||
else if (this_act == LA_ACT_DELETE)
|
||||
{
|
||||
last_act_cookie = acts[--nacts];
|
||||
TEST_COMPARE (acts[nacts], cookie);
|
||||
acts[nacts] = 0;
|
||||
}
|
||||
else if (this_act == LA_ACT_CONSISTENT)
|
||||
{
|
||||
TEST_COMPARE (cookie, last_act_cookie);
|
||||
|
||||
/* LA_ACT_DELETE must always be followed by an la_objclose. */
|
||||
if (last_act == LA_ACT_DELETE)
|
||||
TEST_COMPARE (seen_first_objclose, true);
|
||||
else
|
||||
TEST_COMPARE (last_act, LA_ACT_ADD);
|
||||
}
|
||||
|
||||
last_act = this_act;
|
||||
seen_first_objclose = false;
|
||||
}
|
||||
else if (startswith (buffer, "la_objopen: "))
|
||||
{
|
||||
char *lname;
|
||||
uintptr_t laddr;
|
||||
Lmid_t lmid;
|
||||
uintptr_t cookie;
|
||||
int r = sscanf (buffer, "la_objopen: %"SCNxPTR" %ms %"SCNxPTR" %ld",
|
||||
&cookie, &lname, &laddr, &lmid);
|
||||
TEST_COMPARE (r, 4);
|
||||
|
||||
/* la_objclose is not triggered by vDSO because glibc does not
|
||||
unload it. */
|
||||
if (is_vdso (lname))
|
||||
continue;
|
||||
if (nobjs == max_objs)
|
||||
FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld",
|
||||
lname, laddr, lmid);
|
||||
objs[nobjs].lname = lname;
|
||||
objs[nobjs].laddr = laddr;
|
||||
objs[nobjs].lmid = lmid;
|
||||
objs[nobjs].closed = false;
|
||||
nobjs++;
|
||||
|
||||
/* This indirectly checks that la_objopen always comes before
|
||||
la_objclose btween la_activity calls. */
|
||||
seen_first_objclose = false;
|
||||
}
|
||||
else if (startswith (buffer, "la_objclose: "))
|
||||
{
|
||||
char *lname;
|
||||
uintptr_t laddr;
|
||||
Lmid_t lmid;
|
||||
uintptr_t cookie;
|
||||
int r = sscanf (buffer, "la_objclose: %"SCNxPTR" %ms %"SCNxPTR" %ld",
|
||||
&cookie, &lname, &laddr, &lmid);
|
||||
TEST_COMPARE (r, 4);
|
||||
|
||||
for (size_t i = 0; i < nobjs; i++)
|
||||
{
|
||||
if (strcmp (lname, objs[i].lname) == 0 && lmid == objs[i].lmid)
|
||||
{
|
||||
TEST_COMPARE (objs[i].closed, false);
|
||||
objs[i].closed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* la_objclose should be called after la_activity(LA_ACT_DELETE) for
|
||||
the closed object's namespace. */
|
||||
TEST_COMPARE (last_act, LA_ACT_DELETE);
|
||||
if (!seen_first_objclose)
|
||||
{
|
||||
TEST_COMPARE (last_act_cookie, cookie);
|
||||
seen_first_objclose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nobjs; i++)
|
||||
{
|
||||
TEST_COMPARE (objs[i].closed, true);
|
||||
free (objs[i].lname);
|
||||
}
|
||||
|
||||
/* la_activity(LA_ACT_CONSISTENT) should be the last callback received.
|
||||
Since only one link map may be not-CONSISTENT at a time, this also
|
||||
ensures la_activity(LA_ACT_CONSISTENT) is the last callback received
|
||||
for every namespace. */
|
||||
TEST_COMPARE (last_act, LA_ACT_CONSISTENT);
|
||||
|
||||
free (buffer);
|
||||
xfclose (out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Extra module for tst-audit23
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int
|
||||
foo (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* LD_AUDIT test for la_symbind and bind-now.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
int tst_audit24amod1_func1 (void);
|
||||
int tst_audit24amod1_func2 (void);
|
||||
int tst_audit24amod2_func1 (void);
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
TEST_COMPARE (tst_audit24amod1_func1 (), 1);
|
||||
TEST_COMPARE (tst_audit24amod1_func2 (), 2);
|
||||
TEST_COMPARE (tst_audit24amod2_func1 (), 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Module used by tst-audit24a.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24amod1_func1 (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
tst_audit24amod1_func2 (void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Module used by tst-audit24a.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24amod2_func1 (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* LD_AUDIT test for la_symbind and bind-now.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This is similar to tst-audit24a, with the difference this modules
|
||||
does not have the .gnu.version section header. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
int tst_audit24bmod1_func1 (void);
|
||||
int tst_audit24bmod1_func2 (void);
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
TEST_COMPARE (tst_audit24bmod1_func1 (), 1);
|
||||
TEST_COMPARE (tst_audit24bmod1_func2 (), 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Module used by tst-audit24c.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int tst_audit24bmod2_func1 (void);
|
||||
|
||||
int
|
||||
tst_audit24bmod1_func1 (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tst_audit24bmod1_func2 (void)
|
||||
{
|
||||
return tst_audit24bmod2_func1 ();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Module used by tst-audit24b.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int
|
||||
tst_audit24bmod2_func1 (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/* It tests LD_BIND_NOW=1 instead of linking with -Wl,-z,now */
|
||||
#include "tst-audit24a.c"
|
||||
@@ -0,0 +1,36 @@
|
||||
/* LD_AUDIT test for la_symbind and bind-now.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
|
||||
int tst_audit24dmod1_func1 (void);
|
||||
int tst_audit24dmod1_func2 (void);
|
||||
int tst_audit24dmod2_func1 (void);
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
TEST_COMPARE (tst_audit24dmod1_func1 (), 1);
|
||||
TEST_COMPARE (tst_audit24dmod1_func2 (), 32);
|
||||
TEST_COMPARE (tst_audit24dmod2_func1 (), 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Module used by tst-audit24d.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int tst_audit24dmod3_func1 (void);
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24dmod1_func1 (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
tst_audit24dmod1_func2 (void)
|
||||
{
|
||||
return 2 + tst_audit24dmod3_func1 ();;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Module for tst-audit24d.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int tst_audit24dmod4_func1 (void);
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24dmod2_func1 (void)
|
||||
{
|
||||
tst_audit24dmod4_func1 ();
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Module for tst-audit24d.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24dmod3_func1 (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
tst_audit24dmod3_func2 (void)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Module for tst-audit24d.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
_Noreturn int
|
||||
tst_audit24dmod4_func1 (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/* Check LD_AUDIT and LD_BIND_NOW.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <array_length.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/support.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
void tst_audit25mod1_func1 (void);
|
||||
void tst_audit25mod1_func2 (void);
|
||||
void tst_audit25mod2_func1 (void);
|
||||
void tst_audit25mod2_func2 (void);
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
tst_audit25mod1_func1 ();
|
||||
tst_audit25mod1_func2 ();
|
||||
tst_audit25mod2_func1 ();
|
||||
tst_audit25mod2_func2 ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
/* We must have either:
|
||||
- One or four parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
|
||||
|
||||
char *spargv[9];
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
TEST_VERIFY_EXIT (i < array_length (spargv));
|
||||
|
||||
{
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
/* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with
|
||||
-Wl,-z,now; so only tst_audit25mod3_func1 should be expected to
|
||||
have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */
|
||||
TEST_COMPARE_STRING (result.err.buffer,
|
||||
"la_symbind: tst_audit25mod3_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func1 0\n"
|
||||
"la_symbind: tst_audit25mod1_func2 0\n"
|
||||
"la_symbind: tst_audit25mod2_func1 0\n"
|
||||
"la_symbind: tst_audit25mod4_func1 0\n"
|
||||
"la_symbind: tst_audit25mod2_func2 0\n");
|
||||
|
||||
support_capture_subprocess_free (&result);
|
||||
}
|
||||
|
||||
{
|
||||
setenv ("LD_BIND_NOW", "1", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
/* With LD_BIND_NOW all symbols are expected to have
|
||||
LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution
|
||||
order is done in breadth-first order. */
|
||||
TEST_COMPARE_STRING (result.err.buffer,
|
||||
"la_symbind: tst_audit25mod4_func1 1\n"
|
||||
"la_symbind: tst_audit25mod3_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func1 1\n"
|
||||
"la_symbind: tst_audit25mod2_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func2 1\n"
|
||||
"la_symbind: tst_audit25mod2_func2 1\n");
|
||||
|
||||
support_capture_subprocess_free (&result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,128 @@
|
||||
/* Check LD_AUDIT and LD_BIND_NOW.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <support/capture_subprocess.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/support.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static int restart;
|
||||
#define CMDLINE_OPTIONS \
|
||||
{ "restart", no_argument, &restart, 1 },
|
||||
|
||||
void tst_audit25mod1_func1 (void);
|
||||
void tst_audit25mod1_func2 (void);
|
||||
void tst_audit25mod2_func1 (void);
|
||||
void tst_audit25mod2_func2 (void);
|
||||
|
||||
static int
|
||||
handle_restart (void)
|
||||
{
|
||||
tst_audit25mod1_func1 ();
|
||||
tst_audit25mod1_func2 ();
|
||||
tst_audit25mod2_func1 ();
|
||||
tst_audit25mod2_func2 ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
/* We must have either:
|
||||
- One or four parameters left if called initially:
|
||||
+ path to ld.so optional
|
||||
+ "--library-path" optional
|
||||
+ the library path optional
|
||||
+ the application name */
|
||||
|
||||
if (restart)
|
||||
return handle_restart ();
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
|
||||
|
||||
char *spargv[9];
|
||||
int i = 0;
|
||||
for (; i < argc - 1; i++)
|
||||
spargv[i] = argv[i + 1];
|
||||
spargv[i++] = (char *) "--direct";
|
||||
spargv[i++] = (char *) "--restart";
|
||||
spargv[i] = NULL;
|
||||
|
||||
{
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
/* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but
|
||||
tst-audit25mod2 is built with -Wl,-z,lazy. So only
|
||||
tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not
|
||||
have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */
|
||||
TEST_COMPARE_STRING (result.err.buffer,
|
||||
"la_symbind: tst_audit25mod3_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func1 1\n"
|
||||
"la_symbind: tst_audit25mod2_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func2 1\n"
|
||||
"la_symbind: tst_audit25mod2_func2 1\n"
|
||||
"la_symbind: tst_audit25mod4_func1 0\n");
|
||||
|
||||
support_capture_subprocess_free (&result);
|
||||
}
|
||||
|
||||
{
|
||||
setenv ("LD_BIND_NOW", "1", 0);
|
||||
struct support_capture_subprocess result
|
||||
= support_capture_subprogram (spargv[0], spargv);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
/* With LD_BIND_NOW all symbols are expected to have
|
||||
LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution
|
||||
order is done in breadth-first order. */
|
||||
TEST_COMPARE_STRING (result.err.buffer,
|
||||
"la_symbind: tst_audit25mod4_func1 1\n"
|
||||
"la_symbind: tst_audit25mod3_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func1 1\n"
|
||||
"la_symbind: tst_audit25mod2_func1 1\n"
|
||||
"la_symbind: tst_audit25mod1_func2 1\n"
|
||||
"la_symbind: tst_audit25mod2_func2 1\n");
|
||||
|
||||
support_capture_subprocess_free (&result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Module used by tst-audit25.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
void tst_audit25mod3_func1 (void);
|
||||
|
||||
void
|
||||
tst_audit25mod1_func1 (void)
|
||||
{
|
||||
tst_audit25mod3_func1 ();
|
||||
}
|
||||
|
||||
void
|
||||
tst_audit25mod1_func2 (void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Module used by tst-audit25.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
void tst_audit25mod4_func1 (void);
|
||||
|
||||
void
|
||||
tst_audit25mod2_func1 (void)
|
||||
{
|
||||
tst_audit25mod4_func1 ();
|
||||
}
|
||||
|
||||
void
|
||||
tst_audit25mod2_func2 (void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Module used by tst-audit25.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
void
|
||||
tst_audit25mod3_func1 (void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Module used by tst-audit25.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
void
|
||||
tst_audit25mod4_func1 (void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* DT_AUDIT with modules with TLSDESC.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Check DT_AUDIT with dlmopen.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <link.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
char *
|
||||
la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
return (char *) name;
|
||||
}
|
||||
|
||||
void
|
||||
la_activity (uintptr_t *cookie, unsigned int flag)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
return LA_FLG_BINDTO | LA_FLG_BINDFROM;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objclose (uintptr_t *cookie)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
la_preinit (uintptr_t *cookie)
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||
#else
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
fprintf (stderr, "%s\n", __func__);
|
||||
return sym->st_value;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Audit module for tst-audit18a.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* Audit module for tst-audit18b.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
return LA_FLG_BINDTO | LA_FLG_BINDFROM;
|
||||
}
|
||||
|
||||
uintptr_t
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||
#else
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||
uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
fprintf (stderr, "la_symbind: %s\n", symname);
|
||||
return sym->st_value;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/* Check dlopen failure on audit modules.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int v)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
static void
|
||||
check (void)
|
||||
{
|
||||
{
|
||||
void *mod = dlopen ("nonexistent.so", RTLD_NOW);
|
||||
if (mod != NULL)
|
||||
abort ();
|
||||
}
|
||||
|
||||
{
|
||||
void *mod = dlmopen (LM_ID_BASE, "nonexistent.so", RTLD_NOW);
|
||||
if (mod != NULL)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
la_activity (uintptr_t *cookie, unsigned int flag)
|
||||
{
|
||||
if (flag != LA_ACT_CONSISTENT)
|
||||
return;
|
||||
check ();
|
||||
}
|
||||
|
||||
void
|
||||
la_preinit (uintptr_t *cookie)
|
||||
{
|
||||
check ();
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* Check LD_AUDIT with static TLS.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <link.h>
|
||||
|
||||
#define tls_ie __attribute__ ((tls_model ("initial-exec")))
|
||||
|
||||
__thread int tls_var0 tls_ie;
|
||||
__thread int tls_var1 tls_ie = 0x10;
|
||||
|
||||
/* Defined at tst-auditmod21b.so */
|
||||
extern __thread int tls_var2;
|
||||
extern __thread int tls_var3;
|
||||
|
||||
static volatile int out;
|
||||
|
||||
static void
|
||||
call_libc (void)
|
||||
{
|
||||
/* isspace accesses the initial-exec glibc TLS variables, which are
|
||||
setup in glibc initialization. */
|
||||
out = isspace (' ');
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int v)
|
||||
{
|
||||
tls_var0 = 0x1;
|
||||
if (tls_var1 != 0x10)
|
||||
abort ();
|
||||
tls_var1 = 0x20;
|
||||
|
||||
tls_var2 = 0x2;
|
||||
if (tls_var3 != 0x20)
|
||||
abort ();
|
||||
tls_var3 = 0x40;
|
||||
|
||||
call_libc ();
|
||||
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie)
|
||||
{
|
||||
call_libc ();
|
||||
*cookie = (uintptr_t) map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
la_activity (uintptr_t* cookie, unsigned int flag)
|
||||
{
|
||||
if (tls_var0 != 0x1 || tls_var1 != 0x20)
|
||||
abort ();
|
||||
call_libc ();
|
||||
}
|
||||
|
||||
void
|
||||
la_preinit (uintptr_t* cookie)
|
||||
{
|
||||
call_libc ();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Check LD_AUDIT with static TLS.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define tls_ie __attribute__ ((tls_model ("initial-exec")))
|
||||
|
||||
__thread int tls_var2 tls_ie;
|
||||
__thread int tls_var3 tls_ie = 0x20;
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Check DTAUDIT and vDSO interaction.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static inline bool
|
||||
startswith (const char *str, const char *pre)
|
||||
{
|
||||
size_t lenpre = strlen (pre);
|
||||
size_t lenstr = strlen (str);
|
||||
return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
/* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
|
||||
and it might be the value reported as the AT_SYSINFO_EHDR. */
|
||||
if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
|
||||
fprintf (stderr, "vdso found: %p\n", NULL);
|
||||
else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
|
||||
fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* Audit module loaded by tst-audit23.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/auxv.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
struct map_desc_t
|
||||
{
|
||||
char *lname;
|
||||
uintptr_t laddr;
|
||||
Lmid_t lmid;
|
||||
};
|
||||
|
||||
void
|
||||
la_activity (uintptr_t *cookie, unsigned int flag)
|
||||
{
|
||||
fprintf (stderr, "%s: %d %"PRIxPTR"\n", __func__, flag, (uintptr_t) cookie);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
const char *l_name = map->l_name[0] == '\0' ? "mainapp" : map->l_name;
|
||||
fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__,
|
||||
(uintptr_t) cookie, l_name, map->l_addr, lmid);
|
||||
|
||||
struct map_desc_t *map_desc = malloc (sizeof (struct map_desc_t));
|
||||
if (map_desc == NULL)
|
||||
abort ();
|
||||
|
||||
map_desc->lname = strdup (l_name);
|
||||
map_desc->laddr = map->l_addr;
|
||||
map_desc->lmid = lmid;
|
||||
|
||||
*cookie = (uintptr_t) map_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objclose (uintptr_t *cookie)
|
||||
{
|
||||
struct map_desc_t *map_desc = (struct map_desc_t *) *cookie;
|
||||
fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__,
|
||||
(uintptr_t) cookie, map_desc->lname, map_desc->laddr,
|
||||
map_desc->lmid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Auxiliary functions for tst-audit24x.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _TST_AUDITMOD24_H
|
||||
#define _TST_AUDITMOD24_H
|
||||
|
||||
static void
|
||||
test_symbind_flags (unsigned int flags)
|
||||
{
|
||||
if ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
/* Audit modules for tst-audit24a.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tst-auditmod24.h>
|
||||
|
||||
#define AUDIT24_COOKIE 0x1
|
||||
#define AUDIT24MOD1_COOKIE 0x2
|
||||
#define AUDIT24MOD2_COOKIE 0x3
|
||||
|
||||
#ifndef TEST_NAME
|
||||
# define TEST_NAME "tst-audit24a"
|
||||
#endif
|
||||
#ifndef TEST_MOD
|
||||
# define TEST_MOD TEST_NAME
|
||||
#endif
|
||||
#ifndef TEST_FUNC
|
||||
# define TEST_FUNC "tst_audit24a"
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
const char *p = strrchr (map->l_name, '/');
|
||||
const char *l_name = p == NULL ? TEST_NAME : p + 1;
|
||||
|
||||
uintptr_t ck = -1;
|
||||
if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
|
||||
ck = AUDIT24MOD1_COOKIE;
|
||||
else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
|
||||
ck = AUDIT24MOD2_COOKIE;
|
||||
else if (strcmp (l_name, TEST_NAME) == 0)
|
||||
ck = AUDIT24_COOKIE;
|
||||
|
||||
*cookie = ck;
|
||||
return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_func1 (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_func2 (void)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 64
|
||||
uintptr_t
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#else
|
||||
uintptr_t
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
if (*refcook == AUDIT24_COOKIE)
|
||||
{
|
||||
if (*defcook == AUDIT24MOD1_COOKIE)
|
||||
{
|
||||
/* Check if bind-now symbols are advertised to not call the PLT
|
||||
hooks. */
|
||||
test_symbind_flags (*flags);
|
||||
|
||||
if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
|
||||
return (uintptr_t) tst_func1;
|
||||
else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
|
||||
return sym->st_value;
|
||||
abort ();
|
||||
}
|
||||
if (*defcook == AUDIT24MOD2_COOKIE
|
||||
&& (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
|
||||
{
|
||||
test_symbind_flags (*flags);
|
||||
|
||||
return (uintptr_t) tst_func2;
|
||||
}
|
||||
|
||||
/* malloc functions. */
|
||||
return sym->st_value;
|
||||
}
|
||||
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Audit modules for tst-audit24b.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tst-auditmod24.h>
|
||||
|
||||
#define TEST_NAME "tst-audit24b"
|
||||
#define TEST_FUNC "tst_audit24b"
|
||||
|
||||
#define AUDIT24_COOKIE 0x1
|
||||
#define AUDIT24MOD1_COOKIE 0x2
|
||||
#define AUDIT24MOD2_COOKIE 0x3
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
const char *p = strrchr (map->l_name, '/');
|
||||
const char *l_name = p == NULL ? TEST_NAME : p + 1;
|
||||
|
||||
uintptr_t ck = -1;
|
||||
if (strcmp (l_name, TEST_NAME "mod1.so") == 0)
|
||||
ck = AUDIT24MOD1_COOKIE;
|
||||
else if (strcmp (l_name, TEST_NAME "mod2.so") == 0)
|
||||
ck = AUDIT24MOD2_COOKIE;
|
||||
else if (strcmp (l_name, TEST_NAME) == 0)
|
||||
ck = AUDIT24_COOKIE;
|
||||
|
||||
*cookie = ck;
|
||||
return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_func1 (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_func2 (void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 64
|
||||
uintptr_t
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#else
|
||||
uintptr_t
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
if (*refcook == AUDIT24_COOKIE)
|
||||
{
|
||||
if (*defcook == AUDIT24MOD1_COOKIE)
|
||||
{
|
||||
if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
|
||||
return (uintptr_t) tst_func1;
|
||||
else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
|
||||
return sym->st_value;
|
||||
abort ();
|
||||
}
|
||||
/* malloc functions. */
|
||||
return sym->st_value;
|
||||
}
|
||||
else if (*refcook == AUDIT24MOD1_COOKIE)
|
||||
{
|
||||
if (*defcook == AUDIT24MOD2_COOKIE
|
||||
&& (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
|
||||
{
|
||||
test_symbind_flags (*flags);
|
||||
return (uintptr_t) tst_func2;
|
||||
}
|
||||
}
|
||||
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#define TEST_NAME "tst-audit24c"
|
||||
#define TEST_MOD "tst-audit24a"
|
||||
#include "tst-auditmod24a.c"
|
||||
@@ -0,0 +1,120 @@
|
||||
/* Audit module for tst-audit24d.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <tst-auditmod24.h>
|
||||
|
||||
#define AUDIT24_COOKIE 0x0
|
||||
#define AUDIT24MOD1_COOKIE 0x1
|
||||
#define AUDIT24MOD2_COOKIE 0x2
|
||||
#define AUDIT24MOD3_COOKIE 0x3
|
||||
#define AUDIT24MOD4_COOKIE 0x4
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
const char *p = strrchr (map->l_name, '/');
|
||||
const char *l_name = p == NULL ? "tst-audit24d" : p + 1;
|
||||
|
||||
uintptr_t ck = -1;
|
||||
if (strcmp (l_name, "tst-audit24dmod1.so") == 0)
|
||||
ck = AUDIT24MOD1_COOKIE;
|
||||
else if (strcmp (l_name, "tst-audit24dmod2.so") == 0)
|
||||
ck = AUDIT24MOD2_COOKIE;
|
||||
else if (strcmp (l_name, "tst-audit24dmod3.so") == 0)
|
||||
ck = AUDIT24MOD3_COOKIE;
|
||||
else if (strcmp (l_name, "tst-audit24dmod.so") == 0)
|
||||
ck = AUDIT24MOD4_COOKIE;
|
||||
else if (strcmp (l_name, "tst-audit24d") == 0)
|
||||
ck = AUDIT24_COOKIE;
|
||||
|
||||
*cookie = ck;
|
||||
return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_audit24dmod1_func1 (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_audit24dmod2_func1 (void)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
static int
|
||||
tst_audit24dmod3_func1 (void)
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 64
|
||||
uintptr_t
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#else
|
||||
uintptr_t
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
if (*refcook == AUDIT24_COOKIE)
|
||||
{
|
||||
if (*defcook == AUDIT24MOD1_COOKIE)
|
||||
{
|
||||
if (strcmp (symname, "tst_audit24dmod1_func1") == 0)
|
||||
return (uintptr_t) tst_audit24dmod1_func1;
|
||||
else if (strcmp (symname, "tst_audit24dmod1_func2") == 0)
|
||||
return sym->st_value;
|
||||
abort ();
|
||||
}
|
||||
if (*defcook == AUDIT24MOD2_COOKIE
|
||||
&& (strcmp (symname, "tst_audit24dmod2_func1") == 0))
|
||||
return (uintptr_t) tst_audit24dmod2_func1;
|
||||
|
||||
/* malloc functions. */
|
||||
return sym->st_value;
|
||||
}
|
||||
else if (*refcook == AUDIT24MOD1_COOKIE)
|
||||
{
|
||||
if (*defcook == AUDIT24MOD3_COOKIE
|
||||
&& strcmp (symname, "tst_audit24dmod3_func1") == 0)
|
||||
{
|
||||
test_symbind_flags (*flags);
|
||||
|
||||
return (uintptr_t) tst_audit24dmod3_func1;
|
||||
}
|
||||
}
|
||||
|
||||
abort ();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Audit modules for tst-audit25a.
|
||||
Copyright (C) 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
|
||||
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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define AUDIT25_COOKIE 0x1
|
||||
#define AUDIT25MOD1_COOKIE 0x2
|
||||
#define AUDIT25MOD2_COOKIE 0x3
|
||||
#define AUDIT25MOD3_COOKIE 0x2
|
||||
#define AUDIT25MOD4_COOKIE 0x3
|
||||
|
||||
#define TEST_NAME "tst-audit25"
|
||||
#define TEST_MOD "tst-audit25"
|
||||
#define TEST_FUNC "tst_audit25"
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
return LAV_CURRENT;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
|
||||
{
|
||||
const char *p = strrchr (map->l_name, '/');
|
||||
const char *l_name = p == NULL ? TEST_NAME : p + 1;
|
||||
|
||||
uintptr_t ck = -1;
|
||||
if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
|
||||
ck = AUDIT25MOD1_COOKIE;
|
||||
else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
|
||||
ck = AUDIT25MOD2_COOKIE;
|
||||
else if (strcmp (l_name, TEST_MOD "mod3.so") == 0)
|
||||
ck = AUDIT25MOD3_COOKIE;
|
||||
else if (strcmp (l_name, TEST_MOD "mod4.so") == 0)
|
||||
ck = AUDIT25MOD4_COOKIE;
|
||||
else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
|
||||
ck = AUDIT25_COOKIE;
|
||||
|
||||
*cookie = ck;
|
||||
return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
|
||||
}
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 64
|
||||
uintptr_t
|
||||
la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#else
|
||||
uintptr_t
|
||||
la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
|
||||
uintptr_t *refcook, uintptr_t *defcook,
|
||||
unsigned int *flags, const char *symname)
|
||||
#endif
|
||||
{
|
||||
if (*refcook != -1 && *defcook != -1)
|
||||
fprintf (stderr, "la_symbind: %s %u\n", symname,
|
||||
*flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0);
|
||||
return sym->st_value;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Test case for DSO with readonly dynamic section.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
int foo = -1;
|
||||
@@ -0,0 +1,16 @@
|
||||
SECTIONS
|
||||
{
|
||||
. = SIZEOF_HEADERS;
|
||||
.dynamic : { *(.dynamic) } :text :dynamic
|
||||
.rodata : { *(.data*) *(.bss*) } :text
|
||||
/DISCARD/ : {
|
||||
*(.note.gnu.property)
|
||||
}
|
||||
.note : { *(.note.*) } :text :note
|
||||
}
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5) FILEHDR PHDRS;
|
||||
dynamic PT_DYNAMIC FLAGS(4);
|
||||
note PT_NOTE FLAGS(4);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Test case for DSO with readonly dynamic section.
|
||||
Copyright (C) 2021 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
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/check.h>
|
||||
#include <support/test-driver.h>
|
||||
|
||||
extern int foo;
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
TEST_COMPARE (foo, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
+1
-1
@@ -478,7 +478,7 @@ __gconv_read_conf (void)
|
||||
__gconv_get_path ();
|
||||
|
||||
for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
|
||||
gconv_parseconfdir (__gconv_path_elem[cnt].name,
|
||||
gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name,
|
||||
__gconv_path_elem[cnt].len);
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user