File: misalign.c

package info (click to toggle)
libhugetlbfs 2.24-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,272 kB
  • sloc: ansic: 10,830; python: 810; makefile: 670; sh: 660; asm: 170
file content (145 lines) | stat: -rw-r--r-- 4,628 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * libhugetlbfs - Easy use of Linux hugepages
 * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/utsname.h>

#include <hugetlbfs.h>

#include "hugetests.h"

/*
 * Test rationale:
 *
 * Just as normal mmap()s can't have an address, length or offset
 * which is not page aligned, so hugepage mmap()s can't have an
 * address, length or offset with is not hugepage aligned.
 *
 * However, from time to time when the various mmap() /
 * get_unmapped_area() paths are updated, somebody misses one of the
 * necessary checks for the hugepage paths.  This testcase ensures
 * that attempted hugepage mappings with parameters which are not
 * correctly hugepage aligned are rejected.
 *
 * However starting with 3.10-rc1, length passed in mmap() doesn't need
 * to be aligned because commit af73e4d9506d3b797509f3c030e7dcd554f7d9c4
 * added ALIGN() to kernel side, in mmap_pgoff(), when mapping huge page
 * files.
 */
int main(int argc, char *argv[])
{
	long page_size, hpage_size;
	int fd;
	void *p, *q;
	int err;
	struct utsname buf;

	test_init(argc, argv);

	if (uname(&buf) != 0)
		FAIL("uname failed %s", strerror(errno));

	page_size = getpagesize();
	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	/* First see what an ok mapping looks like, as a basis for our
	 * bad addresses and so forth */
	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() without hint failed: %s", strerror(errno));
	if (((unsigned long)p % hpage_size) != 0)
		FAIL("mmap() without hint at misaligned address");

	verbose_printf("Mapped at %p, length 0x%lx\n", p, hpage_size);

	err = munmap(p, hpage_size);
	if (err != 0)
		FAIL("munmap() without hint failed: %s", strerror(errno));

	/* 1) Try a misaligned hint address */
	q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE, fd, 0);
	if (q == MAP_FAILED)
		/* Bad hint shouldn't fail, just ignore the hint */
		FAIL("mmap() with hint failed: %s", strerror(errno));
	if (((unsigned long)q % hpage_size) != 0)
		FAIL("mmap() with hint at misaligned address");

	err = munmap(q, hpage_size);
	if (err != 0)
		FAIL("munmap() with hint failed: %s", strerror(errno));

	/* 2) Try a misaligned address with MAP_FIXED */
	q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE|MAP_FIXED, fd, 0);
	if (q != MAP_FAILED)
		FAIL("mmap() MAP_FIXED at misaligned address succeeded");

	/* 3) Try a misaligned length */
	q = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);

	if (test_compare_kver(buf.release, "3.10.0") < 0) {
		if (q != MAP_FAILED)
			FAIL("mmap() with misaligned length 0x%lx succeeded",
				page_size);
	} else {
		if (q == MAP_FAILED)
			FAIL("mmap() with misaligned length 0x%lx failed",
				page_size);
	}

	/* 4) Try a misaligned length with MAP_FIXED */
	q = mmap(p, page_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE|MAP_FIXED, fd, 0);

	if (test_compare_kver(buf.release, "3.10.0") < 0) {
		if (q != MAP_FAILED)
			FAIL("mmap() MAP_FIXED with misaligned length 0x%lx "
				"succeeded", page_size);
	} else {
		if (q == MAP_FAILED)
			FAIL("mmap() MAP_FIXED with misaligned length 0x%lx "
				"failed", page_size);
	}

	/* 5) Try a misaligned offset */
	q = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE, fd, page_size);
	if (q != MAP_FAILED)
		FAIL("mmap() with misaligned offset 0x%lx succeeded",
		     page_size);

	/* 6) Try a misaligned offset with MAP_FIXED*/
	q = mmap(p, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE|MAP_FIXED, fd, page_size);
	if (q != MAP_FAILED)
		FAIL("mmap() MAP_FIXED with misaligned offset 0x%lx succeeded",
		     page_size);

	PASS();
}