cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-mmap.c (14026B)


      1/*
      2 * Small test program to verify simulated mmap behaviour.
      3 *
      4 * When running qemu-linux-user with the -p flag, you may need to tell
      5 * this test program about the pagesize because getpagesize() will not reflect
      6 * the -p choice. Simply pass one argument being the pagesize.
      7 *
      8 * Copyright (c) 2007 AXIS Communications AB
      9 * Written by Edgar E. Iglesias.
     10 *
     11 * This program is free software; you can redistribute it and/or modify
     12 * it under the terms of the GNU General Public License as published by
     13 * the Free Software Foundation; either version 2 of the License, or
     14 * (at your option) any later version.
     15 *
     16 * This program is distributed in the hope that it will be useful,
     17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 * GNU General Public License for more details.
     20 * 
     21 * You should have received a copy of the GNU General Public License
     22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
     23 */
     24
     25#include <stdio.h>
     26#include <stdlib.h>
     27#include <stdint.h>
     28#include <string.h>
     29#include <unistd.h>
     30#include <errno.h>
     31#include <sys/mman.h>
     32
     33#define D(x)
     34
     35#define fail_unless(x)                                         \
     36do                                                             \
     37{                                                              \
     38  if (!(x)) {                                                  \
     39    fprintf(stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
     40    exit (EXIT_FAILURE);                                       \
     41  }                                                            \
     42} while (0)
     43
     44unsigned char *dummybuf;
     45static unsigned int pagesize;
     46static unsigned int pagemask;
     47int test_fd;
     48size_t test_fsize;
     49
     50void check_aligned_anonymous_unfixed_mmaps(void)
     51{
     52    void *p1;
     53    void *p2;
     54    void *p3;
     55    void *p4;
     56    void *p5;
     57    uintptr_t p;
     58    int i;
     59    fprintf(stdout, "%s", __func__);
     60    for (i = 0; i < 8; i++) {
     61        size_t len;
     62        len = pagesize + (pagesize * i);
     63        p1 = mmap(NULL, len, PROT_READ,
     64                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     65        p2 = mmap(NULL, len, PROT_READ,
     66                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     67        p3 = mmap(NULL, len, PROT_READ,
     68                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     69        p4 = mmap(NULL, len, PROT_READ,
     70                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     71        p5 = mmap(NULL, len, PROT_READ,
     72                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     73
     74        /*
     75         * Make sure we get pages aligned with the pagesize. The
     76         * target expects this.
     77         */
     78        fail_unless(p1 != MAP_FAILED);
     79        fail_unless(p2 != MAP_FAILED);
     80        fail_unless(p3 != MAP_FAILED);
     81        fail_unless(p4 != MAP_FAILED);
     82        fail_unless(p5 != MAP_FAILED);
     83        p = (uintptr_t) p1;
     84        D(printf("p=%x\n", p));
     85        fail_unless((p & pagemask) == 0);
     86        p = (uintptr_t) p2;
     87        fail_unless((p & pagemask) == 0);
     88        p = (uintptr_t) p3;
     89        fail_unless((p & pagemask) == 0);
     90        p = (uintptr_t) p4;
     91        fail_unless((p & pagemask) == 0);
     92        p = (uintptr_t) p5;
     93        fail_unless((p & pagemask) == 0);
     94
     95        /* Make sure we can read from the entire area.  */
     96        memcpy(dummybuf, p1, pagesize);
     97        memcpy(dummybuf, p2, pagesize);
     98        memcpy(dummybuf, p3, pagesize);
     99        memcpy(dummybuf, p4, pagesize);
    100        memcpy(dummybuf, p5, pagesize);
    101        munmap(p1, len);
    102        munmap(p2, len);
    103        munmap(p3, len);
    104        munmap(p4, len);
    105        munmap(p5, len);
    106    }
    107    fprintf(stdout, " passed\n");
    108}
    109
    110void check_large_anonymous_unfixed_mmap(void)
    111{
    112	void *p1;
    113	uintptr_t p;
    114	size_t len;
    115
    116	fprintf(stdout, "%s", __func__);
    117
    118	len = 0x02000000;
    119	p1 = mmap(NULL, len, PROT_READ, 
    120		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    121
    122	/* Make sure we get pages aligned with the pagesize. The
    123	   target expects this.  */
    124	fail_unless (p1 != MAP_FAILED);
    125	p = (uintptr_t) p1;
    126	fail_unless ((p & pagemask) == 0);
    127	
    128	/* Make sure we can read from the entire area.  */
    129	memcpy (dummybuf, p1, pagesize);
    130	munmap (p1, len);
    131	fprintf(stdout, " passed\n");
    132}
    133
    134void check_aligned_anonymous_unfixed_colliding_mmaps(void)
    135{
    136    char *p1;
    137    char *p2;
    138    char *p3;
    139    uintptr_t p;
    140    int i;
    141
    142    fprintf(stdout, "%s", __func__);
    143    for (i = 0; i < 2; i++) {
    144        int nlen;
    145        p1 = mmap(NULL, pagesize, PROT_READ,
    146                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    147        fail_unless(p1 != MAP_FAILED);
    148        p = (uintptr_t) p1;
    149        fail_unless((p & pagemask) == 0);
    150        memcpy(dummybuf, p1, pagesize);
    151
    152        p2 = mmap(NULL, pagesize, PROT_READ,
    153                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    154        fail_unless(p2 != MAP_FAILED);
    155        p = (uintptr_t) p2;
    156        fail_unless((p & pagemask) == 0);
    157        memcpy(dummybuf, p2, pagesize);
    158
    159
    160        munmap(p1, pagesize);
    161        nlen = pagesize * 8;
    162        p3 = mmap(NULL, nlen, PROT_READ,
    163                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    164        fail_unless(p3 != MAP_FAILED);
    165
    166        /* Check if the mmaped areas collide.  */
    167        if (p3 < p2
    168            && (p3 + nlen) > p2) {
    169            fail_unless(0);
    170        }
    171
    172        memcpy(dummybuf, p3, pagesize);
    173
    174        /*
    175         * Make sure we get pages aligned with the pagesize. The
    176         * target expects this.
    177         */
    178        p = (uintptr_t) p3;
    179        fail_unless((p & pagemask) == 0);
    180        munmap(p2, pagesize);
    181        munmap(p3, nlen);
    182    }
    183    fprintf(stdout, " passed\n");
    184}
    185
    186void check_aligned_anonymous_fixed_mmaps(void)
    187{
    188	char *addr;
    189	void *p1;
    190	uintptr_t p;
    191	int i;
    192
    193	/* Find a suitable address to start with.  */
    194	addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE, 
    195		    MAP_PRIVATE | MAP_ANONYMOUS,
    196		    -1, 0);
    197	fprintf(stdout, "%s addr=%p", __func__, addr);
    198	fail_unless (addr != MAP_FAILED);
    199
    200	for (i = 0; i < 40; i++)
    201	{
    202		/* Create submaps within our unfixed map.  */
    203		p1 = mmap(addr, pagesize, PROT_READ, 
    204			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
    205			  -1, 0);
    206		/* Make sure we get pages aligned with the pagesize. 
    207		   The target expects this.  */
    208		p = (uintptr_t) p1;
    209		fail_unless (p1 == addr);
    210		fail_unless ((p & pagemask) == 0);		
    211		memcpy (dummybuf, p1, pagesize);
    212		munmap (p1, pagesize);
    213		addr += pagesize;
    214	}
    215	fprintf(stdout, " passed\n");
    216}
    217
    218void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
    219{
    220	char *addr;
    221	void *p1;
    222	uintptr_t p;
    223	int i;
    224
    225	/* Find a suitable address to start with.  Right were the x86 hosts
    226	 stack is.  */
    227	addr = ((void *)0x80000000);
    228	fprintf(stdout, "%s addr=%p", __func__, addr);
    229	fprintf(stdout, "FIXME: QEMU fails to track pages used by the host.");
    230
    231	for (i = 0; i < 20; i++)
    232	{
    233		/* Create submaps within our unfixed map.  */
    234		p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, 
    235			  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
    236			  -1, 0);
    237		/* Make sure we get pages aligned with the pagesize. 
    238		   The target expects this.  */
    239		p = (uintptr_t) p1;
    240		fail_unless (p1 == addr);
    241		fail_unless ((p & pagemask) == 0);		
    242		memcpy (p1, dummybuf, pagesize);
    243		munmap (p1, pagesize);
    244		addr += pagesize;
    245	}
    246	fprintf(stdout, " passed\n");
    247}
    248
    249void check_file_unfixed_mmaps(void)
    250{
    251	unsigned int *p1, *p2, *p3;
    252	uintptr_t p;
    253	int i;
    254
    255	fprintf(stdout, "%s", __func__);
    256	for (i = 0; i < 0x10; i++)
    257	{
    258		size_t len;
    259
    260		len = pagesize;
    261		p1 = mmap(NULL, len, PROT_READ, 
    262			  MAP_PRIVATE, 
    263			  test_fd, 0);
    264		p2 = mmap(NULL, len, PROT_READ, 
    265			  MAP_PRIVATE, 
    266			  test_fd, pagesize);
    267		p3 = mmap(NULL, len, PROT_READ, 
    268			  MAP_PRIVATE, 
    269			  test_fd, pagesize * 2);
    270
    271		fail_unless (p1 != MAP_FAILED);
    272		fail_unless (p2 != MAP_FAILED);
    273		fail_unless (p3 != MAP_FAILED);
    274
    275		/* Make sure we get pages aligned with the pagesize. The
    276		   target expects this.  */
    277		p = (uintptr_t) p1;
    278		fail_unless ((p & pagemask) == 0);
    279		p = (uintptr_t) p2;
    280		fail_unless ((p & pagemask) == 0);
    281		p = (uintptr_t) p3;
    282		fail_unless ((p & pagemask) == 0);
    283
    284		/* Verify that the file maps was made correctly.  */
    285		D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
    286		fail_unless (*p1 == 0);
    287		fail_unless (*p2 == (pagesize / sizeof *p2));
    288		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
    289
    290		memcpy (dummybuf, p1, pagesize);
    291		memcpy (dummybuf, p2, pagesize);
    292		memcpy (dummybuf, p3, pagesize);
    293		munmap (p1, len);
    294		munmap (p2, len);
    295		munmap (p3, len);
    296	}
    297	fprintf(stdout, " passed\n");
    298}
    299
    300void check_file_unfixed_eof_mmaps(void)
    301{
    302	char *cp;
    303	unsigned int *p1;
    304	uintptr_t p;
    305	int i;
    306
    307	fprintf(stdout, "%s", __func__);
    308	for (i = 0; i < 0x10; i++)
    309	{
    310		p1 = mmap(NULL, pagesize, PROT_READ, 
    311			  MAP_PRIVATE, 
    312			  test_fd, 
    313			  (test_fsize - sizeof *p1) & ~pagemask);
    314
    315		fail_unless (p1 != MAP_FAILED);
    316
    317		/* Make sure we get pages aligned with the pagesize. The
    318		   target expects this.  */
    319		p = (uintptr_t) p1;
    320		fail_unless ((p & pagemask) == 0);
    321		/* Verify that the file maps was made correctly.  */
    322		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
    323			     == ((test_fsize - sizeof *p1) / sizeof *p1));
    324
    325		/* Verify that the end of page is accessible and zeroed.  */
    326		cp = (void *) p1;
    327		fail_unless (cp[pagesize - 4] == 0);
    328		munmap (p1, pagesize);
    329	}
    330	fprintf(stdout, " passed\n");
    331}
    332
    333void check_file_fixed_eof_mmaps(void)
    334{
    335	char *addr;
    336	char *cp;
    337	unsigned int *p1;
    338	uintptr_t p;
    339	int i;
    340
    341	/* Find a suitable address to start with.  */
    342	addr = mmap(NULL, pagesize * 44, PROT_READ, 
    343		    MAP_PRIVATE | MAP_ANONYMOUS,
    344		    -1, 0);
    345
    346	fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
    347	fail_unless (addr != MAP_FAILED);
    348
    349	for (i = 0; i < 0x10; i++)
    350	{
    351		/* Create submaps within our unfixed map.  */
    352		p1 = mmap(addr, pagesize, PROT_READ, 
    353			  MAP_PRIVATE | MAP_FIXED, 
    354			  test_fd, 
    355			  (test_fsize - sizeof *p1) & ~pagemask);
    356
    357		fail_unless (p1 != MAP_FAILED);
    358
    359		/* Make sure we get pages aligned with the pagesize. The
    360		   target expects this.  */
    361		p = (uintptr_t) p1;
    362		fail_unless ((p & pagemask) == 0);
    363
    364		/* Verify that the file maps was made correctly.  */
    365		fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
    366			     == ((test_fsize - sizeof *p1) / sizeof *p1));
    367
    368		/* Verify that the end of page is accessible and zeroed.  */
    369		cp = (void *)p1;
    370		fail_unless (cp[pagesize - 4] == 0);
    371		munmap (p1, pagesize);
    372		addr += pagesize;
    373	}
    374	fprintf(stdout, " passed\n");
    375}
    376
    377void check_file_fixed_mmaps(void)
    378{
    379	unsigned char *addr;
    380	unsigned int *p1, *p2, *p3, *p4;
    381	int i;
    382
    383	/* Find a suitable address to start with.  */
    384	addr = mmap(NULL, pagesize * 40 * 4, PROT_READ, 
    385		    MAP_PRIVATE | MAP_ANONYMOUS,
    386		    -1, 0);
    387	fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
    388	fail_unless (addr != MAP_FAILED);
    389
    390	for (i = 0; i < 40; i++)
    391	{
    392		p1 = mmap(addr, pagesize, PROT_READ, 
    393			  MAP_PRIVATE | MAP_FIXED,
    394			  test_fd, 0);
    395		p2 = mmap(addr + pagesize, pagesize, PROT_READ, 
    396			  MAP_PRIVATE | MAP_FIXED,
    397			  test_fd, pagesize);
    398		p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ, 
    399			  MAP_PRIVATE | MAP_FIXED,
    400			  test_fd, pagesize * 2);
    401		p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, 
    402			  MAP_PRIVATE | MAP_FIXED,
    403			  test_fd, pagesize * 3);
    404
    405		/* Make sure we get pages aligned with the pagesize. 
    406		   The target expects this.  */
    407		fail_unless (p1 == (void *)addr);
    408		fail_unless (p2 == (void *)addr + pagesize);
    409		fail_unless (p3 == (void *)addr + pagesize * 2);
    410		fail_unless (p4 == (void *)addr + pagesize * 3);
    411
    412		/* Verify that the file maps was made correctly.  */
    413		fail_unless (*p1 == 0);
    414		fail_unless (*p2 == (pagesize / sizeof *p2));
    415		fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
    416		fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
    417
    418		memcpy (dummybuf, p1, pagesize);
    419		memcpy (dummybuf, p2, pagesize);
    420		memcpy (dummybuf, p3, pagesize);
    421		memcpy (dummybuf, p4, pagesize);
    422
    423		munmap (p1, pagesize);
    424		munmap (p2, pagesize);
    425		munmap (p3, pagesize);
    426		munmap (p4, pagesize);
    427		addr += pagesize * 4;
    428	}
    429	fprintf(stdout, " passed\n");
    430}
    431
    432void checked_write(int fd, const void *buf, size_t count)
    433{
    434    ssize_t rc = write(fd, buf, count);
    435    fail_unless(rc == count);
    436}
    437
    438void check_invalid_mmaps(void)
    439{
    440    unsigned char *addr;
    441
    442    /* Attempt to map a zero length page.  */
    443    addr = mmap(NULL, 0, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    444    fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
    445    fail_unless(addr == MAP_FAILED);
    446    fail_unless(errno == EINVAL);
    447
    448    /* Attempt to map a over length page.  */
    449    addr = mmap(NULL, -4, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    450    fprintf(stdout, "%s addr=%p", __func__, (void *)addr);
    451    fail_unless(addr == MAP_FAILED);
    452    fail_unless(errno == ENOMEM);
    453
    454    fprintf(stdout, " passed\n");
    455}
    456
    457int main(int argc, char **argv)
    458{
    459	char tempname[] = "/tmp/.cmmapXXXXXX";
    460	unsigned int i;
    461
    462	/* Trust the first argument, otherwise probe the system for our
    463	   pagesize.  */
    464	if (argc > 1)
    465		pagesize = strtoul(argv[1], NULL, 0);
    466	else
    467		pagesize = sysconf(_SC_PAGESIZE);
    468
    469	/* Assume pagesize is a power of two.  */
    470	pagemask = pagesize - 1;
    471	dummybuf = malloc (pagesize);
    472	printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
    473
    474	test_fd = mkstemp(tempname);
    475	unlink(tempname);
    476
    477	/* Fill the file with int's counting from zero and up.  */
    478    for (i = 0; i < (pagesize * 4) / sizeof i; i++) {
    479        checked_write(test_fd, &i, sizeof i);
    480    }
    481
    482	/* Append a few extra writes to make the file end at non 
    483	   page boundary.  */
    484    checked_write(test_fd, &i, sizeof i); i++;
    485    checked_write(test_fd, &i, sizeof i); i++;
    486    checked_write(test_fd, &i, sizeof i); i++;
    487
    488	test_fsize = lseek(test_fd, 0, SEEK_CUR);
    489
    490	/* Run the tests.  */
    491	check_aligned_anonymous_unfixed_mmaps();
    492	check_aligned_anonymous_unfixed_colliding_mmaps();
    493	check_aligned_anonymous_fixed_mmaps();
    494	check_file_unfixed_mmaps();
    495	check_file_fixed_mmaps();
    496	check_file_fixed_eof_mmaps();
    497	check_file_unfixed_eof_mmaps();
    498	check_invalid_mmaps();
    499
    500	/* Fails at the moment.  */
    501	/* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
    502
    503	return EXIT_SUCCESS;
    504}