Index: include/vki-amd64-linux.h
===================================================================
--- include/vki-amd64-linux.h	(revision 5032)
+++ include/vki-amd64-linux.h	(working copy)
@@ -216,6 +216,8 @@
 #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 */
Index: include/vki-ppc32-linux.h
===================================================================
--- include/vki-ppc32-linux.h	(revision 5032)
+++ include/vki-ppc32-linux.h	(working copy)
@@ -237,6 +237,8 @@
 #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 */
Index: include/vki-x86-linux.h
===================================================================
--- include/vki-x86-linux.h	(revision 5032)
+++ include/vki-x86-linux.h	(working copy)
@@ -246,6 +246,8 @@
 #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 */
Index: coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- coregrind/m_syswrap/syswrap-generic.c	(revision 5032)
+++ coregrind/m_syswrap/syswrap-generic.c	(working copy)
@@ -4552,8 +4552,43 @@
    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)
