aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--posix/Makefile4
-rw-r--r--posix/tst-mmap.c196
-rw-r--r--sysdeps/unix/sysv/linux/i386/mmap64.S8
4 files changed, 208 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 4e39b0112a..fee7a5ea2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2000-01-02 Ulrich Drepper <drepper@cygnus.com>
+ * posix/Makefile (tests): Add tst-mmap.
+ * posix/tst-mmap.c: New file.
+
+ * sysdeps/unix/sysv/linux/i386/mmap64.S: Pop registers after mmap2
+ call before handling error.
+
* sysdeps/unix/sysv/linux/i386/mmap64.S: Handle unaligned offsets.
* sysdeps/unix/sysv/linux/i386/mmap.S: Likewise.
diff --git a/posix/Makefile b/posix/Makefile
index 7861bdf5f3..96c73933e5 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+# Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -57,7 +57,7 @@ include ../Makeconfig
aux := init-posix environ
tests := tstgetopt testfnm runtests runptests \
- tst-preadwrite test-vfork regexbug1 tst-getlogin
+ tst-preadwrite test-vfork regexbug1 tst-getlogin tst-mmap
ifeq (yes,$(build-shared))
test-srcs := globtest
tests += wordexp-test
diff --git a/posix/tst-mmap.c b/posix/tst-mmap.c
new file mode 100644
index 0000000000..0332828723
--- /dev/null
+++ b/posix/tst-mmap.c
@@ -0,0 +1,196 @@
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+
+int
+main (void)
+{
+ int result = 0;
+ FILE *fp;
+ int c;
+ char buf[1000];
+ int fd;
+ char *ptr;
+ size_t ps = sysconf (_SC_PAGESIZE);
+ void *mem;
+
+ /* Create a file and put some data in it. */
+ fp = tmpfile ();
+ if (fp == NULL)
+ {
+ printf ("Cannot create temporary file: %m\n");
+ return 1;
+ }
+ fd = fileno (fp);
+
+ for (c = 0; c < sizeof (buf); ++c)
+ buf[c] = '0' + (c % 10);
+
+ for (c = 0; c < 20; ++c)
+ if (fwrite (buf, 1, sizeof (buf), fp) != sizeof (buf))
+ {
+ printf ("`fwrite' failed: %m\n");
+ return 1;
+ }
+ assert (ps + 1000 < c * sizeof (buf));
+
+ /* First try something which is not allowed: map at an offset which is
+ not module the pagesize. */
+ ptr = mmap (NULL, 1000, PROT_READ, MAP_SHARED, fd, ps - 1);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at offset with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* Try the same for mmap64. */
+ ptr = mmap64 (NULL, 1000, PROT_READ, MAP_SHARED, fd, ps - 1);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at offset with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* And the same for private mapping. */
+ ptr = mmap (NULL, 1000, PROT_READ, MAP_PRIVATE, fd, ps - 1);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at offset with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* Try the same for mmap64. */
+ ptr = mmap64 (NULL, 1000, PROT_READ, MAP_PRIVATE, fd, ps - 1);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at offset with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at offset with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* Get a valid address. */
+ mem = malloc (2 * ps);
+ if (mem != NULL)
+ {
+ /* Now we map at an address which is not mod pagesize. */
+ ptr = mmap (mem + 1, 1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd, ps);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at address with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* Try the same for mmap64. */
+ ptr = mmap64 (mem + 1, 1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd, ps);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at address with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* And again for MAP_PRIVATE. */
+ ptr = mmap (mem + 1, 1000, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ps);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at address with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ /* Try the same for mmap64. */
+ ptr = mmap64 (mem + 1, 1000, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ps);
+ if (ptr != MAP_FAILED)
+ {
+ puts ("mapping at address with mod pagesize != 0 succeeded!");
+ result = 1;
+ }
+ else if (errno != EINVAL && errno != ENOSYS)
+ {
+ puts ("wrong error value for mapping at address with mod pagesize != 0: %m (should be EINVAL)");
+ result = 1;
+ }
+
+ free (mem);
+ }
+
+ /* Now map the memory and see whether the content of the mapped area
+ is correct. */
+ ptr = mmap (NULL, 1000, PROT_READ, MAP_SHARED, fd, ps);
+ if (ptr == MAP_FAILED)
+ {
+ if (errno != ENOSYS)
+ {
+ printf ("cannot mmap file: %m\n");
+ result = 1;
+ }
+ }
+ else
+ {
+ for (c = ps; c < ps + 1000; ++c)
+ if (ptr[c - ps] != '0' + (c % 10))
+ {
+ printf ("wrong data mapped at offset %d\n", c);
+ result = 1;
+ }
+ }
+
+ /* And for mmap64. */
+ ptr = mmap64 (NULL, 1000, PROT_READ, MAP_SHARED, fd, ps);
+ if (ptr == MAP_FAILED)
+ {
+ if (errno != ENOSYS)
+ {
+ printf ("cannot mmap file: %m\n");
+ result = 1;
+ }
+ }
+ else
+ {
+ for (c = ps; c < ps + 1000; ++c)
+ if (ptr[c - ps] != '0' + (c % 10))
+ {
+ printf ("wrong data mapped at offset %d\n", c);
+ result = 1;
+ }
+ }
+
+ /* That's it. */
+ return result;
+}
diff --git a/sysdeps/unix/sysv/linux/i386/mmap64.S b/sysdeps/unix/sysv/linux/i386/mmap64.S
index 346bb52b5f..0785bce783 100644
--- a/sysdeps/unix/sysv/linux/i386/mmap64.S
+++ b/sysdeps/unix/sysv/linux/i386/mmap64.S
@@ -56,16 +56,16 @@ ENTRY (__mmap64)
L(do_syscall):
int $0x80
- /* If 0 > %eax > -4096 there was an error. */
- cmpl $-4096, %eax
- ja SYSCALL_ERROR_LABEL
-
/* Restore registers. */
popl %edi
popl %esi
popl %ebx
popl %ebp
+ /* If 0 > %eax > -4096 there was an error. */
+ cmpl $-4096, %eax
+ ja SYSCALL_ERROR_LABEL
+
/* Successful; return the syscall's value. */
L(pseudo_end):
ret