(linenum→info "unix/slp.c:2238")

glibc/2.7/elf/check-textrel.c

    1: /* Check for text relocations in DSOs.
    2:    Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Contribute by Ulrich Drepper <drepper@redhat.com>. 2002.
    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 <byteswap.h>
   22: #include <elf.h>
   23: #include <endian.h>
   24: #include <fcntl.h>
   25: #include <stdio.h>
   26: #include <stdlib.h>
   27: #include <string.h>
   28: #include <unistd.h>
   29: 
   30: 
   31: #ifdef BITS
   32: 
   33: # define AB(name) _AB (name, BITS)
   34: # define _AB(name, bits) __AB (name, bits)
   35: # define __AB(name, bits) name##bits
   36: # define E(name) _E (name, BITS)
   37: # define _E(name, bits) __E (name, bits)
   38: # define __E(name, bits) Elf##bits##_##name
   39: # define SWAP(val) \
   40:   ({ __typeof (val) __res;                                                    \
   41:      if (((ehdr.e_ident[EI_DATA] == ELFDATA2MSB                               \
   42:            && BYTE_ORDER == LITTLE_ENDIAN)                                   \
   43:           || (ehdr.e_ident[EI_DATA] == ELFDATA2LSB                           \
   44:               && BYTE_ORDER == BIG_ENDIAN))                                  \
   45:          && sizeof (val) != 1)                                               \
   46:        {                                                                      \
   47:          if (sizeof (val) == 2)                                                      \
   48:            __res = bswap_16 (val);                                           \
   49:          else if (sizeof (val) == 4)                                         \
   50:            __res = bswap_32 (val);                                           \
   51:          else                                                                \
   52:            __res = bswap_64 (val);                                           \
   53:        }                                                                      \
   54:      else                                                                     \
   55:        __res = (val);                                                         \
   56:      __res; })
   57: 
   58: 
   59: static int
   60: AB(handle_file) (const char *fname, int fd)
   61: {
   62:   E(Ehdr) ehdr;
   63: 
   64:   if (pread (fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr))
   65:     {
   66:     read_error:
   67:       printf ("%s: read error: %m\n", fname);
   68:       return 1;
   69:     }
   70: 
   71:   const size_t phnum = SWAP (ehdr.e_phnum);
   72:   const size_t phentsize = SWAP (ehdr.e_phentsize);
   73: 
   74:   /* Read the program header.  */
   75:   E(Phdr) *phdr = alloca (phentsize * phnum);
   76:   if (pread (fd, phdr, phentsize * phnum, SWAP (ehdr.e_phoff))
   77:       != phentsize * phnum)
   78:     goto read_error;
   79: 
   80:   /* Search for the PT_DYNAMIC entry.  */
   81:   size_t cnt;
   82:   E(Phdr) *dynphdr = NULL;
   83:   for (cnt = 0; cnt < phnum; ++cnt)
   84:     if (SWAP (phdr[cnt].p_type) == PT_DYNAMIC)
   85:       dynphdr = &phdr[cnt];
   86:     else if (SWAP (phdr[cnt].p_type) == PT_LOAD
   87:              && (SWAP (phdr[cnt].p_flags) & (PF_X | PF_W)) == (PF_X | PF_W))
   88:       {
   89:         printf ("%s: segment %zu is executable and writable\n",
   90:                 fname, cnt);
   91: #if !defined __sparc__ \
   92:     && !defined __alpha__ \
   93:     && (!defined __powerpc__ || defined __powerpc64__ || defined HAVE_PPC_SECURE_PLT)
   94:         /* sparc, sparc64, alpha and powerpc32 (the last one only when using
   95:            -mbss-plt) are expected to have PF_X | PF_W segment containing .plt
   96:            section, it is part of their ABI.  It is bad security wise, nevertheless
   97:            this test shouldn't fail because of this.  */
   98:         return 1;
   99: #endif
  100:       }
  101: 
  102:   if (dynphdr == NULL)
  103:     {
  104:       printf ("%s: no DYNAMIC segment found\n", fname);
  105:       return 1;
  106:     }
  107: 
  108:   /* Read the dynamic segment.  */
  109:   size_t pmemsz = SWAP(dynphdr->p_memsz);
  110:   E(Dyn) *dyn = alloca (pmemsz);
  111:   if (pread (fd, dyn, pmemsz, SWAP(dynphdr->p_offset)) != pmemsz)
  112:     goto read_error;
  113: 
  114:   /* Search for an DT_TEXTREL entry of DT_FLAGS with the DF_TEXTREL
  115:      bit set.  */
  116:   for (cnt = 0; (cnt + 1) * sizeof (E(Dyn)) - 1 < pmemsz; ++cnt)
  117:     {
  118:       unsigned int tag = SWAP (dyn[cnt].d_tag);
  119: 
  120:       if (tag == DT_NULL)
  121:         /* We reached the end.  */
  122:         break;
  123: 
  124:       if (tag == DT_TEXTREL
  125:           || (tag == DT_FLAGS
  126:               && (SWAP (dyn[cnt].d_un.d_val) & DF_TEXTREL) != 0))
  127:         {
  128:           /* Urgh!  The DSO has text relocations.  */
  129:           printf ("%s: text relocations used\n", fname);
  130:           return 1;
  131:         }
  132:     }
  133: 
  134:   printf ("%s: OK\n", fname);
  135: 
  136:   return 0;
  137: }
  138: 
  139: # undef BITS
  140: #else
  141: 
  142: # define BITS 32
  143: # include "check-textrel.c"
  144: 
  145: # define BITS 64
  146: # include "check-textrel.c"
  147: 
  148: 
  149: static int
  150: handle_file (const char *fname)
  151: {
  152:   int fd = open (fname, O_RDONLY);
  153:   if (fd == -1)
  154:     {
  155:       printf ("cannot open %s: %m\n", fname);
  156:       return 1;
  157:     }
  158: 
  159:   /* Read was is supposed to be the ELF header.  Read the initial
  160:      bytes to determine whether this is a 32 or 64 bit file.  */
  161:   char ident[EI_NIDENT];
  162:   if (read (fd, ident, EI_NIDENT) != EI_NIDENT)
  163:     {
  164:       printf ("%s: read error: %m\n", fname);
  165:       close (fd);
  166:       return 1;
  167:     }
  168: 
  169:   if (memcmp (&ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
  170:     {
  171:       printf ("%s: not an ELF file\n", fname);
  172:       close (fd);
  173:       return 1;
  174:     }
  175: 
  176:   int result;
  177:   if (ident[EI_CLASS] == ELFCLASS64)
  178:     result = handle_file64 (fname, fd);
  179:   else
  180:     result = handle_file32 (fname, fd);
  181: 
  182:   close (fd);
  183: 
  184:   return result;
  185: }
  186: 
  187: 
  188: int
  189: main (int argc, char *argv[])
  190: {
  191:   int cnt;
  192:   int result = 0;
  193: 
  194:   for (cnt = 1; cnt < argc; ++cnt)
  195:     result |= handle_file (argv[cnt]);
  196: 
  197:   return result;
  198: }
  199: #endif
Syntax (Markdown)