Fix bug in do_mremap. Also need to allow SkShmC segments.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15219 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index d57da2c..647847a 100644
--- a/NEWS
+++ b/NEWS
@@ -182,6 +182,7 @@
 n-i-bz  Fix compilation on distros with glibc < 2.5
 n-i-bz  (vex 3098) Avoid generation of Neon insns on non-Neon hosts
 n-i-bz  Enable rt_sigpending syscall on ppc64 linux.
+n-i-bz  mremap did not work properly on shared memory
 
 
 Release 3.10.1 (25 November 2014)
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index a28e50a..fcf5687 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -328,7 +328,8 @@
    old_seg = VG_(am_find_nsegment)( old_addr );
    if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
       goto eINVAL;
-   if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC)
+   if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC &&
+       old_seg->kind != SkShmC)
       goto eINVAL;
 
    vg_assert(old_len > 0);
diff --git a/none/tests/linux/Makefile.am b/none/tests/linux/Makefile.am
index 4fb0475..46e2486 100644
--- a/none/tests/linux/Makefile.am
+++ b/none/tests/linux/Makefile.am
@@ -11,6 +11,7 @@
 	    mremap.vgtest \
 	mremap2.stderr.exp mremap2.stdout.exp mremap2.vgtest \
 	mremap3.stderr.exp mremap3.stdout.exp mremap3.vgtest \
+	mremap4.stderr.exp mremap4.vgtest \
 	pthread-stack.stderr.exp pthread-stack.vgtest \
 	stack-overflow.stderr.exp stack-overflow.vgtest
 
@@ -21,6 +22,7 @@
 	mremap \
 	mremap2 \
 	mremap3 \
+	mremap4 \
 	pthread-stack \
 	stack-overflow
 
diff --git a/none/tests/linux/mremap4.c b/none/tests/linux/mremap4.c
new file mode 100644
index 0000000..1f83dab
--- /dev/null
+++ b/none/tests/linux/mremap4.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+
+
+extern void *mremap(void *, size_t, size_t, int, ...);
+
+int main()
+{
+  int shmid = shmget(IPC_PRIVATE, 100 * 4096, 
+                     IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
+  assert(shmid != -1);
+
+  void *addr = shmat(shmid, NULL, 0);
+  assert(addr != (void *)-1);
+
+  addr = mremap(addr, 100 * 4096, 40 * 4096, 0);
+  assert(addr != (void *)-1);
+
+  return 0;
+}
diff --git a/none/tests/linux/mremap4.stderr.exp b/none/tests/linux/mremap4.stderr.exp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/none/tests/linux/mremap4.stderr.exp
diff --git a/none/tests/linux/mremap4.vgtest b/none/tests/linux/mremap4.vgtest
new file mode 100644
index 0000000..b6d5b8b
--- /dev/null
+++ b/none/tests/linux/mremap4.vgtest
@@ -0,0 +1,2 @@
+prog: mremap4
+vgopts: -q