The sloppyRXcheck logic in the sync checker was not correct - it was
simply treating R and X as equivalent but the real problem is that
mappings can appear to have X permission entirely indepenent of anything
else with recent x86 kernels.
If a mapping is inside the (deliberately constrained) code segment then
it will appear to have X permission regardless of whether R or X was asked
for when it was mapped, so what we really need to do is allow the kernel
to add X to any mapping but not to take it away if we were expecting it.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4985 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c
index 55c2a50..600102d 100644
--- a/coregrind/m_aspacemgr/aspacemgr.c
+++ b/coregrind/m_aspacemgr/aspacemgr.c
@@ -1072,7 +1072,7 @@
const UChar* filename )
{
Int iLo, iHi, i;
- Bool sloppyRXcheck;
+ Bool sloppyXcheck;
/* If a problem has already been detected, don't continue comparing
segments, so as to avoid flooding the output with error
@@ -1097,21 +1097,21 @@
aspacem_assert(nsegments[iHi].end >= addr + len - 1 );
/* x86 doesn't differentiate 'x' and 'r' (at least, all except the
- most recent NX-bit enabled CPUs) and so recent kernels mark most
- readable sections also as executable (in the /proc/self/maps
- they give out), which makes checking fail. When sloppyRXcheck
- is True, the checker therefore regards R and X as
- interchangeable. */
- sloppyRXcheck = False;
-# if defined(VGA_x86)
- sloppyRXcheck = True;
-# endif
+ most recent NX-bit enabled CPUs) and so recent kernels attempt
+ to provide execute protection by placing all executable mappings
+ low down in the address space and then reducing the size of the
+ code segment to prevent code at higher addresses being executed.
- if (sloppyRXcheck) {
- /* If either bit is set, ensure both are set. */
- if (prot & (VKI_PROT_READ|VKI_PROT_EXEC))
- prot |= (VKI_PROT_READ|VKI_PROT_EXEC);
- }
+ These kernels report which mappings are really executable in
+ the /proc/self/maps output rather than mirroring what was asked
+ for when each mapping was created. In order to cope with this we
+ have a slopyXcheck mode which we enable on x86 - in this mode we
+ allow the kernel to report execute permission when we weren't
+ expecting it but not vice versa. */
+ sloppyXcheck = False;
+# if defined(VGA_x86)
+ sloppyXcheck = True;
+# endif
/* NSegments iLo .. iHi inclusive should agree with the presented
data. */
@@ -1144,10 +1144,13 @@
if (filename && 0==VG_(strcmp)(filename, "/dev/zero (deleted)"))
cmp_devino = False;
- if (sloppyRXcheck) {
- /* If either bit is set, ensure both are set. */
- if (seg_prot & (VKI_PROT_READ|VKI_PROT_EXEC))
- seg_prot |= (VKI_PROT_READ|VKI_PROT_EXEC);
+ /* If we are doing sloppy execute permission checks then we
+ allow segment to have X permission when we weren't expecting
+ it (but not vice versa) so if the kernel reported execute
+ permission then pretend that this segment has it regardless
+ of what we were expecting. */
+ if (sloppyXcheck && (prot & VKI_PROT_EXEC) != 0) {
+ seg_prot |= VKI_PROT_EXEC;
}
same = same