1 /* $OpenBSD: mmap_noreplace.c,v 1.1 2014/06/19 19:34:22 matthew Exp $ */
2 /*
3 * Copyright (c) 2014 Google Inc.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/mman.h>
19 #include <assert.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #define CHECK(a) assert(a)
24 #define CHECK_EQ(a, b) assert((a) == (b))
25 #define CHECK_NE(a, b) assert((a) != (b))
26 #define CHECK_GE(a, b) assert((a) >= (b))
27
28 int
ismemset(void * b,int c,size_t n)29 ismemset(void *b, int c, size_t n)
30 {
31 unsigned char *p = b;
32 size_t i;
33 for (i = 0; i < n; i++)
34 if (p[i] != c)
35 return (0);
36 return (1);
37 }
38
39 int
main()40 main()
41 {
42 char *p;
43 long pagesize;
44
45 pagesize = sysconf(_SC_PAGESIZE);
46 CHECK_GE(pagesize, 1);
47
48 /* Allocate three pages of anonymous memory. */
49 p = mmap(NULL, 3 * pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
50 CHECK_NE(MAP_FAILED, p);
51
52 /* Initialize memory to all 1 bytes. */
53 memset(p, 1, 3 * pagesize);
54 CHECK(ismemset(p, 1, 3 * pagesize));
55
56 /* Map new anonymous memory over the second page. */
57 CHECK_EQ(p + pagesize, mmap(p + pagesize, pagesize,
58 PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0));
59
60 /* Verify the second page is zero'd out, and the others are unscathed. */
61 CHECK(ismemset(p, 1, pagesize));
62 CHECK(ismemset(p + pagesize, 0, pagesize));
63 CHECK(ismemset(p + 2 * pagesize, 1, pagesize));
64
65 /* Re-initialized memory. */
66 memset(p, 1, 3 * pagesize);
67 CHECK(ismemset(p, 1, 3 * pagesize));
68
69 /* Try to map over second page with __MAP_NOREPLACE; should fail. */
70 CHECK_EQ(MAP_FAILED, mmap(p, pagesize, PROT_READ|PROT_WRITE,
71 MAP_PRIVATE|MAP_ANON|MAP_FIXED|__MAP_NOREPLACE, -1, 0));
72
73 /* Verify the pages are still set. */
74 CHECK(ismemset(p, 1, 3 * pagesize));
75
76 return (0);
77 }
78