summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-10-13 16:02:10 +0200
committerMark Wielaard <mjw@redhat.com>2015-10-13 16:02:10 +0200
commitb9be1434ff0a4ce9ebe80fcda5c6a9891904b26e (patch)
treeb6cd28f2eacf71d4536c7cd868e099ff37b21756
parentae1e85ea0b0d63968c707000ac893d9256eb9c38 (diff)
downloadelfutils-b9be1434ff0a4ce9ebe80fcda5c6a9891904b26e.tar.gz
elflint: Check relro flags are a subset of the load segment.
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>
-rw-r--r--src/ChangeLog5
-rw-r--r--src/elflint.c22
2 files changed, 24 insertions, 3 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 796878f8..8ba25397 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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.
diff --git a/src/elflint.c b/src/elflint.c
index fac457ea..63192bbd 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -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;
}
}