Back to index

glibc  2.9
dl-caller.c
Go to the documentation of this file.
00001 /* Check whether caller comes from the right place.
00002    Copyright (C) 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <ldsodefs.h>
00022 #include <stddef.h>
00023 #include <caller.h>
00024 #include <gnu/lib-names.h>
00025 
00026 
00027 int
00028 attribute_hidden
00029 _dl_check_caller (const void *caller, enum allowmask mask)
00030 {
00031   static const char expected1[] = LIBC_SO;
00032   static const char expected2[] = LIBDL_SO;
00033 #ifdef LIBPTHREAD_SO
00034   static const char expected3[] = LIBPTHREAD_SO;
00035 #endif
00036   static const char expected4[] = LD_SO;
00037 
00038   for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
00039     for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL;
00040         l = l->l_next)
00041       if (caller >= (const void *) l->l_map_start
00042          && caller < (const void *) l->l_text_end)
00043        {
00044          /* The address falls into this DSO's address range.  Check the
00045             name.  */
00046          if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0)
00047            return 0;
00048          if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0)
00049            return 0;
00050 #ifdef LIBPTHREAD_SO
00051          if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0)
00052            return 0;
00053 #endif
00054          if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0)
00055            return 0;
00056 
00057          struct libname_list *runp = l->l_libname;
00058 
00059          while (runp != NULL)
00060            {
00061              if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0)
00062               return 0;
00063              if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0)
00064               return 0;
00065 #ifdef LIBPTHREAD_SO
00066              if ((mask & allow_libpthread)
00067                 && strcmp (expected3, runp->name) == 0)
00068               return 0;
00069 #endif
00070              if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0)
00071               return 0;
00072 
00073              runp = runp->next;
00074            }
00075 
00076          break;
00077        }
00078 
00079   /* Maybe the dynamic linker is not yet on the list.  */
00080   if ((mask & allow_ldso) != 0
00081       && caller >= (const void *) GL(dl_rtld_map).l_map_start
00082       && caller < (const void *) GL(dl_rtld_map).l_text_end)
00083     return 0;
00084 
00085   /* No valid caller.  */
00086   return 1;
00087 }