• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Linux Test Project, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it
13  * is free of the rightful claim of any third person regarding
14  * infringement or the like.  Any license provided herein, whether
15  * implied or otherwise, applies only to this software file.  Patent
16  * licenses, if any, provided herein do not apply to combinations of
17  * this program with other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301, USA.
23  */
24 /*
25  * Test Name: mremap05
26  *
27  * Test Description:
28  *  Verify that MREMAP_FIXED fails without MREMAP_MAYMOVE.
29  *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if target address
30  *    is not page aligned.
31  *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if old range
32  *    overlaps with new range.
33  *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE can move mapping to new address.
34  *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE unmaps previous mapping
35  *    at the address range specified by new_address and new_size.
36  */
37 
38 #define _GNU_SOURCE
39 #include "config.h"
40 #include <sys/mman.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include "test.h"
44 #include "safe_macros.h"
45 
46 char *TCID = "mremap05";
47 
48 struct test_case_t {
49 	char *old_address;
50 	char *new_address;
51 	size_t old_size;	/* in pages */
52 	size_t new_size;	/* in pages */
53 	int flags;
54 	const char *msg;
55 	void *exp_ret;
56 	int exp_errno;
57 	char *ret;
58 	void (*setup) (struct test_case_t *);
59 	void (*cleanup) (struct test_case_t *);
60 };
61 
62 static void setup(void);
63 static void cleanup(void);
64 static void setup0(struct test_case_t *);
65 static void setup1(struct test_case_t *);
66 static void setup2(struct test_case_t *);
67 static void setup3(struct test_case_t *);
68 static void setup4(struct test_case_t *);
69 static void cleanup0(struct test_case_t *);
70 static void cleanup1(struct test_case_t *);
71 
72 struct test_case_t tdat[] = {
73 	{
74 	 .old_size = 1,
75 	 .new_size = 1,
76 	 .flags = MREMAP_FIXED,
77 	 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
78 	 .exp_ret = MAP_FAILED,
79 	 .exp_errno = EINVAL,
80 	 .setup = setup0,
81 	 .cleanup = cleanup0},
82 	{
83 	 .old_size = 1,
84 	 .new_size = 1,
85 	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
86 	 .msg = "new_addr has to be page aligned",
87 	 .exp_ret = MAP_FAILED,
88 	 .exp_errno = EINVAL,
89 	 .setup = setup1,
90 	 .cleanup = cleanup0},
91 	{
92 	 .old_size = 2,
93 	 .new_size = 1,
94 	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
95 	 .msg = "old/new area must not overlap",
96 	 .exp_ret = MAP_FAILED,
97 	 .exp_errno = EINVAL,
98 	 .setup = setup2,
99 	 .cleanup = cleanup0},
100 	{
101 	 .old_size = 1,
102 	 .new_size = 1,
103 	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
104 	 .msg = "mremap #1",
105 	 .setup = setup3,
106 	 .cleanup = cleanup0},
107 	{
108 	 .old_size = 1,
109 	 .new_size = 1,
110 	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
111 	 .msg = "mremap #2",
112 	 .setup = setup4,
113 	 .cleanup = cleanup1},
114 };
115 
116 static int pagesize;
117 static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
118 
free_test_area(void * p,int size)119 static void free_test_area(void *p, int size)
120 {
121 	SAFE_MUNMAP(cleanup, p, size);
122 }
123 
get_test_area(int size,int free_area)124 static void *get_test_area(int size, int free_area)
125 {
126 	void *p;
127 	p = mmap(NULL, size, PROT_READ | PROT_WRITE,
128 		 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
129 	if (p == MAP_FAILED)
130 		tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap");
131 	if (free_area)
132 		free_test_area(p, size);
133 	return p;
134 }
135 
test_mremap(struct test_case_t * t)136 static void test_mremap(struct test_case_t *t)
137 {
138 	t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags,
139 			t->new_address);
140 
141 	if (t->ret == t->exp_ret) {
142 		if (t->ret != MAP_FAILED) {
143 			tst_resm(TPASS, "%s", t->msg);
144 			if (*(t->ret) == 0x1)
145 				tst_resm(TPASS, "%s value OK", t->msg);
146 			else
147 				tst_resm(TPASS, "%s value failed", t->msg);
148 		} else {
149 			if (errno == t->exp_errno)
150 				tst_resm(TPASS, "%s", t->msg);
151 			else
152 				tst_resm(TFAIL | TERRNO, "%s", t->msg);
153 		}
154 	} else {
155 		tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg,
156 			 t->ret, t->exp_ret);
157 	}
158 }
159 
setup0(struct test_case_t * t)160 static void setup0(struct test_case_t *t)
161 {
162 	t->old_address = get_test_area(t->old_size * pagesize, 0);
163 	t->new_address = get_test_area(t->new_size * pagesize, 1);
164 }
165 
setup1(struct test_case_t * t)166 static void setup1(struct test_case_t *t)
167 {
168 	t->old_address = get_test_area(t->old_size * pagesize, 0);
169 	t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1;
170 }
171 
setup2(struct test_case_t * t)172 static void setup2(struct test_case_t *t)
173 {
174 	t->old_address = get_test_area(t->old_size * pagesize, 0);
175 	t->new_address = t->old_address;
176 }
177 
setup3(struct test_case_t * t)178 static void setup3(struct test_case_t *t)
179 {
180 	t->old_address = get_test_area(t->old_size * pagesize, 0);
181 	t->new_address = get_test_area(t->new_size * pagesize, 1);
182 	t->exp_ret = t->new_address;
183 	*(t->old_address) = 0x1;
184 }
185 
setup4(struct test_case_t * t)186 static void setup4(struct test_case_t *t)
187 {
188 	t->old_address = get_test_area(t->old_size * pagesize, 0);
189 	t->new_address = get_test_area(t->new_size * pagesize, 0);
190 	t->exp_ret = t->new_address;
191 	*(t->old_address) = 0x1;
192 	*(t->new_address) = 0x2;
193 }
194 
cleanup0(struct test_case_t * t)195 static void cleanup0(struct test_case_t *t)
196 {
197 	if (t->ret == MAP_FAILED)
198 		free_test_area(t->old_address, t->old_size * pagesize);
199 	else
200 		free_test_area(t->ret, t->new_size * pagesize);
201 }
202 
cleanup1(struct test_case_t * t)203 static void cleanup1(struct test_case_t *t)
204 {
205 	if (t->ret == MAP_FAILED) {
206 		free_test_area(t->old_address, t->old_size * pagesize);
207 		free_test_area(t->new_address, t->new_size * pagesize);
208 	} else {
209 		free_test_area(t->ret, t->new_size * pagesize);
210 	}
211 }
212 
main(int ac,char ** av)213 int main(int ac, char **av)
214 {
215 	int lc, testno;
216 
217 	tst_parse_opts(ac, av, NULL, NULL);
218 
219 	setup();
220 	for (lc = 0; TEST_LOOPING(lc); lc++) {
221 		tst_count = 0;
222 		for (testno = 0; testno < TST_TOTAL; testno++) {
223 			tdat[testno].setup(&tdat[testno]);
224 			test_mremap(&tdat[testno]);
225 			tdat[testno].cleanup(&tdat[testno]);
226 		}
227 	}
228 	cleanup();
229 	tst_exit();
230 }
231 
setup(void)232 static void setup(void)
233 {
234 	pagesize = getpagesize();
235 }
236 
cleanup(void)237 static void cleanup(void)
238 {
239 }
240