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 #ifdef HAVE_MREMAP_FIXED 49 50 struct test_case_t { 51 char *old_address; 52 char *new_address; 53 size_t old_size; /* in pages */ 54 size_t new_size; /* in pages */ 55 int flags; 56 const char *msg; 57 void *exp_ret; 58 int exp_errno; 59 char *ret; 60 void (*setup) (struct test_case_t *); 61 void (*cleanup) (struct test_case_t *); 62 }; 63 64 static void setup(void); 65 static void cleanup(void); 66 static void setup0(struct test_case_t *); 67 static void setup1(struct test_case_t *); 68 static void setup2(struct test_case_t *); 69 static void setup3(struct test_case_t *); 70 static void setup4(struct test_case_t *); 71 static void cleanup0(struct test_case_t *); 72 static void cleanup1(struct test_case_t *); 73 74 struct test_case_t tdat[] = { 75 { 76 .old_size = 1, 77 .new_size = 1, 78 .flags = MREMAP_FIXED, 79 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE", 80 .exp_ret = MAP_FAILED, 81 .exp_errno = EINVAL, 82 .setup = setup0, 83 .cleanup = cleanup0}, 84 { 85 .old_size = 1, 86 .new_size = 1, 87 .flags = MREMAP_FIXED | MREMAP_MAYMOVE, 88 .msg = "new_addr has to be page aligned", 89 .exp_ret = MAP_FAILED, 90 .exp_errno = EINVAL, 91 .setup = setup1, 92 .cleanup = cleanup0}, 93 { 94 .old_size = 2, 95 .new_size = 1, 96 .flags = MREMAP_FIXED | MREMAP_MAYMOVE, 97 .msg = "old/new area must not overlap", 98 .exp_ret = MAP_FAILED, 99 .exp_errno = EINVAL, 100 .setup = setup2, 101 .cleanup = cleanup0}, 102 { 103 .old_size = 1, 104 .new_size = 1, 105 .flags = MREMAP_FIXED | MREMAP_MAYMOVE, 106 .msg = "mremap #1", 107 .setup = setup3, 108 .cleanup = cleanup0}, 109 { 110 .old_size = 1, 111 .new_size = 1, 112 .flags = MREMAP_FIXED | MREMAP_MAYMOVE, 113 .msg = "mremap #2", 114 .setup = setup4, 115 .cleanup = cleanup1}, 116 }; 117 118 static int pagesize; 119 static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 120 121 static void free_test_area(void *p, int size) 122 { 123 SAFE_MUNMAP(cleanup, p, size); 124 } 125 126 static void *get_test_area(int size, int free_area) 127 { 128 void *p; 129 p = mmap(NULL, size, PROT_READ | PROT_WRITE, 130 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 131 if (p == MAP_FAILED) 132 tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap"); 133 if (free_area) 134 free_test_area(p, size); 135 return p; 136 } 137 138 static void test_mremap(struct test_case_t *t) 139 { 140 t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags, 141 t->new_address); 142 143 if (t->ret == t->exp_ret) { 144 if (t->ret != MAP_FAILED) { 145 tst_resm(TPASS, "%s", t->msg); 146 if (*(t->ret) == 0x1) 147 tst_resm(TPASS, "%s value OK", t->msg); 148 else 149 tst_resm(TPASS, "%s value failed", t->msg); 150 } else { 151 if (errno == t->exp_errno) 152 tst_resm(TPASS, "%s", t->msg); 153 else 154 tst_resm(TFAIL | TERRNO, "%s", t->msg); 155 } 156 } else { 157 tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg, 158 t->ret, t->exp_ret); 159 } 160 } 161 162 static void setup0(struct test_case_t *t) 163 { 164 t->old_address = get_test_area(t->old_size * pagesize, 0); 165 t->new_address = get_test_area(t->new_size * pagesize, 1); 166 } 167 168 static void setup1(struct test_case_t *t) 169 { 170 t->old_address = get_test_area(t->old_size * pagesize, 0); 171 t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1; 172 } 173 174 static void setup2(struct test_case_t *t) 175 { 176 t->old_address = get_test_area(t->old_size * pagesize, 0); 177 t->new_address = t->old_address; 178 } 179 180 static void setup3(struct test_case_t *t) 181 { 182 t->old_address = get_test_area(t->old_size * pagesize, 0); 183 t->new_address = get_test_area(t->new_size * pagesize, 1); 184 t->exp_ret = t->new_address; 185 *(t->old_address) = 0x1; 186 } 187 188 static void setup4(struct test_case_t *t) 189 { 190 t->old_address = get_test_area(t->old_size * pagesize, 0); 191 t->new_address = get_test_area(t->new_size * pagesize, 0); 192 t->exp_ret = t->new_address; 193 *(t->old_address) = 0x1; 194 *(t->new_address) = 0x2; 195 } 196 197 static void cleanup0(struct test_case_t *t) 198 { 199 if (t->ret == MAP_FAILED) 200 free_test_area(t->old_address, t->old_size * pagesize); 201 else 202 free_test_area(t->ret, t->new_size * pagesize); 203 } 204 205 static void cleanup1(struct test_case_t *t) 206 { 207 if (t->ret == MAP_FAILED) { 208 free_test_area(t->old_address, t->old_size * pagesize); 209 free_test_area(t->new_address, t->new_size * pagesize); 210 } else { 211 free_test_area(t->ret, t->new_size * pagesize); 212 } 213 } 214 215 int main(int ac, char **av) 216 { 217 int lc, testno; 218 219 tst_parse_opts(ac, av, NULL, NULL); 220 221 setup(); 222 for (lc = 0; TEST_LOOPING(lc); lc++) { 223 tst_count = 0; 224 for (testno = 0; testno < TST_TOTAL; testno++) { 225 tdat[testno].setup(&tdat[testno]); 226 test_mremap(&tdat[testno]); 227 tdat[testno].cleanup(&tdat[testno]); 228 } 229 } 230 cleanup(); 231 tst_exit(); 232 } 233 234 static void setup(void) 235 { 236 pagesize = getpagesize(); 237 } 238 239 static void cleanup(void) 240 { 241 } 242 243 #else 244 245 int main(void) 246 { 247 tst_brkm(TCONF, NULL, "MREMAP_FIXED not present in <sys/mman.h>"); 248 } 249 250 #endif /* HAVE_MREMAP_FIXED */ 251