[BZ #15859] Fix memory leak in _dl_map_object_deps
[platform/upstream/glibc.git] / elf / dl-deps.c
1 /* Load the dependencies of a mapped object.
2    Copyright (C) 1996-2013 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <atomic.h>
20 #include <assert.h>
21 #include <dlfcn.h>
22 #include <errno.h>
23 #include <libintl.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/param.h>
29 #include <ldsodefs.h>
30
31 #include <dl-dst.h>
32
33 /* Whether an shared object references one or more auxiliary objects
34    is signaled by the AUXTAG entry in l_info.  */
35 #define AUXTAG  (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
36                  + DT_EXTRATAGIDX (DT_AUXILIARY))
37 /* Whether an shared object references one or more auxiliary objects
38    is signaled by the AUXTAG entry in l_info.  */
39 #define FILTERTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
40                    + DT_EXTRATAGIDX (DT_FILTER))
41
42
43 /* When loading auxiliary objects we must ignore errors.  It's ok if
44    an object is missing.  */
45 struct openaux_args
46   {
47     /* The arguments to openaux.  */
48     struct link_map *map;
49     int trace_mode;
50     int open_mode;
51     const char *strtab;
52     const char *name;
53
54     /* The return value of openaux.  */
55     struct link_map *aux;
56   };
57
58 static void
59 openaux (void *a)
60 {
61   struct openaux_args *args = (struct openaux_args *) a;
62
63   args->aux = _dl_map_object (args->map, args->name,
64                               (args->map->l_type == lt_executable
65                                ? lt_library : args->map->l_type),
66                               args->trace_mode, args->open_mode,
67                               args->map->l_ns);
68 }
69
70 static ptrdiff_t
71 internal_function
72 _dl_build_local_scope (struct link_map **list, struct link_map *map)
73 {
74   struct link_map **p = list;
75   struct link_map **q;
76
77   *p++ = map;
78   map->l_reserved = 1;
79   if (map->l_initfini)
80     for (q = map->l_initfini + 1; *q; ++q)
81       if (! (*q)->l_reserved)
82         p += _dl_build_local_scope (p, *q);
83   return p - list;
84 }
85
86
87 /* We use a very special kind of list to track the path
88    through the list of loaded shared objects.  We have to
89    produce a flat list with unique members of all involved objects.
90 */
91 struct list
92   {
93     int done;                   /* Nonzero if this map was processed.  */
94     struct link_map *map;       /* The data.  */
95     struct list *next;          /* Elements for normal list.  */
96   };
97
98
99 /* Macro to expand DST.  It is an macro since we use `alloca'.  */
100 #define expand_dst(l, str, fatal) \
101   ({                                                                          \
102     const char *__str = (str);                                                \
103     const char *__result = __str;                                             \
104     size_t __dst_cnt = DL_DST_COUNT (__str, 0);                               \
105                                                                               \
106     if (__dst_cnt != 0)                                                       \
107       {                                                                       \
108         char *__newp;                                                         \
109                                                                               \
110         /* DST must not appear in SUID/SGID programs.  */                     \
111         if (INTUSE(__libc_enable_secure))                                     \
112           _dl_signal_error (0, __str, NULL, N_("\
113 DST not allowed in SUID/SGID programs"));                                     \
114                                                                               \
115         __newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str),  \
116                                                    __dst_cnt));               \
117                                                                               \
118         __result = _dl_dst_substitute (l, __str, __newp, 0);                  \
119                                                                               \
120         if (*__result == '\0')                                                \
121           {                                                                   \
122             /* The replacement for the DST is not known.  We can't            \
123                processed.  */                                                 \
124             if (fatal)                                                        \
125               _dl_signal_error (0, __str, NULL, N_("\
126 empty dynamic string token substitution"));                                   \
127             else                                                              \
128               {                                                               \
129                 /* This is for DT_AUXILIARY.  */                              \
130                 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))\
131                   _dl_debug_printf (N_("\
132 cannot load auxiliary `%s' because of empty dynamic string token "            \
133                                             "substitution\n"), __str);        \
134                 continue;                                                     \
135               }                                                               \
136           }                                                                   \
137       }                                                                       \
138                                                                               \
139     __result; })
140
141
142 void
143 internal_function
144 _dl_map_object_deps (struct link_map *map,
145                      struct link_map **preloads, unsigned int npreloads,
146                      int trace_mode, int open_mode)
147 {
148   struct list *known = __alloca (sizeof *known * (1 + npreloads + 1));
149   struct list *runp, *tail;
150   unsigned int nlist, i;
151   /* Object name.  */
152   const char *name;
153   int errno_saved;
154   int errno_reason;
155   const char *errstring;
156   const char *objname;
157
158   void preload (struct link_map *map)
159     {
160       known[nlist].done = 0;
161       known[nlist].map = map;
162       known[nlist].next = &known[nlist + 1];
163
164       ++nlist;
165       /* We use `l_reserved' as a mark bit to detect objects we have
166          already put in the search list and avoid adding duplicate
167          elements later in the list.  */
168       map->l_reserved = 1;
169     }
170
171   /* No loaded object so far.  */
172   nlist = 0;
173
174   /* First load MAP itself.  */
175   preload (map);
176
177   /* Add the preloaded items after MAP but before any of its dependencies.  */
178   for (i = 0; i < npreloads; ++i)
179     preload (preloads[i]);
180
181   /* Terminate the lists.  */
182   known[nlist - 1].next = NULL;
183
184   /* Pointer to last unique object.  */
185   tail = &known[nlist - 1];
186
187   /* No alloca'd space yet.  */
188   struct link_map **needed_space = NULL;
189   size_t needed_space_bytes = 0;
190
191   /* Process each element of the search list, loading each of its
192      auxiliary objects and immediate dependencies.  Auxiliary objects
193      will be added in the list before the object itself and
194      dependencies will be appended to the list as we step through it.
195      This produces a flat, ordered list that represents a
196      breadth-first search of the dependency tree.
197
198      The whole process is complicated by the fact that we better
199      should use alloca for the temporary list elements.  But using
200      alloca means we cannot use recursive function calls.  */
201   errno_saved = errno;
202   errno_reason = 0;
203   errstring = NULL;
204   errno = 0;
205   name = NULL;
206   for (runp = known; runp; )
207     {
208       struct link_map *l = runp->map;
209       struct link_map **needed = NULL;
210       unsigned int nneeded = 0;
211
212       /* Unless otherwise stated, this object is handled.  */
213       runp->done = 1;
214
215       /* Allocate a temporary record to contain the references to the
216          dependencies of this object.  */
217       if (l->l_searchlist.r_list == NULL && l->l_initfini == NULL
218           && l != map && l->l_ldnum > 0)
219         {
220           size_t new_size = l->l_ldnum * sizeof (struct link_map *);
221
222           if (new_size > needed_space_bytes)
223             needed_space
224               = extend_alloca (needed_space, needed_space_bytes, new_size);
225
226           needed = needed_space;
227         }
228
229       if (l->l_info[DT_NEEDED] || l->l_info[AUXTAG] || l->l_info[FILTERTAG])
230         {
231           const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
232           struct openaux_args args;
233           struct list *orig;
234           const ElfW(Dyn) *d;
235
236           args.strtab = strtab;
237           args.map = l;
238           args.trace_mode = trace_mode;
239           args.open_mode = open_mode;
240           orig = runp;
241
242           for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
243             if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
244               {
245                 /* Map in the needed object.  */
246                 struct link_map *dep;
247
248                 /* Recognize DSTs.  */
249                 name = expand_dst (l, strtab + d->d_un.d_val, 0);
250                 /* Store the tag in the argument structure.  */
251                 args.name = name;
252
253                 bool malloced;
254                 int err = _dl_catch_error (&objname, &errstring, &malloced,
255                                            openaux, &args);
256                 if (__builtin_expect (errstring != NULL, 0))
257                   {
258                     char *new_errstring = strdupa (errstring);
259                     objname = strdupa (objname);
260                     if (malloced)
261                       free ((char *) errstring);
262                     errstring = new_errstring;
263
264                     if (err)
265                       errno_reason = err;
266                     else
267                       errno_reason = -1;
268                     goto out;
269                   }
270                 else
271                   dep = args.aux;
272
273                 if (! dep->l_reserved)
274                   {
275                     /* Allocate new entry.  */
276                     struct list *newp;
277
278                     newp = alloca (sizeof (struct list));
279
280                     /* Append DEP to the list.  */
281                     newp->map = dep;
282                     newp->done = 0;
283                     newp->next = NULL;
284                     tail->next = newp;
285                     tail = newp;
286                     ++nlist;
287                     /* Set the mark bit that says it's already in the list.  */
288                     dep->l_reserved = 1;
289                   }
290
291                 /* Remember this dependency.  */
292                 if (needed != NULL)
293                   needed[nneeded++] = dep;
294               }
295             else if (d->d_tag == DT_AUXILIARY || d->d_tag == DT_FILTER)
296               {
297                 struct list *newp;
298
299                 /* Recognize DSTs.  */
300                 name = expand_dst (l, strtab + d->d_un.d_val,
301                                    d->d_tag == DT_AUXILIARY);
302                 /* Store the tag in the argument structure.  */
303                 args.name = name;
304
305                 if (d->d_tag == DT_AUXILIARY)
306                   {
307                     /* Say that we are about to load an auxiliary library.  */
308                     if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
309                                           0))
310                       _dl_debug_printf ("load auxiliary object=%s"
311                                         " requested by file=%s\n",
312                                         name,
313                                         DSO_FILENAME (l->l_name));
314
315                     /* We must be prepared that the addressed shared
316                        object is not available.  */
317                     bool malloced;
318                     (void) _dl_catch_error (&objname, &errstring, &malloced,
319                                             openaux, &args);
320                     if (__builtin_expect (errstring != NULL, 0))
321                       {
322                         /* We are not interested in the error message.  */
323                         assert (errstring != NULL);
324                         if (malloced)
325                           free ((char *) errstring);
326
327                         /* Simply ignore this error and continue the work.  */
328                         continue;
329                       }
330                   }
331                 else
332                   {
333                     /* Say that we are about to load an auxiliary library.  */
334                     if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS,
335                                           0))
336                       _dl_debug_printf ("load filtered object=%s"
337                                         " requested by file=%s\n",
338                                         name,
339                                         DSO_FILENAME (l->l_name));
340
341                     /* For filter objects the dependency must be available.  */
342                     bool malloced;
343                     int err = _dl_catch_error (&objname, &errstring, &malloced,
344                                                openaux, &args);
345                     if (__builtin_expect (errstring != NULL, 0))
346                       {
347                         char *new_errstring = strdupa (errstring);
348                         objname = strdupa (objname);
349                         if (malloced)
350                           free ((char *) errstring);
351                         errstring = new_errstring;
352
353                         if (err)
354                           errno_reason = err;
355                         else
356                           errno_reason = -1;
357                         goto out;
358                       }
359                   }
360
361                 /* The auxiliary object is actually available.
362                    Incorporate the map in all the lists.  */
363
364                 /* Allocate new entry.  This always has to be done.  */
365                 newp = alloca (sizeof (struct list));
366
367                 /* We want to insert the new map before the current one,
368                    but we have no back links.  So we copy the contents of
369                    the current entry over.  Note that ORIG and NEWP now
370                    have switched their meanings.  */
371                 memcpy (newp, orig, sizeof (*newp));
372
373                 /* Initialize new entry.  */
374                 orig->done = 0;
375                 orig->map = args.aux;
376
377                 /* Remember this dependency.  */
378                 if (needed != NULL)
379                   needed[nneeded++] = args.aux;
380
381                 /* We must handle two situations here: the map is new,
382                    so we must add it in all three lists.  If the map
383                    is already known, we have two further possibilities:
384                    - if the object is before the current map in the
385                    search list, we do nothing.  It is already found
386                    early
387                    - if the object is after the current one, we must
388                    move it just before the current map to make sure
389                    the symbols are found early enough
390                 */
391                 if (args.aux->l_reserved)
392                   {
393                     /* The object is already somewhere in the list.
394                        Locate it first.  */
395                     struct list *late;
396
397                     /* This object is already in the search list we
398                        are building.  Don't add a duplicate pointer.
399                        Just added by _dl_map_object.  */
400                     for (late = newp; late->next != NULL; late = late->next)
401                       if (late->next->map == args.aux)
402                         break;
403
404                     if (late->next != NULL)
405                       {
406                         /* The object is somewhere behind the current
407                            position in the search path.  We have to
408                            move it to this earlier position.  */
409                         orig->next = newp;
410
411                         /* Now remove the later entry from the list
412                            and adjust the tail pointer.  */
413                         if (tail == late->next)
414                           tail = late;
415                         late->next = late->next->next;
416
417                         /* We must move the object earlier in the chain.  */
418                         if (args.aux->l_prev != NULL)
419                           args.aux->l_prev->l_next = args.aux->l_next;
420                         if (args.aux->l_next != NULL)
421                           args.aux->l_next->l_prev = args.aux->l_prev;
422
423                         args.aux->l_prev = newp->map->l_prev;
424                         newp->map->l_prev = args.aux;
425                         if (args.aux->l_prev != NULL)
426                           args.aux->l_prev->l_next = args.aux;
427                         args.aux->l_next = newp->map;
428                       }
429                     else
430                       {
431                         /* The object must be somewhere earlier in the
432                            list.  Undo to the current list element what
433                            we did above.  */
434                         memcpy (orig, newp, sizeof (*newp));
435                         continue;
436                       }
437                   }
438                 else
439                   {
440                     /* This is easy.  We just add the symbol right here.  */
441                     orig->next = newp;
442                     ++nlist;
443                     /* Set the mark bit that says it's already in the list.  */
444                     args.aux->l_reserved = 1;
445
446                     /* The only problem is that in the double linked
447                        list of all objects we don't have this new
448                        object at the correct place.  Correct this here.  */
449                     if (args.aux->l_prev)
450                       args.aux->l_prev->l_next = args.aux->l_next;
451                     if (args.aux->l_next)
452                       args.aux->l_next->l_prev = args.aux->l_prev;
453
454                     args.aux->l_prev = newp->map->l_prev;
455                     newp->map->l_prev = args.aux;
456                     if (args.aux->l_prev != NULL)
457                       args.aux->l_prev->l_next = args.aux;
458                     args.aux->l_next = newp->map;
459                   }
460
461                 /* Move the tail pointer if necessary.  */
462                 if (orig == tail)
463                   tail = newp;
464
465                 /* Move on the insert point.  */
466                 orig = newp;
467               }
468         }
469
470       /* Terminate the list of dependencies and store the array address.  */
471       if (needed != NULL)
472         {
473           needed[nneeded++] = NULL;
474
475           struct link_map **l_initfini = (struct link_map **)
476             malloc ((2 * nneeded + 1) * sizeof needed[0]);
477           if (l_initfini == NULL)
478             _dl_signal_error (ENOMEM, map->l_name, NULL,
479                               N_("cannot allocate dependency list"));
480           l_initfini[0] = l;
481           memcpy (&l_initfini[1], needed, nneeded * sizeof needed[0]);
482           memcpy (&l_initfini[nneeded + 1], l_initfini,
483                   nneeded * sizeof needed[0]);
484           atomic_write_barrier ();
485           l->l_initfini = l_initfini;
486           l->l_free_initfini = 1;
487         }
488
489       /* If we have no auxiliary objects just go on to the next map.  */
490       if (runp->done)
491         do
492           runp = runp->next;
493         while (runp != NULL && runp->done);
494     }
495
496  out:
497   if (errno == 0 && errno_saved != 0)
498     __set_errno (errno_saved);
499
500   struct link_map **old_l_initfini = NULL;
501   if (map->l_initfini != NULL && map->l_type == lt_loaded)
502     {
503       /* This object was previously loaded as a dependency and we have
504          a separate l_initfini list.  We don't need it anymore.  */
505       assert (map->l_searchlist.r_list == NULL);
506       old_l_initfini = map->l_initfini;
507     }
508
509   /* Store the search list we built in the object.  It will be used for
510      searches in the scope of this object.  */
511   struct link_map **l_initfini =
512     (struct link_map **) malloc ((2 * nlist + 1)
513                                  * sizeof (struct link_map *));
514   if (l_initfini == NULL)
515     _dl_signal_error (ENOMEM, map->l_name, NULL,
516                       N_("cannot allocate symbol search list"));
517
518
519   map->l_searchlist.r_list = &l_initfini[nlist + 1];
520   map->l_searchlist.r_nlist = nlist;
521
522   for (nlist = 0, runp = known; runp; runp = runp->next)
523     {
524       if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
525         /* This can happen when we trace the loading.  */
526         --map->l_searchlist.r_nlist;
527       else
528         map->l_searchlist.r_list[nlist++] = runp->map;
529
530       /* Now clear all the mark bits we set in the objects on the search list
531          to avoid duplicates, so the next call starts fresh.  */
532       runp->map->l_reserved = 0;
533     }
534
535   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0
536       && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
537     {
538       /* If we are to compute conflicts, we have to build local scope
539          for each library, not just the ultimate loader.  */
540       for (i = 0; i < nlist; ++i)
541         {
542           struct link_map *l = map->l_searchlist.r_list[i];
543           unsigned int j, cnt;
544
545           /* The local scope has been already computed.  */
546           if (l == map
547               || (l->l_local_scope[0]
548                   && l->l_local_scope[0]->r_nlist) != 0)
549             continue;
550
551           if (l->l_info[AUXTAG] || l->l_info[FILTERTAG])
552             {
553               /* As current DT_AUXILIARY/DT_FILTER implementation needs to be
554                  rewritten, no need to bother with prelinking the old
555                  implementation.  */
556               _dl_signal_error (EINVAL, l->l_name, NULL, N_("\
557 Filters not supported with LD_TRACE_PRELINKING"));
558             }
559
560           cnt = _dl_build_local_scope (l_initfini, l);
561           assert (cnt <= nlist);
562           for (j = 0; j < cnt; j++)
563             {
564               l_initfini[j]->l_reserved = 0;
565               if (j && __builtin_expect (l_initfini[j]->l_info[DT_SYMBOLIC]
566                                          != NULL, 0))
567                 l->l_symbolic_in_local_scope = true;
568             }
569
570           l->l_local_scope[0] =
571             (struct r_scope_elem *) malloc (sizeof (struct r_scope_elem)
572                                             + (cnt
573                                                * sizeof (struct link_map *)));
574           if (l->l_local_scope[0] == NULL)
575             _dl_signal_error (ENOMEM, map->l_name, NULL,
576                               N_("cannot allocate symbol search list"));
577           l->l_local_scope[0]->r_nlist = cnt;
578           l->l_local_scope[0]->r_list =
579             (struct link_map **) (l->l_local_scope[0] + 1);
580           memcpy (l->l_local_scope[0]->r_list, l_initfini,
581                   cnt * sizeof (struct link_map *));
582         }
583     }
584
585   /* Maybe we can remove some relocation dependencies now.  */
586   assert (map->l_searchlist.r_list[0] == map);
587   struct link_map_reldeps *l_reldeps = NULL;
588   if (map->l_reldeps != NULL)
589     {
590       for (i = 1; i < nlist; ++i)
591         map->l_searchlist.r_list[i]->l_reserved = 1;
592
593       struct link_map **list = &map->l_reldeps->list[0];
594       for (i = 0; i < map->l_reldeps->act; ++i)
595         if (list[i]->l_reserved)
596           {
597             /* Need to allocate new array of relocation dependencies.  */
598             l_reldeps = malloc (sizeof (*l_reldeps)
599                                 + map->l_reldepsmax
600                                   * sizeof (struct link_map *));
601             if (l_reldeps == NULL)
602               /* Bad luck, keep the reldeps duplicated between
603                  map->l_reldeps->list and map->l_initfini lists.  */
604               ;
605             else
606               {
607                 unsigned int j = i;
608                 memcpy (&l_reldeps->list[0], &list[0],
609                         i * sizeof (struct link_map *));
610                 for (i = i + 1; i < map->l_reldeps->act; ++i)
611                   if (!list[i]->l_reserved)
612                     l_reldeps->list[j++] = list[i];
613                 l_reldeps->act = j;
614               }
615           }
616
617       for (i = 1; i < nlist; ++i)
618         map->l_searchlist.r_list[i]->l_reserved = 0;
619     }
620
621   /* Sort the initializer list to take dependencies into account.  The binary
622      itself will always be initialize last.  */
623   memcpy (l_initfini, map->l_searchlist.r_list,
624           nlist * sizeof (struct link_map *));
625   if (__builtin_expect (nlist > 1, 1))
626     {
627       /* We can skip looking for the binary itself which is at the front
628          of the search list.  */
629       i = 1;
630       uint16_t seen[nlist];
631       memset (seen, 0, nlist * sizeof (seen[0]));
632       while (1)
633         {
634           /* Keep track of which object we looked at this round.  */
635           ++seen[i];
636           struct link_map *thisp = l_initfini[i];
637
638           /* Find the last object in the list for which the current one is
639              a dependency and move the current object behind the object
640              with the dependency.  */
641           unsigned int k = nlist - 1;
642           while (k > i)
643             {
644               struct link_map **runp = l_initfini[k]->l_initfini;
645               if (runp != NULL)
646                 /* Look through the dependencies of the object.  */
647                 while (*runp != NULL)
648                   if (__builtin_expect (*runp++ == thisp, 0))
649                     {
650                       /* Move the current object to the back past the last
651                          object with it as the dependency.  */
652                       memmove (&l_initfini[i], &l_initfini[i + 1],
653                                (k - i) * sizeof (l_initfini[0]));
654                       l_initfini[k] = thisp;
655
656                       if (seen[i + 1] > nlist - i)
657                         {
658                           ++i;
659                           goto next_clear;
660                         }
661
662                       uint16_t this_seen = seen[i];
663                       memmove (&seen[i], &seen[i + 1],
664                                (k - i) * sizeof (seen[0]));
665                       seen[k] = this_seen;
666
667                       goto next;
668                     }
669
670               --k;
671             }
672
673           if (++i == nlist)
674             break;
675         next_clear:
676           memset (&seen[i], 0, (nlist - i) * sizeof (seen[0]));
677
678         next:;
679         }
680     }
681
682   /* Terminate the list of dependencies.  */
683   l_initfini[nlist] = NULL;
684   atomic_write_barrier ();
685   map->l_initfini = l_initfini;
686   map->l_free_initfini = 1;
687   if (l_reldeps != NULL)
688     {
689       atomic_write_barrier ();
690       void *old_l_reldeps = map->l_reldeps;
691       map->l_reldeps = l_reldeps;
692       _dl_scope_free (old_l_reldeps);
693     }
694   if (old_l_initfini != NULL)
695     _dl_scope_free (old_l_initfini);
696
697   if (errno_reason)
698     _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname,
699                       NULL, errstring);
700 }