mirror of https://gitee.com/Nocallback/glibc.git
Browse Source
This patch moves the vDSO setup from libc to loader code, just after the vDSO link_map setup. For static case the initialization is moved to _dl_non_dynamic_init instead. Instead of using the mangled pointer, the vDSO data is set as attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for static). It is read-only even with partial relro. It fixes BZ#24967 now that the vDSO pointer is setup earlier than malloc interposition is called. Also, vDSO calls should not be a problem for static dlopen as indicated by BZ#20802. The vDSO pointer would be zero-initialized and the syscall will be issued instead. Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu, powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and sparcv9-linux-gnu. I also run some tests on mips. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>zack/obsolete-time-functions
31 changed files with 257 additions and 289 deletions
@ -0,0 +1 @@ |
|||
/* Empty. */ |
|||
@ -0,0 +1,28 @@ |
|||
/* ELF symbol initialization functions for VDSO objects.
|
|||
Copyright (C) 2020 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_VDSO_INIT_H |
|||
#define _DL_VDSO_INIT_H |
|||
|
|||
/* Initialize the VDSO functions pointers. */ |
|||
static inline void __attribute__ ((always_inline)) |
|||
setup_vdso_pointers (void) |
|||
{ |
|||
} |
|||
|
|||
#endif |
|||
@ -0,0 +1,30 @@ |
|||
/* ELF symbol resolve functions for VDSO objects.
|
|||
Copyright (C) 2020 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_VDSO_H |
|||
#define _DL_VDSO_H 1 |
|||
|
|||
/* Function for resolving symbols in the VDSO link map. Return the
|
|||
address of the vdso symbol NAME. */ |
|||
static inline void * |
|||
dl_vdso_vsym (const char *name) |
|||
{ |
|||
return NULL; |
|||
} |
|||
|
|||
#endif |
|||
@ -0,0 +1,81 @@ |
|||
/* Data for vDSO support. Linux version.
|
|||
Copyright (C) 2020 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 file is included in three different modes for both static (libc.a)
|
|||
and shared (rtld) modes: |
|||
|
|||
1. PROCINFO_DECL is defined, meaning we are only interested in |
|||
declarations. For static it requires use the extern keywork along with |
|||
the attribute_relro while for shared it will be embedded in the |
|||
rtld_global_ro. |
|||
|
|||
2. PROCINFO_DECL and SHARED are not defined. Nothing to do, the default |
|||
zero initializion is suffice. |
|||
|
|||
3. PROCINFO_DECL is not defined while SHARED is. Similar to 2., the zero |
|||
initialization of rtld_global_ro is suffice. */ |
|||
|
|||
#ifndef PROCINFO_CLASS |
|||
# define PROCINFO_CLASS |
|||
#endif |
|||
|
|||
#ifndef SHARED |
|||
# define RELRO attribute_relro |
|||
#else |
|||
# define RELRO |
|||
#endif |
|||
|
|||
#if defined PROCINFO_DECL || !defined SHARED |
|||
# ifdef HAVE_CLOCK_GETTIME_VSYSCALL |
|||
PROCINFO_CLASS int (*_dl_vdso_clock_gettime) (clockid_t, |
|||
struct timespec *) RELRO; |
|||
#endif |
|||
# ifdef HAVE_GETTIMEOFDAY_VSYSCALL |
|||
PROCINFO_CLASS int (*_dl_vdso_gettimeofday) (struct timeval *, void *) RELRO; |
|||
#endif |
|||
# ifdef HAVE_TIME_VSYSCALL |
|||
PROCINFO_CLASS time_t (*_dl_vdso_time) (time_t *) RELRO; |
|||
# endif |
|||
# ifdef HAVE_GETCPU_VSYSCALL |
|||
PROCINFO_CLASS int (*_dl_vdso_getcpu) (unsigned *, unsigned *, void *) RELRO; |
|||
# endif |
|||
# ifdef HAVE_CLOCK_GETRES_VSYSCALL |
|||
PROCINFO_CLASS int (*_dl_vdso_clock_getres) (clockid_t, |
|||
struct timespec *) RELRO; |
|||
# endif |
|||
|
|||
/* PowerPC specific ones. */ |
|||
# ifdef HAVE_GET_TBFREQ |
|||
PROCINFO_CLASS uint64_t (*_dl_vdso_get_tbfreq)(void) RELRO; |
|||
# endif |
|||
/* The sigtramp are used on powerpc backtrace without using
|
|||
INLINE_VSYSCALL, so there is no need to set their type. */ |
|||
# ifdef HAVE_SIGTRAMP_RT64 |
|||
PROCINFO_CLASS void *_dl_vdso_sigtramp_rt64 RELRO; |
|||
# endif |
|||
# ifdef HAVE_SIGTRAMP_RT32 |
|||
PROCINFO_CLASS void *_dl_vdso_sigtramp_rt32 RELRO; |
|||
# endif |
|||
# ifdef HAVE_SIGTRAMP_32 |
|||
PROCINFO_CLASS void *_dl_vdso_sigtramp_32 RELRO; |
|||
# endif |
|||
#endif |
|||
|
|||
#undef RELRO |
|||
#undef PROCINFO_DECL |
|||
#undef PROCINFO_CLASS |
|||
@ -0,0 +1,55 @@ |
|||
/* ELF symbol initialization functions for VDSO objects. Linux version.
|
|||
Copyright (C) 2020 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_VDSO_INIT_H |
|||
#define _DL_VDSO_INIT_H |
|||
|
|||
/* Initialize the VDSO functions pointers. */ |
|||
static inline void __attribute__ ((always_inline)) |
|||
setup_vdso_pointers (void) |
|||
{ |
|||
#ifdef HAVE_CLOCK_GETTIME_VSYSCALL |
|||
GLRO(dl_vdso_clock_gettime) = dl_vdso_vsym (HAVE_CLOCK_GETTIME_VSYSCALL); |
|||
#endif |
|||
#ifdef HAVE_GETTIMEOFDAY_VSYSCALL |
|||
GLRO(dl_vdso_gettimeofday) = dl_vdso_vsym (HAVE_GETTIMEOFDAY_VSYSCALL); |
|||
#endif |
|||
#ifdef HAVE_TIME_VSYSCALL |
|||
GLRO(dl_vdso_time) = dl_vdso_vsym (HAVE_TIME_VSYSCALL); |
|||
#endif |
|||
#ifdef HAVE_GETCPU_VSYSCALL |
|||
GLRO(dl_vdso_getcpu) = dl_vdso_vsym (HAVE_GETCPU_VSYSCALL); |
|||
#endif |
|||
#ifdef HAVE_CLOCK_GETRES_VSYSCALL |
|||
GLRO(dl_vdso_clock_getres) = dl_vdso_vsym (HAVE_CLOCK_GETRES_VSYSCALL); |
|||
#endif |
|||
#ifdef HAVE_GET_TBFREQ |
|||
GLRO(dl_vdso_get_tbfreq) = dl_vdso_vsym (HAVE_GET_TBFREQ); |
|||
#endif |
|||
#ifdef HAVE_SIGTRAMP_RT64 |
|||
GLRO(dl_vdso_sigtramp_rt64) = dl_vdso_vsym (HAVE_SIGTRAMP_RT64); |
|||
#endif |
|||
#ifdef HAVE_SIGTRAMP_RT32 |
|||
GLRO(dl_vdso_sigtramp_rt32) = dl_vdso_vsym (HAVE_SIGTRAMP_RT32); |
|||
#endif |
|||
#ifdef HAVE_SIGTRAMP_32 |
|||
GLRO(dl_vdso_sigtramp_32) = dl_vdso_vsym (HAVE_SIGTRAMP_32); |
|||
#endif |
|||
} |
|||
|
|||
#endif |
|||
@ -1,48 +0,0 @@ |
|||
/* ELF symbol resolve functions for VDSO objects.
|
|||
Copyright (C) 2005-2020 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 "config.h" |
|||
#include <ldsodefs.h> |
|||
|
|||
|
|||
void * |
|||
_dl_vdso_vsym (const char *name, const struct r_found_version *vers) |
|||
{ |
|||
struct link_map *map = GLRO (dl_sysinfo_map); |
|||
void *value = NULL; |
|||
|
|||
|
|||
if (map != NULL) |
|||
{ |
|||
/* Use a WEAK REF so we don't error out if the symbol is not found. */ |
|||
ElfW (Sym) wsym; |
|||
memset (&wsym, 0, sizeof (ElfW (Sym))); |
|||
wsym.st_info = (unsigned char) ELFW (ST_INFO (STB_WEAK, STT_NOTYPE)); |
|||
|
|||
/* Search the scope of the vdso map. */ |
|||
const ElfW (Sym) *ref = &wsym; |
|||
lookup_t result = GLRO (dl_lookup_symbol_x) (name, map, &ref, |
|||
map->l_local_scope, |
|||
vers, 0, 0, NULL); |
|||
|
|||
if (ref != NULL) |
|||
value = DL_SYMBOL_ADDRESS (result, ref); |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
@ -1,90 +0,0 @@ |
|||
/* vDSO internal symbols. Linux generic version.
|
|||
Copyright (C) 2019-2020 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 |
|||
<http://www.gnu.org/licenses/>. */
|
|||
|
|||
#include <dl-vdso.h> |
|||
#include <libc-vdso.h> |
|||
|
|||
/* vDSO symbol used on clock_gettime implementation. */ |
|||
#ifdef HAVE_CLOCK_GETTIME_VSYSCALL |
|||
int (*VDSO_SYMBOL(clock_gettime)) (clockid_t, struct timespec *) |
|||
attribute_hidden; |
|||
#endif |
|||
/* vDSO symbol used on clock_gettime64 implementation. */ |
|||
#ifdef HAVE_CLOCK_GETTIME64_VSYSCALL |
|||
int (*VDSO_SYMBOL(clock_gettime64)) (clockid_t, struct __timespec64 *) |
|||
attribute_hidden; |
|||
#endif |
|||
/* vDSO symbol used on clock_getres implementation. */ |
|||
#ifdef HAVE_CLOCK_GETRES_VSYSCALL |
|||
int (*VDSO_SYMBOL(clock_getres)) (clockid_t, struct timespec *) |
|||
attribute_hidden; |
|||
#endif |
|||
/* vDSO symbol used on gettimeofday implementation. */ |
|||
#ifdef HAVE_GETTIMEOFDAY_VSYSCALL |
|||
int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *) |
|||
attribute_hidden; |
|||
#endif |
|||
/* vDSO symbol used on GNU extension getcpu implementation. */ |
|||
#ifdef HAVE_GETCPU_VSYSCALL |
|||
long int (*VDSO_SYMBOL(getcpu)) (unsigned *, unsigned *, void *) |
|||
attribute_hidden; |
|||
#endif |
|||
/* vDSO symbol used on time implementation. */ |
|||
#ifdef HAVE_TIME_VSYSCALL |
|||
time_t (*VDSO_SYMBOL(time)) (time_t *) attribute_hidden; |
|||
#endif |
|||
|
|||
static inline void |
|||
__libc_vdso_platform_setup (void) |
|||
{ |
|||
#ifdef HAVE_CLOCK_GETTIME_VSYSCALL |
|||
VDSO_SYMBOL(clock_gettime) |
|||
= get_vdso_mangle_symbol (HAVE_CLOCK_GETTIME_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef HAVE_CLOCK_GETTIME64_VSYSCALL |
|||
VDSO_SYMBOL(clock_gettime64) |
|||
= get_vdso_mangle_symbol (HAVE_CLOCK_GETTIME64_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef HAVE_CLOCK_GETRES_VSYSCALL |
|||
VDSO_SYMBOL(clock_getres) |
|||
= get_vdso_mangle_symbol (HAVE_CLOCK_GETRES_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef HAVE_GETTIMEOFDAY_VSYSCALL |
|||
VDSO_SYMBOL(gettimeofday) |
|||
= get_vdso_mangle_symbol (HAVE_GETTIMEOFDAY_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef HAVE_GETCPU_VSYSCALL |
|||
VDSO_SYMBOL(getcpu) = get_vdso_mangle_symbol (HAVE_GETCPU_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef HAVE_TIME_VSYSCALL |
|||
VDSO_SYMBOL(time) = get_vdso_mangle_symbol (HAVE_TIME_VSYSCALL); |
|||
#endif |
|||
|
|||
#ifdef VDSO_SETUP_ARCH |
|||
VDSO_SETUP_ARCH (); |
|||
#endif |
|||
} |
|||
|
|||
#define VDSO_SETUP __libc_vdso_platform_setup |
|||
|
|||
#include <csu/init-first.c> |
|||
@ -1,50 +0,0 @@ |
|||
/* Initialization code run first thing by the ELF startup code. Linux/PowerPC.
|
|||
Copyright (C) 2007-2020 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 <dl-vdso.h> |
|||
#include <libc-vdso.h> |
|||
|
|||
unsigned long long (*VDSO_SYMBOL(get_tbfreq)) (void) attribute_hidden; |
|||
#if defined(__PPC64__) || defined(__powerpc64__) |
|||
void *VDSO_SYMBOL(sigtramp_rt64) attribute_hidden; |
|||
#else |
|||
void *VDSO_SYMBOL(sigtramp32) attribute_hidden; |
|||
void *VDSO_SYMBOL(sigtramp_rt32) attribute_hidden; |
|||
#endif |
|||
|
|||
static inline void |
|||
__libc_vdso_platform_setup_arch (void) |
|||
{ |
|||
VDSO_SYMBOL (get_tbfreq) = get_vdso_mangle_symbol (HAVE_GET_TBFREQ); |
|||
|
|||
/* PPC64 uses only one signal trampoline symbol, while PPC32 will use
|
|||
two depending if SA_SIGINFO is used (__kernel_sigtramp_rt32) or not |
|||
(__kernel_sigtramp32). |
|||
There is no need to pointer mangle these symbol because they will |
|||
used only for pointer comparison. */ |
|||
#if defined(__PPC64__) || defined(__powerpc64__) |
|||
VDSO_SYMBOL(sigtramp_rt64) = get_vdso_symbol (HAVE_SIGTRAMP_RT64); |
|||
#else |
|||
VDSO_SYMBOL(sigtramp32) = get_vdso_symbol (HAVE_SIGTRAMP_32); |
|||
VDSO_SYMBOL(sigtramp_rt32) = get_vdso_symbol (HAVE_SIGTRAMP_RT32); |
|||
#endif |
|||
} |
|||
|
|||
#define VDSO_SETUP_ARCH __libc_vdso_platform_setup_arch |
|||
|
|||
#include <sysdeps/unix/sysv/linux/init-first.c> |
|||
Loading…
Reference in new issue