Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 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 |
Cyril Hrubis | 123bb3d | 2013-01-21 16:11:26 +0100 | [diff] [blame] | 39 | #include "config.h" |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 40 | #include <sys/mman.h> |
| 41 | #include <errno.h> |
| 42 | #include <unistd.h> |
| 43 | #include "test.h" |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 44 | |
| 45 | char *TCID = "mremap05"; |
| 46 | |
Cyril Hrubis | 123bb3d | 2013-01-21 16:11:26 +0100 | [diff] [blame] | 47 | #ifdef HAVE_MREMAP_FIXED |
| 48 | |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 49 | struct test_case_t { |
| 50 | char *old_address; |
| 51 | char *new_address; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 52 | size_t old_size; /* in pages */ |
| 53 | size_t new_size; /* in pages */ |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 54 | int flags; |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 55 | const const char *msg; |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 56 | void *exp_ret; |
| 57 | int exp_errno; |
| 58 | char *ret; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 59 | void (*setup) (struct test_case_t *); |
| 60 | void (*cleanup) (struct test_case_t *); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 61 | }; |
| 62 | |
| 63 | static void setup(void); |
| 64 | static void cleanup(void); |
| 65 | static void setup0(struct test_case_t *); |
| 66 | static void setup1(struct test_case_t *); |
| 67 | static void setup2(struct test_case_t *); |
| 68 | static void setup3(struct test_case_t *); |
| 69 | static void setup4(struct test_case_t *); |
| 70 | static void cleanup0(struct test_case_t *); |
| 71 | static void cleanup1(struct test_case_t *); |
| 72 | |
| 73 | struct test_case_t tdat[] = { |
| 74 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 75 | .old_size = 1, |
| 76 | .new_size = 1, |
| 77 | .flags = MREMAP_FIXED, |
| 78 | .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE", |
| 79 | .exp_ret = MAP_FAILED, |
| 80 | .exp_errno = EINVAL, |
| 81 | .setup = setup0, |
| 82 | .cleanup = cleanup0}, |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 83 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 84 | .old_size = 1, |
| 85 | .new_size = 1, |
| 86 | .flags = MREMAP_FIXED | MREMAP_MAYMOVE, |
| 87 | .msg = "new_addr has to be page aligned", |
| 88 | .exp_ret = MAP_FAILED, |
| 89 | .exp_errno = EINVAL, |
| 90 | .setup = setup1, |
| 91 | .cleanup = cleanup0}, |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 92 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 93 | .old_size = 2, |
| 94 | .new_size = 1, |
| 95 | .flags = MREMAP_FIXED | MREMAP_MAYMOVE, |
| 96 | .msg = "old/new area must not overlap", |
| 97 | .exp_ret = MAP_FAILED, |
| 98 | .exp_errno = EINVAL, |
| 99 | .setup = setup2, |
| 100 | .cleanup = cleanup0}, |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 101 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 102 | .old_size = 1, |
| 103 | .new_size = 1, |
| 104 | .flags = MREMAP_FIXED | MREMAP_MAYMOVE, |
| 105 | .msg = "mremap #1", |
| 106 | .setup = setup3, |
| 107 | .cleanup = cleanup0}, |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 108 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 109 | .old_size = 1, |
| 110 | .new_size = 1, |
| 111 | .flags = MREMAP_FIXED | MREMAP_MAYMOVE, |
| 112 | .msg = "mremap #2", |
| 113 | .setup = setup4, |
| 114 | .cleanup = cleanup1}, |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 115 | }; |
| 116 | |
| 117 | static int pagesize; |
| 118 | static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); |
| 119 | |
| 120 | static void free_test_area(void *p, int size) |
| 121 | { |
| 122 | if (munmap(p, size) < 0) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 123 | tst_brkm(TBROK | TERRNO, cleanup, "free_test_area munmap"); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | static void *get_test_area(int size, int free_area) |
| 127 | { |
| 128 | void *p; |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 129 | p = mmap(NULL, size, PROT_READ | PROT_WRITE, |
| 130 | MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 131 | if (p == MAP_FAILED) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 132 | tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap"); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 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, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 141 | t->new_address); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 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 |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 154 | tst_resm(TFAIL | TERRNO, "%s", t->msg); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 155 | } |
| 156 | } else { |
| 157 | tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 158 | t->ret, t->exp_ret); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 159 | } |
| 160 | } |
| 161 | |
| 162 | static void setup0(struct test_case_t *t) |
| 163 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 164 | t->old_address = get_test_area(t->old_size * pagesize, 0); |
| 165 | t->new_address = get_test_area(t->new_size * pagesize, 1); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | static void setup1(struct test_case_t *t) |
| 169 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 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; |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | static void setup2(struct test_case_t *t) |
| 175 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 176 | t->old_address = get_test_area(t->old_size * pagesize, 0); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 177 | t->new_address = t->old_address; |
| 178 | } |
| 179 | |
| 180 | static void setup3(struct test_case_t *t) |
| 181 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 182 | t->old_address = get_test_area(t->old_size * pagesize, 0); |
| 183 | t->new_address = get_test_area(t->new_size * pagesize, 1); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 184 | t->exp_ret = t->new_address; |
| 185 | *(t->old_address) = 0x1; |
| 186 | } |
| 187 | |
| 188 | static void setup4(struct test_case_t *t) |
| 189 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 190 | t->old_address = get_test_area(t->old_size * pagesize, 0); |
| 191 | t->new_address = get_test_area(t->new_size * pagesize, 0); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 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) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 200 | free_test_area(t->old_address, t->old_size * pagesize); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 201 | else |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 202 | free_test_area(t->ret, t->new_size * pagesize); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | static void cleanup1(struct test_case_t *t) |
| 206 | { |
| 207 | if (t->ret == MAP_FAILED) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 208 | free_test_area(t->old_address, t->old_size * pagesize); |
| 209 | free_test_area(t->new_address, t->new_size * pagesize); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 210 | } else { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 211 | free_test_area(t->ret, t->new_size * pagesize); |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | |
| 215 | int main(int ac, char **av) |
| 216 | { |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 217 | const char *msg; |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 218 | int lc, testno; |
| 219 | |
| 220 | msg = parse_opts(ac, av, NULL, NULL); |
| 221 | if (msg != NULL) |
| 222 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
| 223 | |
| 224 | setup(); |
| 225 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
Caspar Zhang | d59a659 | 2013-03-07 14:59:12 +0800 | [diff] [blame] | 226 | tst_count = 0; |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 227 | for (testno = 0; testno < TST_TOTAL; testno++) { |
| 228 | tdat[testno].setup(&tdat[testno]); |
| 229 | test_mremap(&tdat[testno]); |
| 230 | tdat[testno].cleanup(&tdat[testno]); |
| 231 | } |
| 232 | } |
| 233 | cleanup(); |
| 234 | tst_exit(); |
| 235 | } |
| 236 | |
| 237 | static void setup(void) |
| 238 | { |
| 239 | pagesize = getpagesize(); |
| 240 | } |
| 241 | |
| 242 | static void cleanup(void) |
| 243 | { |
Jan Stancek | e6a89db | 2012-11-05 12:18:33 +0100 | [diff] [blame] | 244 | } |
Cyril Hrubis | 123bb3d | 2013-01-21 16:11:26 +0100 | [diff] [blame] | 245 | |
| 246 | #else |
| 247 | |
| 248 | int main(void) |
| 249 | { |
| 250 | tst_brkm(TCONF, NULL, "MREMAP_FIXED not present in <sys/mman.h>"); |
| 251 | } |
| 252 | |
| 253 | #endif /* HAVE_MREMAP_FIXED */ |