]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - elf/dl-error.c
elf: Refuse to dlopen PIE objects [BZ #24323]
[thirdparty/glibc.git] / elf / dl-error.c
index 8257c170300813b2c150e29588bbecc96c09e857..f047618a07263bcfff78456bc8a3280252255efe 100644 (file)
@@ -1,5 +1,5 @@
-/* Error handling for runtime dynamic linker.
-   Copyright (C) 1995-2013 Free Software Foundation, Inc.
+/* Error handling for runtime dynamic linker, full version.
+   Copyright (C) 1995-2019 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
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <libintl.h>
-#include <setjmp.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <ldsodefs.h>
+/* 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.
 
-/* This structure communicates state between _dl_catch_error and
-   _dl_signal_error.  */
-struct catch
-  {
-    const char *objname;       /* Object/File name.  */
-    const char *errstring;     /* Error detail filled in here.  */
-    bool malloced;             /* Nonzero if the string is malloced
-                                  by the libc malloc.  */
-    jmp_buf env;               /* longjmp here on error.  */
-  };
+   The signal/catch mechanism is used by the audit framework, which
+   means that even in ld.so, not all errors are fatal.  */
 
-/* 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.  The _dl_error_catch_tsd function pointer is reset by the thread
-   library so that it returns the address of a thread-local variable.  */
-
-
-/* This message we return as a last resort.  We define the string in a
-   variable since we have to avoid freeing it and so have to enable
-   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
-static const char _dl_out_of_memory[] = "out of memory";
-
-
-/* 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'.
-
-   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;
-
-#ifdef _LIBC_REENTRANT
-# define CATCH_HOOK    (*(struct catch **) (*GL(dl_error_catch_tsd)) ())
-#else
-static struct catch *catch_hook;
-# define CATCH_HOOK    catch_hook
-#endif
-
-void
-internal_function
-_dl_signal_error (int errcode, const char *objname, const char *occation,
-                 const char *errstring)
-{
-  struct catch *lcatch;
-
-  if (! errstring)
-    errstring = N_("DYNAMIC LINKER BUG!!!");
-
-  lcatch = CATCH_HOOK;
-  if (objname == NULL)
-    objname = "";
-  if (lcatch != NULL)
-    {
-      /* We are inside _dl_catch_error.  Return to it.  We have to
-        duplicate the error string since it might be allocated on the
-        stack.  The object name is always a string constant.  */
-      size_t len_objname = strlen (objname) + 1;
-      size_t len_errstring = strlen (errstring) + 1;
-
-      lcatch->errstring = (char *) malloc (len_objname + len_errstring);
-      if (lcatch->errstring != NULL)
-       {
-         /* Make a copy of the object file name and the error string.  */
-         lcatch->objname = memcpy (__mempcpy ((char *) lcatch->errstring,
-                                              errstring, len_errstring),
-                                   objname, len_objname);
-
-         /* If the main executable is relocated it means the libc's malloc
-            is used.  */
-#ifdef SHARED
-         lcatch->malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL
-                             && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated
-                                 != 0));
-#else
-         lcatch->malloced = true;
-#endif
-       }
-      else
-       {
-         /* This is better than nothing.  */
-         lcatch->objname = "";
-         lcatch->errstring = _dl_out_of_memory;
-         lcatch->malloced = false;
-       }
-      /* We do not restore the signal mask because none was saved.  */
-      __longjmp (lcatch->env[0].__jmpbuf, errcode ?: -1);
-    }
-  else
-    {
-      /* Lossage while resolving the program's own symbols is always fatal.  */
-      char buffer[1024];
-      _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
-                       RTLD_PROGNAME,
-                       occation ?: N_("error while loading shared libraries"),
-                       objname, *objname ? ": " : "",
-                       errstring, errcode ? ": " : "",
-                       (errcode
-                        ? __strerror_r (errcode, buffer, sizeof buffer)
-                        : ""));
-    }
-}
-
-
-void
-internal_function
-_dl_signal_cerror (int errcode, const char *objname, const char *occation,
-                  const char *errstring)
-{
-  if (__builtin_expect (GLRO(dl_debug_mask)
-                       & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
-    _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
-                     errstring, receiver ? "continued" : "fatal");
-
-  if (receiver)
-    {
-      /* We are inside _dl_receive_error.  Call the user supplied
-        handler and resume the work.  The receiver will still be
-        installed.  */
-      (*receiver) (errcode, objname, errstring);
-    }
-  else
-    _dl_signal_error (errcode, objname, occation, errstring);
-}
-
-
-int
-internal_function
-_dl_catch_error (const char **objname, const char **errstring,
-                bool *mallocedp, void (*operate) (void *), void *args)
-{
-  int errcode;
-  struct catch *volatile old;
-  struct catch c;
-  /* We need not handle `receiver' since setting a `catch' is handled
-     before it.  */
-
-  /* Some systems (e.g., SPARC) handle constructors to local variables
-     inefficient.  So we initialize `c' by hand.  */
-  c.errstring = NULL;
-
-  struct catch **const catchp = &CATCH_HOOK;
-  old = *catchp;
-  /* Do not save the signal mask.  */
-  errcode = __sigsetjmp (c.env, 0);
-  if (__builtin_expect (errcode, 0) == 0)
-    {
-      *catchp = &c;
-      (*operate) (args);
-      *catchp = old;
-      *objname = NULL;
-      *errstring = NULL;
-      *mallocedp = false;
-      return 0;
-    }
-
-  /* We get here only if we longjmp'd out of OPERATE.  */
-  *catchp = old;
-  *objname = c.objname;
-  *errstring = c.errstring;
-  *mallocedp = c.malloced;
-  return errcode == -1 ? 0 : errcode;
-}
-
-
-void
-internal_function
-_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
-{
-  struct catch **const catchp = &CATCH_HOOK;
-  struct catch *old_catch;
-  receiver_fct old_receiver;
-
-  old_catch = *catchp;
-  old_receiver = receiver;
-
-  /* Set the new values.  */
-  *catchp = NULL;
-  receiver = fct;
-
-  (*operate) (args);
-
-  *catchp = old_catch;
-  receiver = old_receiver;
-}
+#define DL_ERROR_BOOTSTRAP 0
+#include "dl-error-skeleton.c"