diff options
author | Florian Weimer <fweimer@redhat.com> | 2018-02-21 10:37:22 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2018-02-21 10:37:22 +0100 |
commit | 52a01100ad011293197637e42b5be1a479a2f4ae (patch) | |
tree | 8bfbd570b7eda10ee7de5fcb8ce430c1043af0f0 /elf/dl-caller.c | |
parent | b5bf62e40c5ff4e3906572f257dcda77b393ffa0 (diff) | |
download | glibc-52a01100ad011293197637e42b5be1a479a2f4ae.tar glibc-52a01100ad011293197637e42b5be1a479a2f4ae.tar.gz glibc-52a01100ad011293197637e42b5be1a479a2f4ae.tar.bz2 glibc-52a01100ad011293197637e42b5be1a479a2f4ae.zip |
elf: Remove ad-hoc restrictions on dlopen callers [BZ #22787]
This looks like a post-exploitation hardening measure: If an attacker is
able to redirect execution flow, they could use that to load a DSO which
contains additional code (or perhaps make the stack executable).
However, the checks are not in the correct place to be effective: If
they are performed before the critical operation, an attacker with
sufficient control over execution flow could simply jump directly to
the code which performs the operation, bypassing the check. The check
would have to be executed unconditionally after the operation and
terminate the process in case a caller violation was detected.
Furthermore, in _dl_check_caller, there was a fallback reading global
writable data (GL(dl_rtld_map).l_map_start and
GL(dl_rtld_map).l_text_end), which could conceivably be targeted by an
attacker to disable the check, too.
Other critical functions (such as system) remain completely
unprotected, so the value of these additional checks does not appear
that large. Therefore this commit removes this functionality.
Diffstat (limited to 'elf/dl-caller.c')
-rw-r--r-- | elf/dl-caller.c | 86 |
1 files changed, 0 insertions, 86 deletions
diff --git a/elf/dl-caller.c b/elf/dl-caller.c deleted file mode 100644 index 81a77af4eb..0000000000 --- a/elf/dl-caller.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Check whether caller comes from the right place. - Copyright (C) 2004-2018 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 <assert.h> -#include <ldsodefs.h> -#include <stddef.h> -#include <caller.h> -#include <gnu/lib-names.h> - - -int -attribute_hidden -_dl_check_caller (const void *caller, enum allowmask mask) -{ - static const char expected1[] = LIBC_SO; - static const char expected2[] = LIBDL_SO; -#ifdef LIBPTHREAD_SO - static const char expected3[] = LIBPTHREAD_SO; -#endif - static const char expected4[] = LD_SO; - - for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) - for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; - l = l->l_next) - if (caller >= (const void *) l->l_map_start - && caller < (const void *) l->l_text_end) - { - /* The address falls into this DSO's address range. Check the - name. */ - if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0) - return 0; - if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0) - return 0; -#ifdef LIBPTHREAD_SO - if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0) - return 0; -#endif - if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0) - return 0; - - struct libname_list *runp = l->l_libname; - - while (runp != NULL) - { - if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0) - return 0; - if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0) - return 0; -#ifdef LIBPTHREAD_SO - if ((mask & allow_libpthread) - && strcmp (expected3, runp->name) == 0) - return 0; -#endif - if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0) - return 0; - - runp = runp->next; - } - - break; - } - - /* Maybe the dynamic linker is not yet on the list. */ - if ((mask & allow_ldso) != 0 - && caller >= (const void *) GL(dl_rtld_map).l_map_start - && caller < (const void *) GL(dl_rtld_map).l_text_end) - return 0; - - /* No valid caller. */ - return 1; -} |