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