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