* Copyright (c) International Business Machines Corp., 2001
* 07/2001 Ported by Wayne Boyer
* Copyright (c) 2025 SUSE LLC Ricardo B. Marlière <rbm@suse.com>
*/
* Verify that, munmap call will succeed to unmap a mapped file or
* anonymous shared memory region from the calling process's address space
* and after successful completion of munmap, the unmapped region is no
* longer accessible (even if partially unmapped).
*
* munmap call should succeed to unmap a part or all of the mapped region of
* a file or anonymous shared memory region from the process's address space
* and it returns with a value 0, further reference to the unmapped region
* should result in a segmentation fault (SIGSEGV).
*/
#include "tst_test.h"
static size_t page_sz;
static int fd = -1;
static char *map_base;
static char *map_addr;
static unsigned int map_len;
static unsigned int map_len_full;
static const char *const variants[] = {
"unmapped region not accessible",
"partially unmapped region not accessible",
};
static void run(void)
{
int status;
SAFE_MUNMAP(map_addr, map_len);
map_base = NULL;
* Check whether further reference is possible to the unmapped memory
* region by writing to the first byte of region with some arbitrary
* number.
*/
if (!SAFE_FORK()) {
*map_addr = 50;
_exit(0);
}
SAFE_WAIT(&status);
if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {
tst_res(TPASS, "Child was unable to access unmapped memory");
return;
}
tst_res(TFAIL, "Child succeeds to refer unmapped memory region");
}
static void setup(void)
{
page_sz = SAFE_SYSCONF(_SC_PAGESIZE);
tst_res(TINFO, "Testing variant: %s", variants[tst_variant]);
map_len_full = 3 * page_sz;
map_len = map_len_full;
fd = SAFE_OPEN("mmapfile", O_RDWR | O_CREAT, 0666);
SAFE_LSEEK(fd, map_len, SEEK_SET);
SAFE_WRITE(SAFE_WRITE_ALL, fd, "a", 1);
map_base = SAFE_MMAP(0, map_len, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, fd, 0);
map_addr = map_base;
if (tst_variant) {
map_addr = map_addr + page_sz;
map_len = map_len - page_sz;
}
}
static void cleanup(void)
{
if (map_base) {
SAFE_MUNMAP(map_base, map_len_full);
} else {
if (tst_variant)
SAFE_MUNMAP(map_addr, page_sz);
}
if (fd != -1)
SAFE_CLOSE(fd);
}
static struct tst_test test = {
.test_all = run,
.setup = setup,
.cleanup = cleanup,
.needs_tmpdir = 1,
.forks_child = 1,
.test_variants = ARRAY_SIZE(variants),
};