aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/mmap64.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-04-06 17:01:56 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-04-12 11:04:28 -0300
commit158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d (patch)
tree4314d7eeee6694b56c5c12153686f6a58d5ab890 /sysdeps/unix/sysv/linux/mmap64.c
parent4fee33f8c11447d345b2b1118a98958b54d5fda3 (diff)
downloadglibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.tar
glibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.tar.gz
glibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.tar.bz2
glibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.zip
Consolidate Linux mmap implementation (BZ#21270)
This patch consolidates all Linux mmap implementations on default sysdeps/unix/sysv/linux/mmap{64}.c one. To accomodate all required architecture specific requeriments a new internal header is created (mmap_internal.h) where each architecture add its specific code requirements. Currently only x86_64 (to define MMAP_PREPARE to add MAP_32BITS), s390 (which have a different kernel ABI for mmap), m68k (which have variable minimum page sizes), and MIPS n32 (which zero extend the offset to handle negative one correctly) redefine the new header. The patch also fixes BZ#21270 where default mmap64 on architectures which uses mmap2 silent truncates large offsets value (larger than 1 << (page shift + 8 * sizeof (off_t)) or 1<<44 on architectures with 4096 bytes page size). The new consolidate implementation returns EINVAL as allowed by POSIX. It also adds a tests for on current tst-mmap-offset one. I have run a full make check on x86_64, x86_64-32, i686, aarch64, armhf, powerpc, powerpc64le, sparc64, and sparcv9 without any regressions. I also ran some basic tests (tst-mmap-offset) on sh4, m68k, and on qemu simulated MIPS32 and MIPS64. [BZ #21270] * posix/tst-mmap-offset.c (do_prepare): New function. (do_test): Rename to do_test_bz18877 and use FAIL_RET. (do_test_bz21270): New function. * sysdeps/unix/sysv/linux/aarch64/mmap.c: Remove file. * sysdeps/unix/sysv/linux/arm/mmap.c: Remove file. * sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c: Likewise. * sysdeps/unix/sysv/linux/hppa/mmap.c: Likewise. * sysdeps/unix/sysv/linux/i386/mmap.c: Likewise. * sysdeps/unix/sysv/linux/m68k/mmap.S: Likewise. * sysdeps/unix/sysv/linux/m68k/mmap64.c: Likewise. * sysdeps/unix/sysv/linux/microblaze/mmap.S: Likewise. * sysdeps/unix/sysv/linux/mips/mips32/mmap.c: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/mmap.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S: Likewise. * sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Likewise. * sysdeps/unix/sysv/linux/wordsize-64/mmap.c: Likewise. * sysdeps/unix/sysv/linux/wordsize-64/mmap64.c: Likewise. * sysdeps/unix/sysv/linux/x86_64/64/mmap.c: Likewise. * sysdeps/unix/sysv/linux/mmap_internal.h: New file. * sysdeps/unix/sysv/linux/m68k/mmap_internal.h: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h: Likewise. * sysdeps/unix/sysv/linux/s390/mmap_internal.h: Likewise. * sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list: Remove mmap from auto-generation list. * sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list: Likewise. * sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: Likewise. * sysdeps/unix/sysv/linux/mmap.c: New file. * sysdeps/unix/sysv/linux/mmap64.c (__mmap64): Add check for invalid offsets and support for mmap2 syscall.
Diffstat (limited to 'sysdeps/unix/sysv/linux/mmap64.c')
-rw-r--r--sysdeps/unix/sysv/linux/mmap64.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c
index e823600a0d..d3ea279afe 100644
--- a/sysdeps/unix/sysv/linux/mmap64.c
+++ b/sysdeps/unix/sysv/linux/mmap64.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+/* mmap - map files or devices into memory. Linux version.
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 1999.
@@ -19,39 +20,41 @@
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
-#include <string.h>
-
#include <sysdep.h>
-#include <sys/syscall.h>
+#include <mmap_internal.h>
-/* This is always 12, even on architectures where PAGE_SHIFT != 12. */
-#ifndef MMAP2_PAGE_SHIFT
-# define MMAP2_PAGE_SHIFT 12
-#endif
-#if MMAP2_PAGE_SHIFT == -1
-static int page_shift;
-#else
-#define page_shift MMAP2_PAGE_SHIFT
-#endif
+/* To avoid silent truncation of offset when using mmap2, do not accept
+ offset larger than 1 << (page_shift + off_t bits). For archictures with
+ 32 bits off_t and page size of 4096 it would be 1^44. */
+#define MMAP_OFF_HIGH_MASK \
+ ((-(MMAP2_PAGE_UNIT << 1) << (8 * sizeof (off_t) - 1)))
+#define MMAP_OFF_MASK (MMAP_OFF_HIGH_MASK | MMAP_OFF_LOW_MASK)
+
+/* An architecture may override this. */
+#ifndef MMAP_PREPARE
+# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
+#endif
void *
__mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
{
-#if MMAP2_PAGE_SHIFT == -1
- if (page_shift == 0)
- {
- int page_size = __getpagesize ();
- page_shift = __ffs (page_size) - 1;
- }
-#endif
- if (offset & ((1 << page_shift) - 1))
+ MMAP_CHECK_PAGE_UNIT ();
+
+ if (offset & MMAP_OFF_MASK)
return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
- void *result;
- result = (void *)
- INLINE_SYSCALL (mmap2, 6, addr,
- len, prot, flags, fd,
- (off_t) (offset >> page_shift));
- return result;
+
+ MMAP_PREPARE (addr, len, prot, flags, fd, offset);
+#ifdef __NR_mmap2
+ return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
+ (off_t) (offset / MMAP2_PAGE_UNIT));
+#else
+ return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset);
+#endif
}
weak_alias (__mmap64, mmap64)
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+weak_alias (__mmap64, mmap)
+weak_alias (__mmap64, __mmap)
+#endif