]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
elflint: Check relro flags are a subset of the load segment.
authorMark Wielaard <mjw@redhat.com>
Tue, 13 Oct 2015 14:02:10 +0000 (16:02 +0200)
committerMark Wielaard <mjw@redhat.com>
Tue, 13 Oct 2015 14:02:10 +0000 (16:02 +0200)
If the RELRO segment doesn't fully overlap with the load segment then the
load segment might have more flags sets. This happens for example on sparc
when the .plt, which is executable, is also part of the load segment that
RELRO covers.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
src/ChangeLog
src/elflint.c

index 796878f8e1e58088e838d099ed2772af6543fe25..8ba253977beec063456363cb483b7a46a35fcd54 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-13  Mark Wielaard  <mjw@redhat.com>
+
+       * elflint.c (check_program_header): Check relro flags are a subset
+       of the load segment if they don't fully overlap.
+
 2015-10-07  Mark Wielaard  <mjw@redhat.com>
 
        * Makefile.am (ldlex_no_Wstack_usage): New.
index fac457ea6c4c573ae5bc10ec9ddb2aa2d3d67f50..63192bbd0c91eb2eed3da0837b17ef0ce99f4f67 100644 (file)
@@ -4459,10 +4459,26 @@ 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))
-                       ERROR (gettext ("\
+                     /* Unless fully covered, relro flags could be a
+                        subset of the phdrs2 flags.  For example the load
+                        segment could also have PF_X set.  */
+                     if (phdr->p_vaddr == phdr2->p_vaddr
+                         && (phdr->p_vaddr + phdr->p_memsz
+                             == phdr2->p_vaddr + phdr2->p_memsz))
+                       {
+                         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);
+                                  cnt, inner);
+                       }
+                     else
+                       {
+                         if ((phdr->p_flags & ~phdr2->p_flags) != 0)
+                           ERROR (gettext ("\
+GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"),
+                                  inner, cnt);
+                       }
                      break;
                    }
                }