glibc/posix/tst-mmap-offset.c
Joseph Myers 95511aab9d Fix testing with read-only source directory.
Three tests fail with a read-only source directory because they try to
write into the source directory.  None of these write into it in a way
that should actually be problematic for concurrent builds sharing the
same writable source directory, but avoiding any writing into the
source directory (from testing, or from building glibc if the source
timestamps are properly ordered) is still a good idea, as being able
to build with read-only sources helps make sure there isn't anything
that could cause problems for concurrent builds.

This patch changes the tests in question to use either /tmp or the
build directory to write their temporary files (or to test O_TMPFILE,
as applicable).

Tested for x86_64.

	* io/Makefile (tst-open-tmpfile-ARGS): New variable.
	* posix/tst-mmap-offset.c (fname): Use /tmp.
	* stdlib/tst-setcontext3.sh (tempfile): Use ${objpfx}.
2017-12-15 22:37:17 +00:00

119 lines
3.1 KiB
C

/* BZ #18877 and #21270 mmap offset test.
Copyright (C) 2015-2017 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
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <support/check.h>
static int fd;
static long int page_shift;
static char fname[] = "/tmp/tst-mmap-offset-XXXXXX";
static void
do_prepare (int argc, char **argv)
{
fd = mkstemp64 (fname);
if (fd < 0)
FAIL_EXIT1 ("mkstemp failed");
if (unlink (fname))
FAIL_EXIT1 ("unlink failed");
long sz = sysconf(_SC_PAGESIZE);
if (sz == -1)
sz = 4096L;
page_shift = ffs (sz) - 1;
}
#define PREPARE do_prepare
/* Check if negative offsets are handled correctly by mmap. */
static int
do_test_bz18877 (void)
{
const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_SHARED;
const unsigned long length = 0x10000;
const unsigned long offset = 0xace00000;
const unsigned long size = offset + length;
void *addr;
if (ftruncate64 (fd, size))
FAIL_RET ("ftruncate64 failed");
addr = mmap (NULL, length, prot, flags, fd, offset);
if (MAP_FAILED == addr)
FAIL_RET ("mmap failed");
/* This memcpy is likely to SIGBUS if mmap has messed up with offset. */
memcpy (addr, fname, sizeof (fname));
return 0;
}
/* Check if invalid offset are handled correctly by mmap. */
static int
do_test_bz21270 (void)
{
/* For architectures with sizeof (off_t) < sizeof (off64_t) mmap is
implemented with __SYS_mmap2 syscall and the offset is represented in
multiples of page size. For offset larger than
'1 << (page_shift + 8 * sizeof (off_t))' (that is, 1<<44 on system with
page size of 4096 bytes) the system call silently truncates the offset.
For this case glibc mmap implementation returns EINVAL. */
const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_SHARED;
const int64_t offset = 1ULL << (page_shift + 8 * sizeof (uint32_t));
const size_t length = 4096;
void *addr = mmap64 (NULL, length, prot, flags, fd, offset);
if (sizeof (off_t) < sizeof (off64_t))
{
if ((addr != MAP_FAILED) && (errno != EINVAL))
FAIL_RET ("mmap succeed");
}
else
{
if (addr == MAP_FAILED)
FAIL_RET ("mmap failed");
}
return 0;
}
int
do_test (void)
{
int ret = 0;
ret += do_test_bz18877 ();
ret += do_test_bz21270 ();
return ret;
}
#include <support/test-driver.c>