chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / elf / dl-caller.c
1 /* Check whether caller comes from the right place.
2    Copyright (C) 2004, 2009 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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <assert.h>
21 #include <ldsodefs.h>
22 #include <stddef.h>
23 #include <caller.h>
24 #include <gnu/lib-names.h>
25
26
27 int
28 attribute_hidden
29 _dl_check_caller (const void *caller, enum allowmask mask)
30 {
31   static const char expected1[] = LIBC_SO;
32   static const char expected2[] = LIBDL_SO;
33 #ifdef LIBPTHREAD_SO
34   static const char expected3[] = LIBPTHREAD_SO;
35 #endif
36   static const char expected4[] = LD_SO;
37
38   for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
39     for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
40          l = l->l_next)
41       if (caller >= (const void *) l->l_map_start
42           && caller < (const void *) l->l_text_end)
43         {
44           /* The address falls into this DSO's address range.  Check the
45              name.  */
46           if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0)
47             return 0;
48           if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0)
49             return 0;
50 #ifdef LIBPTHREAD_SO
51           if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0)
52             return 0;
53 #endif
54           if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0)
55             return 0;
56
57           struct libname_list *runp = l->l_libname;
58
59           while (runp != NULL)
60             {
61               if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0)
62                 return 0;
63               if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0)
64                 return 0;
65 #ifdef LIBPTHREAD_SO
66               if ((mask & allow_libpthread)
67                   && strcmp (expected3, runp->name) == 0)
68                 return 0;
69 #endif
70               if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0)
71                 return 0;
72
73               runp = runp->next;
74             }
75
76           break;
77         }
78
79   /* Maybe the dynamic linker is not yet on the list.  */
80   if ((mask & allow_ldso) != 0
81       && caller >= (const void *) GL(dl_rtld_map).l_map_start
82       && caller < (const void *) GL(dl_rtld_map).l_text_end)
83     return 0;
84
85   /* No valid caller.  */
86   return 1;
87 }