Home | History | Annotate | Download | only in munmap
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2001
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;  if not, write to the Free Software
     17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /*
     21  * Test Description:
     22  *  Verify that,
     23  *   1. munmap() fails with -1 return value and sets errno to EINVAL
     24  *      if addresses in the range [addr,addr+len) are outside the valid
     25  *	range for the address space of a process.
     26  *   2. munmap() fails with -1 return value and sets errno to EINVAL
     27  *      if the len argument is 0.
     28  *   3. munmap() fails with -1 return value and sets errno to EINVAL
     29  *      if the addr argument is not a multiple of the page size as
     30  *      returned by sysconf().
     31  *
     32  * HISTORY
     33  *	07/2001 Ported by Wayne Boyer
     34  */
     35 
     36 #include <errno.h>
     37 #include <unistd.h>
     38 #include <fcntl.h>
     39 #include <sys/mman.h>
     40 #include <sys/resource.h>
     41 #include <sys/stat.h>
     42 
     43 #include "test.h"
     44 #include "safe_macros.h"
     45 
     46 char *TCID = "munmap03";
     47 
     48 static size_t page_sz;
     49 static char *global_addr;
     50 static size_t global_maplen;
     51 
     52 static void setup(void);
     53 static void cleanup(void);
     54 
     55 static void test_einval1(void);
     56 static void test_einval2(void);
     57 static void test_einval3(void);
     58 static void (*testfunc[])(void) = { test_einval1, test_einval2, test_einval3 };
     59 int TST_TOTAL = ARRAY_SIZE(testfunc);
     60 
     61 int main(int ac, char **av)
     62 {
     63 	int i, lc;
     64 
     65 	tst_parse_opts(ac, av, NULL, NULL);
     66 
     67 	setup();
     68 
     69 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     70 		tst_count = 0;
     71 
     72 		for (i = 0; i < TST_TOTAL; i++)
     73 			(*testfunc[i])();
     74 	}
     75 
     76 	cleanup();
     77 	tst_exit();
     78 }
     79 
     80 static void setup(void)
     81 {
     82 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
     83 
     84 	TEST_PAUSE;
     85 
     86 	page_sz = (size_t)sysconf(_SC_PAGESIZE);
     87 
     88 	global_maplen = page_sz * 2;
     89 	global_addr = SAFE_MMAP(cleanup, NULL, global_maplen, PROT_READ |
     90 				PROT_WRITE, MAP_PRIVATE_EXCEPT_UCLINUX |
     91 				MAP_ANONYMOUS, -1, 0);
     92 }
     93 
     94 static void check_and_print(int expected_errno)
     95 {
     96 	if (TEST_RETURN == -1) {
     97 		if (TEST_ERRNO == expected_errno) {
     98 			tst_resm(TPASS | TTERRNO, "failed as expected");
     99 		} else {
    100 			tst_resm(TFAIL | TTERRNO,
    101 				 "failed unexpectedly; expected - %d : %s",
    102 				 expected_errno, strerror(expected_errno));
    103 		}
    104 	} else {
    105 		tst_resm(TFAIL, "munmap succeeded unexpectedly");
    106 	}
    107 }
    108 
    109 static void test_einval1(void)
    110 {
    111 	struct rlimit brkval;
    112 	char *addr;
    113 	size_t map_len;
    114 
    115 	SAFE_GETRLIMIT(cleanup, RLIMIT_DATA, &brkval);
    116 
    117 	addr = (char *)brkval.rlim_max;
    118 	map_len = page_sz * 2;
    119 
    120 	TEST(munmap(addr, map_len));
    121 
    122 	check_and_print(EINVAL);
    123 }
    124 
    125 static void test_einval2(void)
    126 {
    127 	char *addr = global_addr;
    128 	size_t map_len = 0;
    129 
    130 	if (tst_kvercmp(2, 6, 12) < 0) {
    131 		tst_resm(TCONF,
    132 			 "EINVAL error value test for this condition needs "
    133 			 "kernel 2.6.12 or higher");
    134 		return;
    135 	}
    136 
    137 	TEST(munmap(addr, map_len));
    138 
    139 	check_and_print(EINVAL);
    140 }
    141 
    142 static void test_einval3(void)
    143 {
    144 	char *addr = (char *)(global_addr + 1);
    145 	size_t map_len = page_sz;
    146 
    147 	TEST(munmap(addr, map_len));
    148 
    149 	check_and_print(EINVAL);
    150 }
    151 
    152 static void cleanup(void)
    153 {
    154 	if (munmap(global_addr, global_maplen) == -1)
    155 		tst_resm(TWARN | TERRNO, "munmap failed");
    156 }
    157