diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 3 | ||||
-rw-r--r-- | elf/Versions | 8 | ||||
-rw-r--r-- | elf/dl-catch.c (renamed from elf/dl-error-skeleton.c) | 154 | ||||
-rw-r--r-- | elf/dl-error-minimal.c | 23 | ||||
-rw-r--r-- | elf/dl-error.c | 27 | ||||
-rw-r--r-- | elf/rtld.c | 2 |
6 files changed, 79 insertions, 138 deletions
diff --git a/elf/Makefile b/elf/Makefile index 5f7d222..eca7b28 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -34,7 +34,6 @@ routines = \ dl-addr \ dl-addr-obj \ dl-early_allocate \ - dl-error \ dl-iteratephdr \ dl-libc \ dl-origin \ @@ -54,6 +53,7 @@ routines = \ dl-routines = \ dl-call-libc-early-init \ dl-call_fini \ + dl-catch \ dl-close \ dl-debug \ dl-debug-symbols \ @@ -134,7 +134,6 @@ rtld-routines = \ dl-diagnostics-cpu \ dl-diagnostics-kernel \ dl-environ \ - dl-error-minimal \ dl-hwcaps \ dl-hwcaps-subdirs \ dl-hwcaps_split \ diff --git a/elf/Versions b/elf/Versions index a9ff278..4614ace 100644 --- a/elf/Versions +++ b/elf/Versions @@ -31,10 +31,6 @@ libc { GLIBC_PRIVATE { # functions used in other libraries __libc_early_init; - - # Internal error handling support. Interposes the functions in ld.so. - _dl_signal_exception; _dl_catch_exception; - _dl_signal_error; _dl_catch_error; } } @@ -77,10 +73,8 @@ ld { # Internal error handling support. _dl_exception_create; _dl_exception_create_format; _dl_exception_free; - - # Internal error handling support. Interposed by libc.so. _dl_signal_exception; _dl_catch_exception; - _dl_signal_error; _dl_catch_error; + _dl_signal_error; # Set value of a tunable. __tunable_get_val; diff --git a/elf/dl-error-skeleton.c b/elf/dl-catch.c index 8abf437..54763dd 100644 --- a/elf/dl-error-skeleton.c +++ b/elf/dl-catch.c @@ -1,4 +1,4 @@ -/* Template for error handling for runtime dynamic linker. +/* Exception handling in the dynamic linker. Copyright (C) 1995-2022 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,16 +16,6 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -/* The following macro needs to be defined before including this - skeleton file: - - DL_ERROR_BOOTSTRAP - - If 1, do not use TLS and implement _dl_signal_cerror and - _dl_receive_error. If 0, TLS is used, and the variants with - error callbacks are not provided. */ - - #include <libintl.h> #include <setjmp.h> #include <stdbool.h> @@ -34,39 +24,54 @@ #include <unistd.h> #include <ldsodefs.h> #include <stdio.h> +#include <tls.h> /* This structure communicates state between _dl_catch_error and _dl_signal_error. */ -struct catch +struct rtld_catch { struct dl_exception *exception; /* The exception data is stored there. */ volatile int *errcode; /* Return value of _dl_signal_error. */ jmp_buf env; /* longjmp here on error. */ }; -/* Multiple threads at once can use the `_dl_catch_error' function. The - calls can come from `_dl_map_object_deps', `_dlerror_run', or from - any of the libc functionality which loads dynamic objects (NSS, iconv). - Therefore we have to be prepared to save the state in thread-local - memory. */ -#if !DL_ERROR_BOOTSTRAP -static __thread struct catch *catch_hook attribute_tls_model_ie; -#else -/* The version of this code in ld.so cannot use thread-local variables - and is used during bootstrap only. */ -static struct catch *catch_hook; +/* Multiple threads at once can use the `_dl_catch_error' function. + The calls can come from `_dl_map_object_deps', `_dlerror_run', or + from any of the libc functionality which loads dynamic objects + (NSS, iconv). Therefore we have to be prepared to save the state + in thread-local memory. We use THREAD_GETMEM and THREAD_SETMEM + instead of ELF TLS because ELF TLS is not available in the dynamic + loader. Additionally, the exception handling mechanism must be + usable before the TCB has been set up, which is why + rtld_catch_notls is used if !__rtld_tls_init_tp_called. This is + not needed for static builds, where initialization completes before + static dlopen etc. can be called. */ + +#if IS_IN (rtld) +static struct rtld_catch *rtld_catch_notls; #endif -#if DL_ERROR_BOOTSTRAP -/* This points to a function which is called when an continuable error is - received. Unlike the handling of `catch' this function may return. - The arguments will be the `errstring' and `objname'. +static struct rtld_catch * +get_catch (void) +{ +#if IS_IN (rtld) + if (!__rtld_tls_init_tp_called) + return rtld_catch_notls; + else +#endif + return THREAD_GETMEM (THREAD_SELF, rtld_catch); +} - Since this functionality is not used in normal programs (only in ld.so) - we do not care about multi-threaded programs here. We keep this as a - global variable. */ -static receiver_fct receiver; -#endif /* DL_ERROR_BOOTSTRAP */ +static void +set_catch (struct rtld_catch *catch) +{ +#if IS_IN (rtld) + if (!__rtld_tls_init_tp_called) + rtld_catch_notls = catch; + else +#endif + THREAD_SETMEM (THREAD_SELF, rtld_catch, catch); +} /* Lossage while resolving the program's own symbols is always fatal. */ static void @@ -89,7 +94,7 @@ void _dl_signal_exception (int errcode, struct dl_exception *exception, const char *occasion) { - struct catch *lcatch = catch_hook; + struct rtld_catch *lcatch = get_catch (); if (lcatch != NULL) { *lcatch->exception = *exception; @@ -101,13 +106,13 @@ _dl_signal_exception (int errcode, struct dl_exception *exception, else fatal_error (errcode, exception->objname, occasion, exception->errstring); } -libc_hidden_def (_dl_signal_exception) +rtld_hidden_def (_dl_signal_exception) void _dl_signal_error (int errcode, const char *objname, const char *occation, const char *errstring) { - struct catch *lcatch = catch_hook; + struct rtld_catch *lcatch = get_catch (); if (! errstring) errstring = N_("DYNAMIC LINKER BUG!!!"); @@ -123,10 +128,18 @@ _dl_signal_error (int errcode, const char *objname, const char *occation, else fatal_error (errcode, objname, occation, errstring); } -libc_hidden_def (_dl_signal_error) +rtld_hidden_def (_dl_signal_error) + +#if IS_IN (rtld) +/* This points to a function which is called when a continuable error is + received. Unlike the handling of `catch' this function may return. + The arguments will be the `errstring' and `objname'. + Since this functionality is not used in normal programs (only in ld.so) + we do not care about multi-threaded programs here. We keep this as a + global variable. */ +static receiver_fct receiver; -#if DL_ERROR_BOOTSTRAP void _dl_signal_cexception (int errcode, struct dl_exception *exception, const char *occasion) @@ -167,7 +180,23 @@ _dl_signal_cerror (int errcode, const char *objname, const char *occation, else _dl_signal_error (errcode, objname, occation, errstring); } -#endif /* DL_ERROR_BOOTSTRAP */ + +void +_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) +{ + struct rtld_catch *old_catch = get_catch (); + receiver_fct old_receiver = receiver; + + /* Set the new values. */ + set_catch (NULL); + receiver = fct; + + (*operate) (args); + + set_catch (old_catch); + receiver = old_receiver; +} +#endif int _dl_catch_exception (struct dl_exception *exception, @@ -177,11 +206,11 @@ _dl_catch_exception (struct dl_exception *exception, Exceptions during operate (args) are fatal. */ if (exception == NULL) { - struct catch *const old = catch_hook; - catch_hook = NULL; + struct rtld_catch *old_catch = get_catch (); + set_catch (NULL); operate (args); /* If we get here, the operation was successful. */ - catch_hook = old; + set_catch (old_catch); return 0; } @@ -194,19 +223,19 @@ _dl_catch_exception (struct dl_exception *exception, in _dl_signal_error (before longjmp). */ volatile int errcode; - struct catch c; + struct rtld_catch c; /* Don't use an initializer since we don't need to clear C.env. */ c.exception = exception; c.errcode = &errcode; - struct catch *const old = catch_hook; - catch_hook = &c; + struct rtld_catch *old = get_catch (); + set_catch (&c); /* Do not save the signal mask. */ if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) { (*operate) (args); - catch_hook = old; + set_catch (old); *exception = (struct dl_exception) { NULL }; return 0; } @@ -214,10 +243,10 @@ _dl_catch_exception (struct dl_exception *exception, /* We get here only if we longjmp'd out of OPERATE. _dl_signal_exception has already stored values into *EXCEPTION. */ - catch_hook = old; + set_catch (old); return errcode; } -libc_hidden_def (_dl_catch_exception) +rtld_hidden_def (_dl_catch_exception) int _dl_catch_error (const char **objname, const char **errstring, @@ -230,34 +259,3 @@ _dl_catch_error (const char **objname, const char **errstring, *mallocedp = exception.message_buffer == exception.errstring; return errorcode; } -libc_hidden_def (_dl_catch_error) - -#if DL_ERROR_BOOTSTRAP -void -_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) -{ - struct catch *old_catch = catch_hook; - receiver_fct old_receiver = receiver; - - /* Set the new values. */ - catch_hook = NULL; - receiver = fct; - - (*operate) (args); - - catch_hook = old_catch; - receiver = old_receiver; -} - -/* Forwarder used for initializing GLRO (_dl_catch_error). */ -int -_rtld_catch_error (const char **objname, const char **errstring, - bool *mallocedp, void (*operate) (void *), - void *args) -{ - /* The reference to _dl_catch_error will eventually be relocated to - point to the implementation in libc.so. */ - return _dl_catch_error (objname, errstring, mallocedp, operate, args); -} - -#endif /* DL_ERROR_BOOTSTRAP */ diff --git a/elf/dl-error-minimal.c b/elf/dl-error-minimal.c deleted file mode 100644 index 9b833b9..0000000 --- a/elf/dl-error-minimal.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Error handling for runtime dynamic linker, minimal version. - Copyright (C) 1995-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - 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 version does lives in ld.so, does not use thread-local data - and supports _dl_signal_cerror and _dl_receive_error. */ - -#define DL_ERROR_BOOTSTRAP 1 -#include "dl-error-skeleton.c" diff --git a/elf/dl-error.c b/elf/dl-error.c deleted file mode 100644 index 0b7332a..0000000 --- a/elf/dl-error.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Error handling for runtime dynamic linker, full version. - Copyright (C) 1995-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - 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 implementation lives in libc.so because it uses thread-local - data, which is not available in ld.so. It interposes the version - in dl-error-minimal.c after ld.so bootstrap. - - The signal/catch mechanism is used by the audit framework, which - means that even in ld.so, not all errors are fatal. */ - -#define DL_ERROR_BOOTSTRAP 0 -#include "dl-error-skeleton.c" @@ -370,7 +370,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_lookup_symbol_x = _dl_lookup_symbol_x, ._dl_open = _dl_open, ._dl_close = _dl_close, - ._dl_catch_error = _rtld_catch_error, + ._dl_catch_error = _dl_catch_error, ._dl_error_free = _dl_error_free, ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, ._dl_libc_freeres = __rtld_libc_freeres, |