From db732ea18852b33ec319cb9fdaea4a8dd229cc1c Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 8 Nov 2005 16:51:55 +0000 Subject: [PATCH] Handle the PROT_GROWSDOWN and PROT_GROWSUP mprotect flags properly which stops glibc falling over when a program requires an executable stack and glibc has been built to assume that PROT_GROWSDOWN will work. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5041 --- coregrind/m_syswrap/syswrap-generic.c | 37 ++++++++++++++++++++++++++- include/vki-amd64-linux.h | 2 ++ include/vki-ppc32-linux.h | 2 ++ include/vki-x86-linux.h | 2 ++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 4c2bd7b14b..0b5e10bb60 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -4552,8 +4552,43 @@ PRE(sys_mprotect) PRE_REG_READ3(long, "mprotect", unsigned long, addr, vki_size_t, len, unsigned long, prot); - if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) + if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) { SET_STATUS_Failure( VKI_ENOMEM ); + } else if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) { + UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP); + NSegment *aseg = VG_(am_find_nsegment)(ARG1); + NSegment *rseg; + + vg_assert(aseg); + + if (grows == VKI_PROT_GROWSDOWN) { + rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ ); + if (rseg && + rseg->kind == SkResvn && + rseg->smode == SmUpper && + rseg->end+1 == aseg->start) { + Addr end = ARG1 + ARG2; + ARG1 = aseg->start; + ARG2 = end - aseg->start; + ARG3 &= ~VKI_PROT_GROWSDOWN; + } else { + SET_STATUS_Failure( VKI_EINVAL ); + } + } else if (grows == VKI_PROT_GROWSUP) { + rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ ); + if (rseg && + rseg->kind == SkResvn && + rseg->smode == SmLower && + aseg->end+1 == rseg->start) { + ARG2 = aseg->end - ARG1 + 1; + ARG3 &= ~VKI_PROT_GROWSUP; + } else { + SET_STATUS_Failure( VKI_EINVAL ); + } + } else { + SET_STATUS_Failure( VKI_EINVAL ); + } + } } POST(sys_mprotect) diff --git a/include/vki-amd64-linux.h b/include/vki-amd64-linux.h index e4277ad384..79f96a432d 100644 --- a/include/vki-amd64-linux.h +++ b/include/vki-amd64-linux.h @@ -216,6 +216,8 @@ struct vki_sigcontext { #define VKI_PROT_WRITE 0x2 /* page can be written */ #define VKI_PROT_EXEC 0x4 /* page can be executed */ #define VKI_PROT_NONE 0x0 /* page can not be accessed */ +#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ #define VKI_MAP_SHARED 0x01 /* Share changes */ #define VKI_MAP_PRIVATE 0x02 /* Changes are private */ diff --git a/include/vki-ppc32-linux.h b/include/vki-ppc32-linux.h index 7f8b752d00..d5ade89dc7 100644 --- a/include/vki-ppc32-linux.h +++ b/include/vki-ppc32-linux.h @@ -237,6 +237,8 @@ struct vki_sigcontext { #define VKI_PROT_READ 0x1 /* page can be read */ #define VKI_PROT_WRITE 0x2 /* page can be written */ #define VKI_PROT_EXEC 0x4 /* page can be executed */ +#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ #define VKI_MAP_SHARED 0x01 /* Share changes */ #define VKI_MAP_PRIVATE 0x02 /* Changes are private */ diff --git a/include/vki-x86-linux.h b/include/vki-x86-linux.h index ae73305aea..5d8d3296cc 100644 --- a/include/vki-x86-linux.h +++ b/include/vki-x86-linux.h @@ -246,6 +246,8 @@ struct vki_sigcontext { #define VKI_PROT_READ 0x1 /* page can be read */ #define VKI_PROT_WRITE 0x2 /* page can be written */ #define VKI_PROT_EXEC 0x4 /* page can be executed */ +#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ #define VKI_MAP_SHARED 0x01 /* Share changes */ #define VKI_MAP_PRIVATE 0x02 /* Changes are private */ -- 2.47.3