Implement check for PT_GNU_EH_FRAME program header check.
authorUlrich Drepper <drepper@redhat.com>
Sat, 17 Jan 2009 05:11:49 +0000 (21:11 -0800)
committerUlrich Drepper <drepper@redhat.com>
Sat, 17 Jan 2009 05:11:49 +0000 (21:11 -0800)
NEWS
TODO
src/ChangeLog
src/elflint.c

diff --git a/NEWS b/NEWS
index e041437..07d80a4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ libcpu: Add Intel SSE4 disassembler support
 readelf: Implement call frame information and exception handling dumping.
          Add -e option.  Enable it implicitly for -a.
 
+elflint: Check PT_GNU_EH_FRAME program header entry.
+
 libdwfl: Support automatic gzip/bzip2 decompression of ELF files.
 
 Version 0.138:
diff --git a/TODO b/TODO
index bc37414..c884c2c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
                      ToDo list for elfutils                      -*-outline-*-
                       ----------------------
 
-Time-stamp: <2009-01-01 16:56:38 drepper>
+Time-stamp: <2009-01-16 20:55:06 drepper>
 
 * mkinstalldirs
 
@@ -118,6 +118,8 @@ Time-stamp: <2009-01-01 16:56:38 drepper>
 
    check TLS relocation depencies
 
+   Check content of .eh_frame_hdr, .eh_frame, .gcc_except_table
+
 *** for x86
 
     check that R_386_TLS_GD is followed by R_386_PLT32 for __tls_get_addr
index ab13810..4a9b631 100644 (file)
@@ -1,5 +1,9 @@
 2009-01-16  Ulrich Drepper  <drepper@redhat.com>
 
+       * elflint.c (check_program_header): Check that PT_GNU_EH_FRAME entry
+       matches .eh_frame_hdr section, if it is available.  Also check that
+       the segment is allocated, not writable, not executable.
+
        * readelf.c: Add -e option.  Dump exception and unwind related
        sections.  Add -e to -a.
        (print_encoding_base): Handle DW_EH_PE_omit.
index 23b0f49..35368a5 100644 (file)
@@ -4132,7 +4132,7 @@ more than one GNU_RELRO entry in program header\n"));
                      if ((phdr2->p_flags & PF_W) == 0)
                        ERROR (gettext ("\
 loadable segment GNU_RELRO applies to is not writable\n"));
-                     if ((phdr2->p_flags &~ PF_W) != (phdr->p_flags &~ PF_W))
+                     if ((phdr2->p_flags & ~PF_W) != (phdr->p_flags & ~PF_W))
                        ERROR (gettext ("\
 loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
                               cnt, inner);
@@ -4173,6 +4173,41 @@ loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
            ERROR (gettext ("\
 program header offset in ELF header and PHDR entry do not match"));
        }
+      else if (phdr->p_type == PT_GNU_EH_FRAME)
+       {
+         /* If there is an .eh_frame_hdr section it must be
+            referenced by this program header entry.  */
+         Elf_Scn *scn = NULL;
+         while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+           {
+             GElf_Shdr shdr_mem;
+             GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+             if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
+                 && ! strcmp (".eh_frame_hdr",
+                              elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
+               {
+                 if (phdr->p_offset != shdr->sh_offset)
+                   ERROR (gettext ("\
+call frame search table reference in program header has wrong offset\n"));
+                 if (phdr->p_memsz != shdr->sh_size)
+                   ERROR (gettext ("\
+call frame search table size mismatch in program and section header\n"));
+                 break;
+               }
+           }
+
+         /* The section must be allocated and not be writable and
+            executable.  */
+         if ((phdr->p_flags & PF_R) == 0)
+           ERROR (gettext ("\
+call frame search table must be allocated\n"));
+         if ((phdr->p_flags & PF_W) != 0)
+           ERROR (gettext ("\
+call frame search table must not be writable\n"));
+         if ((phdr->p_flags & PF_X) != 0)
+           ERROR (gettext ("\
+call frame search table must not be executable\n"));
+       }
 
       if (phdr->p_filesz > phdr->p_memsz
          && (phdr->p_memsz != 0 || phdr->p_type != PT_NOTE))