]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
robustify: libelf.
authorJakub Jelinek <jakub@redhat.com>
Fri, 17 Jan 2014 18:36:16 +0000 (19:36 +0100)
committerMark Wielaard <mjw@redhat.com>
Thu, 23 Jan 2014 10:31:53 +0000 (11:31 +0100)
Signed-off-by: Mark Wielaard <mjw@redhat.com>
libelf/ChangeLog
libelf/elf32_getphdr.c
libelf/elf32_getshdr.c
libelf/elf32_newphdr.c
libelf/elf32_updatefile.c
libelf/elf_begin.c
libelf/elf_getarsym.c
libelf/elf_getshdrstrndx.c
libelf/elf_newscn.c

index 148c945347ac83f09bb6cfcf2ddb5cf12c6e8954..ee070e050042d4ce7a38442028c85f672b280df9 100644 (file)
@@ -1,3 +1,23 @@
+2014-01-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf32_getphdr.c (elfw2(LIBELFBITS,getphdr)): Check if program header
+       table fits into object's bounds.
+       * elf_getshdrstrndx.c (elf_getshstrndx): Add elf->start_offset to
+       elf->map_address.  Check if first section header fits into object's
+       bounds.
+       * elf32_getshdr.c (elfw2(LIBELFBITS,getshdr)):
+       Check if section header table fits into object's bounds.
+       * elf_begin.c (get_shnum): Ensure section headers fits into
+       object's bounds.
+       (file_read_elf): Make sure scncnt is small enough to allocate both
+       ElfXX_Shdr and Elf_Scn array.  Make sure section and program header
+       tables fit into object's bounds.  Avoid memory leak on failure.
+       * elf_newscn.c (elf_newscn): Check for overflow.
+       * elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Likewise.
+       (__elfw2(LIBELFBITS,updatefile)): Likewise.
+       * elf32_newphdr.c (elfw2(LIBELFBITS,newphdr)): Likewise.
+       * elf_getarsym.c (elf_getarsym): Likewise.
+
 2013-11-08  Mark Wielaard  <mjw@redhat.com>
 
        * elf32_updatefile.c (elfXX_updatemmap): Only memcpy ehdr when not
index a47c9f7afd5b0d66f0e8ec4836f8e8a06104857d..e74e63fd52c85067ad18451bc6763fc20df41478 100644 (file)
@@ -1,5 +1,5 @@
 /* Get ELF program header table.
-   Copyright (C) 1998-2010 Red Hat, Inc.
+   Copyright (C) 1998-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -93,6 +93,16 @@ __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
 
       if (elf->map_address != NULL)
        {
+         /* First see whether the information in the ELF header is
+            valid and it does not ask for too much.  */
+         if (unlikely (ehdr->e_phoff >= elf->maximum_size)
+             || unlikely (elf->maximum_size - ehdr->e_phoff < size))
+           {
+             /* Something is wrong.  */
+             __libelf_seterrno (ELF_E_INVALID_PHDR);
+             goto out;
+           }
+
          /* All the data is already mapped.  Use it.  */
          void *file_phdr = ((char *) elf->map_address
                             + elf->start_offset + ehdr->e_phoff);
index bd9340dd70710ab6fd69ca17a7eba9da9051383e..741704736f7ae01cf33c4d4e87ffa22da98376b9 100644 (file)
@@ -1,5 +1,5 @@
 /* Return section header.
-   Copyright (C) 1998-2002, 2005, 2007, 2009, 2012 Red Hat, Inc.
+   Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -60,7 +60,8 @@ load_shdr_wrlock (Elf_Scn *scn)
     goto out;
 
   size_t shnum;
-  if (__elf_getshdrnum_rdlock (elf, &shnum) != 0)
+  if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
+      || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
     goto out;
   size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
 
@@ -77,6 +78,16 @@ load_shdr_wrlock (Elf_Scn *scn)
 
   if (elf->map_address != NULL)
     {
+      /* First see whether the information in the ELF header is
+        valid and it does not ask for too much.  */
+      if (unlikely (ehdr->e_shoff >= elf->maximum_size)
+         || unlikely (elf->maximum_size - ehdr->e_shoff < size))
+       {
+         /* Something is wrong.  */
+         __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+         goto free_and_out;
+       }
+
       ElfW2(LIBELFBITS,Shdr) *notcvt;
 
       /* All the data is already mapped.  If we could use it
index 1db208066626590a8558db0e0bb335a42057f03b..01038e733c65da1ff89d9058fc4da8396db0952a 100644 (file)
@@ -1,5 +1,5 @@
 /* Create new ELF program header table.
-   Copyright (C) 1999-2010 Red Hat, Inc.
+   Copyright (C) 1999-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -114,6 +114,12 @@ elfw2(LIBELFBITS,newphdr) (elf, count)
           || count == PN_XNUM
           || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
     {
+      if (unlikely (count > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))))
+       {
+         result = NULL;
+         goto out;
+       }
+
       /* Allocate a new program header with the appropriate number of
         elements.  */
       result = (ElfW2(LIBELFBITS,Phdr) *)
