]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - elf/dl-deps.c
elf: Refuse to dlopen PIE objects [BZ #24323]
[thirdparty/glibc.git] / elf / dl-deps.c
index 622331e6e29d8ee1682f8bbd74614e949bf7daaa..e12c353158a1fa5cb76de1a62806c808f768d7af 100644 (file)
@@ -1,5 +1,5 @@
 /* Load the dependencies of a mapped object.
-   Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   Copyright (C) 1996-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
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <sys/param.h>
 #include <ldsodefs.h>
+#include <scratch_buffer.h>
 
 #include <dl-dst.h>
 
@@ -100,7 +101,7 @@ struct list
   ({                                                                         \
     const char *__str = (str);                                               \
     const char *__result = __str;                                            \
-    size_t __dst_cnt = DL_DST_COUNT (__str, 0);                                      \
+    size_t __dst_cnt = _dl_dst_count (__str);                                \
                                                                              \
     if (__dst_cnt != 0)                                                              \
       {                                                                              \
@@ -114,7 +115,7 @@ DST not allowed in SUID/SGID programs"));                                 \
        __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
                                                   __dst_cnt));               \
                                                                              \
-       __result = _dl_dst_substitute (l, __str, __newp, 0);                  \
+       __result = _dl_dst_substitute (l, __str, __newp);                     \
                                                                              \
        if (*__result == '\0')                                                \
          {                                                                   \
@@ -181,9 +182,8 @@ _dl_map_object_deps (struct link_map *map,
   /* Pointer to last unique object.  */
   tail = &known[nlist - 1];
 
-  /* No alloca'd space yet.  */
-  struct link_map **needed_space = NULL;
-  size_t needed_space_bytes = 0;
+  struct scratch_buffer needed_space;
+  scratch_buffer_init (&needed_space);
 
   /* Process each element of the search list, loading each of its
      auxiliary objects and immediate dependencies.  Auxiliary objects
@@ -213,13 +213,12 @@ _dl_map_object_deps (struct link_map *map,
       if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
          && l != map && l->l_ldnum > 0)
        {
-         size_t new_size = l->l_ldnum * sizeof (struct link_map *);
-
-         if (new_size > needed_space_bytes)
-           needed_space
-             = extend_alloca (needed_space, needed_space_bytes, new_size);
-
-         needed = needed_space;
+         /* l->l_ldnum includes space for the terminating NULL.  */
+         if (!scratch_buffer_set_array_size
+             (&needed_space, l->l_ldnum, sizeof (struct link_map *)))
+           _dl_signal_error (ENOMEM, map->l_name, NULL,
+                             N_("cannot allocate dependency buffer"));
+         needed = needed_space.data;
        }
 
       if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
@@ -438,8 +437,11 @@ _dl_map_object_deps (struct link_map *map,
          struct link_map **l_initfini = (struct link_map **)
            malloc ((2 * nneeded + 1) * sizeof needed[0]);
          if (l_initfini == NULL)
-           _dl_signal_error (ENOMEM, map->l_name, NULL,
-                             N_("cannot allocate dependency list"));
+           {
+             scratch_buffer_free (&needed_space);
+             _dl_signal_error (ENOMEM, map->l_name, NULL,
+                               N_("cannot allocate dependency list"));
+           }
          l_initfini[0] = l;
          memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]);
          memcpy (&l_initfini[nneeded + 1], l_initfini,
@@ -457,6 +459,8 @@ _dl_map_object_deps (struct link_map *map,
     }
 
  out:
+  scratch_buffer_free (&needed_space);
+
   if (errno == 0 && errno_saved != 0)
     __set_errno (errno_saved);