selftest/vm: verify remap destination address in mremap_test

[ Upstream commit 18d609daa5 ]

Because mremap does not have a MAP_FIXED_NOREPLACE flag, it can destroy
existing mappings.  This causes a segfault when regions such as text are
remapped and the permissions are changed.

Verify the requested mremap destination address does not overlap any
existing mappings by using mmap's MAP_FIXED_NOREPLACE flag.  Keep
incrementing the destination address until a valid mapping is found or
fail the current test once the max address is reached.

Link: https://lkml.kernel.org/r/20220420215721.4868-2-sidhartha.kumar@oracle.com
Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com>
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Sidhartha Kumar 2022-04-21 16:35:52 -07:00 committed by Greg Kroah-Hartman
parent e8b9989597
commit 0b4e16093e

View file

@ -66,6 +66,30 @@ enum {
.expect_failure = should_fail \
}
/*
* Returns false if the requested remap region overlaps with an
* existing mapping (e.g text, stack) else returns true.
*/
static bool is_remap_region_valid(void *addr, unsigned long long size)
{
void *remap_addr = NULL;
bool ret = true;
/* Use MAP_FIXED_NOREPLACE flag to ensure region is not mapped */
remap_addr = mmap(addr, size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_ANONYMOUS | MAP_SHARED,
-1, 0);
if (remap_addr == MAP_FAILED) {
if (errno == EEXIST)
ret = false;
} else {
munmap(remap_addr, size);
}
return ret;
}
/* Returns mmap_min_addr sysctl tunable from procfs */
static unsigned long long get_mmap_min_addr(void)
{