1/*
2 * Copyright (c) International Business Machines  Corp., 2001
3 *
4 * This program is free software;  you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY;  without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program;  if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/*
20 * Test Description:
21 *  Call mmap() to map a file creating a mapped region with read access
22 *  under the following conditions -
23 *	- The prot parameter is set to PROT_WRITE
24 *	- The file descriptor is open for writing.
25 *	- The flags parameter has MAP_PRIVATE set.
26 *
27 *  The call should fail to map the file.
28 *
29 * Expected Result:
30 *  mmap() should fail returning -1 and errno should get set to EACCES.
31 *
32 * HISTORY
33 *	07/2001 Ported by Wayne Boyer
34 */
35#include <stdio.h>
36#include <stdlib.h>
37#include <sys/types.h>
38#include <errno.h>
39#include <unistd.h>
40#include <fcntl.h>
41#include <string.h>
42#include <signal.h>
43#include <sys/stat.h>
44#include <sys/mman.h>
45
46#include "test.h"
47
48#define TEMPFILE	"mmapfile"
49
50char *TCID = "mmap07";
51int TST_TOTAL = 1;
52
53static size_t page_sz;
54static char *addr;
55static int fildes;
56
57static void setup(void);
58static void cleanup(void);
59
60int main(int ac, char **av)
61{
62	int lc;
63
64	tst_parse_opts(ac, av, NULL, NULL);
65
66	setup();
67
68	for (lc = 0; TEST_LOOPING(lc); lc++) {
69
70		tst_count = 0;
71
72		/*
73		 * Call mmap to map the temporary file 'TEMPFILE'
74		 * with write access.
75		 */
76		errno = 0;
77		addr = mmap(0, page_sz, PROT_WRITE,
78			    MAP_FILE | MAP_PRIVATE, fildes, 0);
79		TEST_ERRNO = errno;
80
81		/* Check for the return value of mmap() */
82		if (addr != MAP_FAILED) {
83			tst_resm(TFAIL | TERRNO,
84				 "mmap() returned invalid value, expected: %p",
85				 MAP_FAILED);
86			/* Unmap the mapped memory */
87			if (munmap(addr, page_sz) != 0) {
88				tst_resm(TBROK, "munmap() failed");
89				cleanup();
90			}
91			continue;
92		}
93		if (TEST_ERRNO == EACCES) {
94			tst_resm(TPASS, "mmap failed with EACCES");
95		} else {
96			tst_resm(TFAIL | TERRNO,
97				 "mmap failed with unexpected errno");
98		}
99
100	}
101	cleanup();
102	tst_exit();
103
104}
105
106static void setup(void)
107{
108	char *tst_buff;
109
110	tst_sig(NOFORK, DEF_HANDLER, cleanup);
111
112	TEST_PAUSE;
113
114	page_sz = getpagesize();
115
116	/* Allocate space for the test buffer */
117	if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
118		tst_brkm(TFAIL, NULL,
119			 "calloc() failed to allocate space for tst_buff");
120	}
121
122	/* Fill the test buffer with the known data */
123	memset(tst_buff, 'A', page_sz);
124
125	tst_tmpdir();
126
127	/* Creat a temporary file used for mapping */
128	if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
129		free(tst_buff);
130		tst_brkm(TFAIL, cleanup, "open() on %s failed", TEMPFILE);
131	}
132
133	/* Write test buffer contents into temporary file */
134	if (write(fildes, tst_buff, page_sz) < (int)page_sz) {
135		free(tst_buff);
136		tst_brkm(TFAIL, cleanup, "writing to %s failed", TEMPFILE);
137	}
138
139	free(tst_buff);
140}
141
142static void cleanup(void)
143{
144	close(fildes);
145	tst_rmdir();
146}
147