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