1*49a6e16fSderaadt /* $OpenBSD: mmap_hint.c,v 1.6 2021/12/13 16:56:50 deraadt Exp $ */
2faca773dSariane /*
3faca773dSariane * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl>
4faca773dSariane *
5faca773dSariane * Permission to use, copy, modify, and distribute this software for any
6faca773dSariane * purpose with or without fee is hereby granted, provided that the above
7faca773dSariane * copyright notice and this permission notice appear in all copies.
8faca773dSariane *
9faca773dSariane * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10faca773dSariane * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11faca773dSariane * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12faca773dSariane * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13faca773dSariane * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14faca773dSariane * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15faca773dSariane * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16faca773dSariane */
17faca773dSariane
18*49a6e16fSderaadt #include <sys/param.h> /* PAGE_SIZE PAGE_MASK */
19faca773dSariane #include <sys/types.h>
20faca773dSariane #include <sys/mman.h>
21c4613df5Sbluhm #include <sys/tree.h>
22c4613df5Sbluhm #include <machine/pmap.h>
23faca773dSariane #include <machine/vmparam.h>
24faca773dSariane #include <err.h>
25faca773dSariane #include <sysexits.h>
26faca773dSariane #include <stdio.h>
27faca773dSariane
28faca773dSariane #define MAX_HINT_DIST (2UL * 1024 * 1024 * 1024)
29faca773dSariane
30faca773dSariane int errors = 0;
31faca773dSariane
32faca773dSariane void *
mmap_hint(void * hint)33faca773dSariane mmap_hint(void *hint)
34faca773dSariane {
35faca773dSariane void *p;
369e720447Sbluhm size_t delta;
37faca773dSariane
38faca773dSariane p = mmap(hint, 1, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
39faca773dSariane if (p == MAP_FAILED) {
40faca773dSariane warn("mmap(addr=%p, len=1) failed", hint);
41faca773dSariane errors++;
42faca773dSariane return MAP_FAILED;
43faca773dSariane } else if (p == NULL) {
44faca773dSariane warnx("mmap(addr=%p, len=1) mapped at address 0", hint);
45faca773dSariane errors++;
46faca773dSariane return MAP_FAILED;
47faca773dSariane } else
48faca773dSariane fprintf(stderr, " -> %p\n", p);
49faca773dSariane
50faca773dSariane if (hint > p)
519e720447Sbluhm delta = hint - p;
52faca773dSariane else
539e720447Sbluhm delta = p - hint;
54faca773dSariane
559e720447Sbluhm if (hint != NULL && delta > MAX_HINT_DIST) {
569e720447Sbluhm warnx("hinted allocation more than %#zx bytes away from hint: "
579e720447Sbluhm "hint %p, result %p", delta, hint, p);
58faca773dSariane errors++;
59faca773dSariane return MAP_FAILED;
60faca773dSariane }
61faca773dSariane return p;
62faca773dSariane }
63faca773dSariane
64faca773dSariane int
main()65faca773dSariane main()
66faca773dSariane {
679e720447Sbluhm void *p, *hint;
68faca773dSariane
69faca773dSariane /* Check that unhinted allocation works properly. */
709e720447Sbluhm hint = NULL;
719e720447Sbluhm fprintf(stderr, "1: Checking hint %p mmap\n", hint);
729e720447Sbluhm p = mmap_hint(hint);
73faca773dSariane
74faca773dSariane /* Check hinted allocation at top of map. */
759e720447Sbluhm hint = (void *)((VM_MAXUSER_ADDRESS & ~PAGE_MASK) - PAGE_SIZE);
769e720447Sbluhm fprintf(stderr, "2: Checking hint page below "
779e720447Sbluhm "VM_MAXUSER_ADDRESS %p mmap\n", hint);
789e720447Sbluhm p = mmap_hint(hint);
79faca773dSariane
80faca773dSariane /* Check hinted allocation at bottom of map. */
819e720447Sbluhm hint = (void *)VM_MIN_ADDRESS;
829e720447Sbluhm fprintf(stderr, "3: Checking hint VM_MIN_ADDRESS %p mmap\n", hint);
839e720447Sbluhm p = mmap_hint(hint);
84faca773dSariane
85faca773dSariane /*
86faca773dSariane * Check that hinted allocation doesn't overwrite existing allocation.
87faca773dSariane */
88faca773dSariane if (p == MAP_FAILED) {
89faca773dSariane fprintf(stderr, "4: Skipping test: required previous test "
90faca773dSariane "to succeed");
91faca773dSariane goto skip4;
92faca773dSariane }
939e720447Sbluhm hint = p;
949e720447Sbluhm fprintf(stderr, "4: Checking hint %p mmap, which is in use\n", hint);
959e720447Sbluhm p = mmap_hint(hint);
969e720447Sbluhm if (p == hint) {
979e720447Sbluhm warnx("hinted allocation %p overwrites previous allocation %p",
989e720447Sbluhm hint, p);
99faca773dSariane errors++;
100faca773dSariane }
101faca773dSariane
1029e720447Sbluhm skip4:
103faca773dSariane return errors;
104faca773dSariane }
105