index b39e28416778492230e79753fa10a58eb5d9fd00..153e377f67dddd473edf6c8ae25432704d3c10db 100644 (file)
@@ -1,5 +1,5 @@
 /* Write changed data structures.
-   Copyright (C) 2000-2010 Red Hat, Inc.
+   Copyright (C) 2000-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
 
@@ -202,6 +202,9 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
   /* Write all the sections.  Well, only those which are modified.  */
   if (shnum > 0)
     {
+      if (unlikely (shnum > SIZE_MAX / sizeof (Elf_Scn *)))
+       return 1;
+
       Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
       Elf_Scn **scns = (Elf_Scn **) alloca (shnum * sizeof (Elf_Scn *));
       char *const shdr_start = ((char *) elf->map_address + elf->start_offset
@@ -624,6 +627,10 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
   /* Write all the sections.  Well, only those which are modified.  */
   if (shnum > 0)
     {
+      if (unlikely (shnum > SIZE_MAX / (sizeof (Elf_Scn *)
+                                       + sizeof (ElfW2(LIBELFBITS,Shdr)))))
+       return 1;
+
       off_t shdr_offset = elf->start_offset + ehdr->e_shoff;
 #if EV_NUM != 2
       xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
index b9d5cea4eb1f6a5e45de7a01270b8123d1a078ff..a592fbf770756399189937475f963cfba915b2f0 100644 (file)
@@ -1,5 +1,5 @@
 /* Create descriptor for processing file.
-   Copyright (C) 1998-2010, 2012 Red Hat, Inc.
+   Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -144,7 +144,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
 
       if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
        {
-         if (ehdr.e32->e_shoff + sizeof (Elf32_Shdr) > maxsize)
+         if (unlikely (ehdr.e32->e_shoff >= maxsize)
+             || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
            /* Cannot read the first section header.  */
            return 0;
 
@@ -192,7 +193,8 @@ get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
 
       if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
        {
-         if (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize)
+         if (unlikely (ehdr.e64->e_shoff >= maxsize)
+             || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
            /* Cannot read the first section header.  */
            return 0;
 
@@ -264,6 +266,15 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
     /* Could not determine the number of sections.  */
     return NULL;
 
+  /* Check for too many sections.  */
+  if (e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
+       return NULL;
+    }
+  else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
+    return NULL;
+
   /* We can now allocate the memory.  Even if there are no section headers,
      we allocate space for a zeroth section in case we need it later.  */
   const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
@@ -303,6 +314,16 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
        {
          /* We can use the mmapped memory.  */
          elf->state.elf32.ehdr = ehdr;
+
+         if (unlikely (ehdr->e_shoff >= maxsize)
+             || unlikely (maxsize - ehdr->e_shoff
+                          < scncnt * sizeof (Elf32_Shdr)))
+           {
+           free_and_out:
+             free (elf);
+             __libelf_seterrno (ELF_E_INVALID_FILE);
+             return NULL;
+           }
          elf->state.elf32.shdr
            = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
 
@@ -389,6 +410,11 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
        {
          /* We can use the mmapped memory.  */
          elf->state.elf64.ehdr = ehdr;
+
+         if (unlikely (ehdr->e_shoff >= maxsize)
+             || unlikely (ehdr->e_shoff
+                          + scncnt * sizeof (Elf32_Shdr) > maxsize))
+           goto free_and_out;
          elf->state.elf64.shdr
            = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
 
index d0bb28a939827e2f10741ce686cd17d23bc56261..7325190ab243f40eaa40bdf0475c1d1a0ba4c8e9 100644 (file)
@@ -1,5 +1,5 @@
 /* Return symbol table of archive.
-   Copyright (C) 1998-2000, 2002, 2005, 2012 Red Hat, Inc.
+   Copyright (C) 1998-2000, 2002, 2005, 2009, 2012, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -183,6 +183,9 @@ elf_getarsym (elf, ptr)
       size_t index_size = atol (tmpbuf);
 
       if (SARMAG + sizeof (struct ar_hdr) + index_size > elf->maximum_size
+#if SIZE_MAX <= 4294967295U
+         || n >= SIZE_MAX / sizeof (Elf_Arsym)
+#endif
          || n * w > index_size)
        {
          /* This index table cannot be right since it does not fit into
index 57ad80057f38dce85b4886c6742ea7e736c0f263..1dbed4c84616edb1677ece141a66b9a7367f76e3 100644 (file)
@@ -1,5 +1,5 @@
 /* Return section index of section header string table.
-   Copyright (C) 2002, 2005, 2009 Red Hat, Inc.
+   Copyright (C) 2002, 2005, 2009, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -104,10 +104,25 @@ elf_getshdrstrndx (elf, dst)
              if (elf->map_address != NULL
                  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
                  && (ALLOW_UNALIGNED
-                     || (((size_t) ((char *) elf->map_address + offset))
+                     || (((size_t) ((char *) elf->map_address
+                          + elf->start_offset + offset))
                          & (__alignof__ (Elf32_Shdr) - 1)) == 0))
-               /* We can directly access the memory.  */
-               num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link;
+               {
+                 /* First see whether the information in the ELF header is
+                    valid and it does not ask for too much.  */
+                 if (unlikely (elf->maximum_size - offset
+                               < sizeof (Elf32_Shdr)))
+                   {
+                     /* Something is wrong.  */
+                     __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+                     result = -1;
+                     goto out;
+                   }
+
+                 /* We can directly access the memory.  */
+                 num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
+                                        + offset))->sh_link;
+               }
              else
                {
                  /* We avoid reading in all the section headers.  Just read
@@ -142,10 +157,25 @@ elf_getshdrstrndx (elf, dst)
              if (elf->map_address != NULL
                  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
                  && (ALLOW_UNALIGNED
-                     || (((size_t) ((char *) elf->map_address + offset))
+                     || (((size_t) ((char *) elf->map_address
+                          + elf->start_offset + offset))
                          & (__alignof__ (Elf64_Shdr) - 1)) == 0))
-               /* We can directly access the memory.  */
-               num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link;
+               {
+                 /* First see whether the information in the ELF header is
+                    valid and it does not ask for too much.  */
+                 if (unlikely (elf->maximum_size - offset
+                               < sizeof (Elf64_Shdr)))
+                   {
+                     /* Something is wrong.  */
+                     __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+                     result = -1;
+                     goto out;
+                   }
+
+                 /* We can directly access the memory.  */
+                 num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
+                                        + offset))->sh_link;
+               }
              else
                {
                  /* We avoid reading in all the section headers.  Just read
index 70d29b664702d2caa7806c11aa20f600233035f1..6e0029ed02342eb6f3b19151fefa79a8ea771852 100644 (file)
@@ -1,5 +1,5 @@
 /* Append new section.
-   Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2009, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
 
@@ -83,10 +83,18 @@ elf_newscn (elf)
   else
     {
       /* We must allocate a new element.  */
-      Elf_ScnList *newp;
+      Elf_ScnList *newp = NULL;
 
       assert (elf->state.elf.scnincr > 0);
 
+      if (
+#if SIZE_MAX <= 4294967295U
+         likely (elf->state.elf.scnincr
+                 < SIZE_MAX / 2 / sizeof (Elf_Scn) - sizeof (Elf_ScnList))
+#else
+         1
+#endif
+         )
       newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList)
                                     + ((elf->state.elf.scnincr *= 2)
                                        * sizeof (Elf_Scn)), 1);