glibc/nptl/tst-audit-threads-mod1.c

75 lines
2.2 KiB
C
Raw Permalink Normal View History

Fix _dl_profile_fixup data-dependency issue (Bug 23690) There is a data-dependency between the fields of struct l_reloc_result and the field used as the initialization guard. Users of the guard expect writes to the structure to be observable when they also observe the guard initialized. The solution for this problem is to use an acquire and release load and store to ensure previous writes to the structure are observable if the guard is initialized. The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) as the initialization guard, making it impossible for some architectures to load and store it atomically, i.e. hppa and ia64, due to its larger size. This commit adds an unsigned int to l_reloc_result to be used as the new initialization guard of the struct, making it possible to load and store it atomically in all architectures. The fix ensures that the values observed in l_reloc_result are consistent and do not lead to crashes. The algorithm is documented in the code in elf/dl-runtime.c (_dl_profile_fixup). Not all data races have been eliminated. Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. [BZ #23690] * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory modification order when accessing reloc_result->addr. * include/link.h (reloc_result): Add field init. * nptl/Makefile (tests): Add tst-audit-threads. (modules-names): Add tst-audit-threads-mod1 and tst-audit-threads-mod2. Add rules to build tst-audit-threads. * nptl/tst-audit-threads-mod1.c: New file. * nptl/tst-audit-threads-mod2.c: Likewise. * nptl/tst-audit-threads.c: Likewise. * nptl/tst-audit-threads.h: Likewise. Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2018-12-01 04:05:32 +08:00
/* Dummy audit library for test-audit-threads.
Copyright (C) 2018-2024 Free Software Foundation, Inc.
Fix _dl_profile_fixup data-dependency issue (Bug 23690) There is a data-dependency between the fields of struct l_reloc_result and the field used as the initialization guard. Users of the guard expect writes to the structure to be observable when they also observe the guard initialized. The solution for this problem is to use an acquire and release load and store to ensure previous writes to the structure are observable if the guard is initialized. The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) as the initialization guard, making it impossible for some architectures to load and store it atomically, i.e. hppa and ia64, due to its larger size. This commit adds an unsigned int to l_reloc_result to be used as the new initialization guard of the struct, making it possible to load and store it atomically in all architectures. The fix ensures that the values observed in l_reloc_result are consistent and do not lead to crashes. The algorithm is documented in the code in elf/dl-runtime.c (_dl_profile_fixup). Not all data races have been eliminated. Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. [BZ #23690] * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory modification order when accessing reloc_result->addr. * include/link.h (reloc_result): Add field init. * nptl/Makefile (tests): Add tst-audit-threads. (modules-names): Add tst-audit-threads-mod1 and tst-audit-threads-mod2. Add rules to build tst-audit-threads. * nptl/tst-audit-threads-mod1.c: New file. * nptl/tst-audit-threads-mod2.c: Likewise. * nptl/tst-audit-threads.c: Likewise. * nptl/tst-audit-threads.h: Likewise. Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2018-12-01 04:05:32 +08:00
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
Prefer https to http for gnu.org and fsf.org URLs Also, change sources.redhat.com to sourceware.org. This patch was automatically generated by running the following shell script, which uses GNU sed, and which avoids modifying files imported from upstream: sed -ri ' s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g ' \ $(find $(git ls-files) -prune -type f \ ! -name '*.po' \ ! -name 'ChangeLog*' \ ! -path COPYING ! -path COPYING.LIB \ ! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \ ! -path manual/texinfo.tex ! -path scripts/config.guess \ ! -path scripts/config.sub ! -path scripts/install-sh \ ! -path scripts/mkinstalldirs ! -path scripts/move-if-change \ ! -path INSTALL ! -path locale/programs/charmap-kw.h \ ! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \ ! '(' -name configure \ -execdir test -f configure.ac -o -f configure.in ';' ')' \ ! '(' -name preconfigure \ -execdir test -f preconfigure.ac ';' ')' \ -print) and then by running 'make dist-prepare' to regenerate files built from the altered files, and then executing the following to cleanup: chmod a+x sysdeps/unix/sysv/linux/riscv/configure # Omit irrelevant whitespace and comment-only changes, # perhaps from a slightly-different Autoconf version. git checkout -f \ sysdeps/csky/configure \ sysdeps/hppa/configure \ sysdeps/riscv/configure \ sysdeps/unix/sysv/linux/csky/configure # Omit changes that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines git checkout -f \ sysdeps/powerpc/powerpc64/ppc-mcount.S \ sysdeps/unix/sysv/linux/s390/s390-64/syscall.S # Omit change that caused a pre-commit check to fail like this: # remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
<https://www.gnu.org/licenses/>. */
Fix _dl_profile_fixup data-dependency issue (Bug 23690) There is a data-dependency between the fields of struct l_reloc_result and the field used as the initialization guard. Users of the guard expect writes to the structure to be observable when they also observe the guard initialized. The solution for this problem is to use an acquire and release load and store to ensure previous writes to the structure are observable if the guard is initialized. The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) as the initialization guard, making it impossible for some architectures to load and store it atomically, i.e. hppa and ia64, due to its larger size. This commit adds an unsigned int to l_reloc_result to be used as the new initialization guard of the struct, making it possible to load and store it atomically in all architectures. The fix ensures that the values observed in l_reloc_result are consistent and do not lead to crashes. The algorithm is documented in the code in elf/dl-runtime.c (_dl_profile_fixup). Not all data races have been eliminated. Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. [BZ #23690] * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory modification order when accessing reloc_result->addr. * include/link.h (reloc_result): Add field init. * nptl/Makefile (tests): Add tst-audit-threads. (modules-names): Add tst-audit-threads-mod1 and tst-audit-threads-mod2. Add rules to build tst-audit-threads. * nptl/tst-audit-threads-mod1.c: New file. * nptl/tst-audit-threads-mod2.c: Likewise. * nptl/tst-audit-threads.c: Likewise. * nptl/tst-audit-threads.h: Likewise. Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2018-12-01 04:05:32 +08:00
#include <elf.h>
#include <link.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
/* We must use a dummy LD_AUDIT module to force the dynamic loader to
*not* update the real PLT, and instead use a cached value for the
lazy resolution result. It is the update of that cached value that
we are testing for correctness by doing this. */
/* Library to be audited. */
#define LIB "tst-audit-threads-mod2.so"
/* CALLNUM is the number of retNum functions. */
#define CALLNUM 7999
#define CONCATX(a, b) __CONCAT (a, b)
static int previous = 0;
unsigned int
la_version (unsigned int ver)
{
return 1;
}
unsigned int
la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
{
return LA_FLG_BINDTO | LA_FLG_BINDFROM;
}
uintptr_t
CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym,
unsigned int ndx,
uintptr_t *refcook,
uintptr_t *defcook,
unsigned int *flags,
const char *symname)
{
const char * retnum = "retNum";
char * num = strstr (symname, retnum);
int n;
/* Validate if the symbols are getting called in the correct order.
This code is here to verify binutils does not optimize out the PLT
entries that require the symbol binding. */
if (num != NULL)
{
n = atoi (num);
assert (n >= previous);
assert (n <= CALLNUM);
previous = n;
}
return sym->st_value;
}