2018-10-26 15:10:48 -07:00
// SPDX-License-Identifier: GPL-2.0
/*
* Test that MAP_FIXED_NOREPLACE works .
*
* Copyright 2018 , Jann Horn < jannh @ google . com >
* Copyright 2018 , Michael Ellerman , IBM Corporation .
*/
# include <sys/mman.h>
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# ifndef MAP_FIXED_NOREPLACE
# define MAP_FIXED_NOREPLACE 0x100000
# endif
static void dump_maps ( void )
{
char cmd [ 32 ] ;
snprintf ( cmd , sizeof ( cmd ) , " cat /proc/%d/maps " , getpid ( ) ) ;
system ( cmd ) ;
}
2022-02-25 19:11:08 -08:00
static unsigned long find_base_addr ( unsigned long size )
{
void * addr ;
unsigned long flags ;
flags = MAP_PRIVATE | MAP_ANONYMOUS ;
addr = mmap ( NULL , size , PROT_NONE , flags , - 1 , 0 ) ;
if ( addr = = MAP_FAILED ) {
printf ( " Error: couldn't map the space we need for the test \n " ) ;
return 0 ;
}
if ( munmap ( addr , size ) ! = 0 ) {
printf ( " Error: couldn't map the space we need for the test \n " ) ;
return 0 ;
}
return ( unsigned long ) addr ;
}
2018-10-26 15:10:48 -07:00
int main ( void )
{
2022-02-25 19:11:08 -08:00
unsigned long base_addr ;
2018-10-26 15:10:48 -07:00
unsigned long flags , addr , size , page_size ;
char * p ;
page_size = sysconf ( _SC_PAGE_SIZE ) ;
2022-02-25 19:11:08 -08:00
//let's find a base addr that is free before we start the tests
size = 5 * page_size ;
base_addr = find_base_addr ( size ) ;
if ( ! base_addr ) {
printf ( " Error: couldn't map the space we need for the test \n " ) ;
return 1 ;
}
2018-10-26 15:10:48 -07:00
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE ;
// Check we can map all the areas we need below
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr ;
2018-10-26 15:10:48 -07:00
size = 5 * page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p = = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error: couldn't map the space we need for the test \n " ) ;
return 1 ;
}
errno = 0 ;
if ( munmap ( ( void * ) addr , 5 * page_size ) ! = 0 ) {
dump_maps ( ) ;
printf ( " Error: munmap failed!? \n " ) ;
return 1 ;
}
printf ( " unmap() successful \n " ) ;
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr + page_size ;
2018-10-26 15:10:48 -07:00
size = 3 * page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p = = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error: first mmap() failed unexpectedly \n " ) ;
return 1 ;
}
/*
* Exact same mapping again :
* base | free | new
* + 1 | mapped | new
* + 2 | mapped | new
* + 3 | mapped | new
* + 4 | free | new
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr ;
2018-10-26 15:10:48 -07:00
size = 5 * page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p ! = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:1: mmap() succeeded when it shouldn't have \n " ) ;
return 1 ;
}
/*
* Second mapping contained within first :
*
* base | free |
* + 1 | mapped |
* + 2 | mapped | new
* + 3 | mapped |
* + 4 | free |
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr + ( 2 * page_size ) ;
2018-10-26 15:10:48 -07:00
size = page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p ! = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:2: mmap() succeeded when it shouldn't have \n " ) ;
return 1 ;
}
/*
* Overlap end of existing mapping :
* base | free |
* + 1 | mapped |
* + 2 | mapped |
* + 3 | mapped | new
* + 4 | free | new
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr + ( 3 * page_size ) ;
2018-10-26 15:10:48 -07:00
size = 2 * page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p ! = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:3: mmap() succeeded when it shouldn't have \n " ) ;
return 1 ;
}
/*
* Overlap start of existing mapping :
* base | free | new
* + 1 | mapped | new
* + 2 | mapped |
* + 3 | mapped |
* + 4 | free |
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr ;
2018-10-26 15:10:48 -07:00
size = 2 * page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p ! = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:4: mmap() succeeded when it shouldn't have \n " ) ;
return 1 ;
}
/*
* Adjacent to start of existing mapping :
* base | free | new
* + 1 | mapped |
* + 2 | mapped |
* + 3 | mapped |
* + 4 | free |
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr ;
2018-10-26 15:10:48 -07:00
size = page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p = = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:5: mmap() failed when it shouldn't have \n " ) ;
return 1 ;
}
/*
* Adjacent to end of existing mapping :
* base | free |
* + 1 | mapped |
* + 2 | mapped |
* + 3 | mapped |
* + 4 | free | new
*/
errno = 0 ;
2022-02-25 19:11:08 -08:00
addr = base_addr + ( 4 * page_size ) ;
2018-10-26 15:10:48 -07:00
size = page_size ;
p = mmap ( ( void * ) addr , size , PROT_NONE , flags , - 1 , 0 ) ;
printf ( " mmap() @ 0x%lx-0x%lx p=%p result=%m \n " , addr , addr + size , p ) ;
if ( p = = MAP_FAILED ) {
dump_maps ( ) ;
printf ( " Error:6: mmap() failed when it shouldn't have \n " ) ;
return 1 ;
}
2022-02-25 19:11:08 -08:00
addr = base_addr ;
2018-10-26 15:10:48 -07:00
size = 5 * page_size ;
if ( munmap ( ( void * ) addr , size ) ! = 0 ) {
dump_maps ( ) ;
printf ( " Error: munmap failed!? \n " ) ;
return 1 ;
}
printf ( " unmap() successful \n " ) ;
printf ( " OK \n " ) ;
return 0 ;
}