1 /* BZ #18877, BZ #21270, and BZ #24699 mmap offset test.
3 Copyright (C) 2015-2024 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
27 #include <mmap_info.h>
29 #include <support/check.h>
32 static long int page_shift
;
33 static char fname
[] = "/tmp/tst-mmap-offset-XXXXXX";
36 do_prepare (int argc
, char **argv
)
38 fd
= mkstemp64 (fname
);
40 FAIL_EXIT1 ("mkstemp failed");
43 FAIL_EXIT1 ("unlink failed");
45 long sz
= sysconf(_SC_PAGESIZE
);
48 page_shift
= ffs (sz
) - 1;
51 #define PREPARE do_prepare
54 /* Check if negative offsets are handled correctly by mmap. */
56 do_test_bz18877 (void)
58 const int prot
= PROT_READ
| PROT_WRITE
;
59 const int flags
= MAP_SHARED
;
60 const unsigned long length
= 0x10000;
61 const unsigned long offset
= 0xace00000;
62 const unsigned long size
= offset
+ length
;
65 if (ftruncate64 (fd
, size
))
66 FAIL_RET ("ftruncate64 failed");
68 addr
= mmap (NULL
, length
, prot
, flags
, fd
, offset
);
69 if (MAP_FAILED
== addr
)
70 FAIL_RET ("mmap failed");
72 /* This memcpy is likely to SIGBUS if mmap has messed up with offset. */
73 memcpy (addr
, fname
, sizeof (fname
));
78 /* Check if invalid offset are handled correctly by mmap. */
80 do_test_large_offset (void)
82 /* For architectures with sizeof (off_t) < sizeof (off64_t) mmap is
83 implemented with __SYS_mmap2 syscall and the offset is represented in
84 multiples of page size. For offset larger than
85 '1 << (page_shift + 8 * sizeof (off_t))' (that is, 1<<44 on system with
86 page size of 4096 bytes) the system call silently truncates the offset.
87 For this case glibc mmap implementation returns EINVAL. */
88 const int prot
= PROT_READ
| PROT_WRITE
;
89 const int flags
= MAP_SHARED
;
90 const int64_t offset
= 1ULL << (page_shift
+ 8 * sizeof (uint32_t));
91 const size_t length
= 4096;
93 void *addr
= mmap64 (NULL
, length
, prot
, flags
, fd
, offset
);
94 if (mmap64_maximum_offset (page_shift
) < UINT64_MAX
)
96 if ((addr
!= MAP_FAILED
) && (errno
!= EINVAL
))
97 FAIL_RET ("mmap succeed");
101 if (addr
== MAP_FAILED
)
102 FAIL_RET ("mmap failed");
113 ret
+= do_test_bz18877 ();
114 ret
+= do_test_large_offset ();
119 #include <support/test-driver.c>