blob: 2447329fd825147e647a9f606d7d2134213dbc95 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
Cyril Hrubis5efee332013-06-04 20:14:58 +02002 * Copyright (c) International Business Machines Corp., 2001
plars865695b2001-08-27 22:15:12 +00003 *
Cyril Hrubis5efee332013-06-04 20:14:58 +02004 * 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.
plars865695b2001-08-27 22:15:12 +00008 *
Cyril Hrubis5efee332013-06-04 20:14:58 +02009 * 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.
plars865695b2001-08-27 22:15:12 +000013 *
Cyril Hrubis5efee332013-06-04 20:14:58 +020014 * 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
plars865695b2001-08-27 22:15:12 +000017 */
18
19/*
plars865695b2001-08-27 22:15:12 +000020 * Test Description:
21 * Call mmap() to map a file creating a mapped region with execute access
22 * under the following conditions -
23 * - The prot parameter is set to PROT_EXE
24 * - The file descriptor is open for read
25 * - The file being mapped has execute permission bit set.
26 * - The minimum file permissions should be 0555.
27 *
28 * The call should succeed to map the file creating mapped memory with the
29 * required attributes.
30 *
31 * Expected Result:
32 * mmap() should succeed returning the address of the mapped region,
33 * and the mapped region should contain the contents of the mapped file.
vapier42c5b6b2007-07-21 20:40:56 +000034 * but with ia64 and PARISC/hppa,
robbiew30d1bed2003-05-07 15:50:36 +000035 * an attempt to access the contents of the mapped region should give
36 * rise to the signal SIGSEGV.
plars865695b2001-08-27 22:15:12 +000037 *
plars865695b2001-08-27 22:15:12 +000038 * HISTORY
39 * 07/2001 Ported by Wayne Boyer
plars865695b2001-08-27 22:15:12 +000040 */
plars865695b2001-08-27 22:15:12 +000041#include <stdio.h>
42#include <stdlib.h>
43#include <sys/types.h>
44#include <errno.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <string.h>
48#include <signal.h>
49#include <sys/stat.h>
50#include <sys/mman.h>
robbiew30d1bed2003-05-07 15:50:36 +000051#include <setjmp.h>
plars865695b2001-08-27 22:15:12 +000052
53#include "test.h"
plars865695b2001-08-27 22:15:12 +000054
55#define TEMPFILE "mmapfile"
56
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020057char *TCID = "mmap03";
58int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000059
Cyril Hrubis5efee332013-06-04 20:14:58 +020060static size_t page_sz;
61static char *addr;
62static char *dummy;
63static int fildes;
64static volatile int pass = 0;
65static sigjmp_buf env;
66
67static void setup(void);
68static void cleanup(void);
69static void sig_handler(int sig);
plars865695b2001-08-27 22:15:12 +000070
subrata_modak56207ce2009-03-23 13:35:39 +000071int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000072{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020073 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020074 const char *msg;
subrata_modakbdbaec52009-02-26 12:14:51 +000075
Garrett Cooper11d51042010-11-22 20:47:29 -080076 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
plars865695b2001-08-27 22:15:12 +000077 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
plars865695b2001-08-27 22:15:12 +000078
plars865695b2001-08-27 22:15:12 +000079 setup();
80
plars865695b2001-08-27 22:15:12 +000081 for (lc = 0; TEST_LOOPING(lc); lc++) {
Garrett Cooper2c282152010-12-16 00:55:50 -080082
Caspar Zhangd59a6592013-03-07 14:59:12 +080083 tst_count = 0;
plars865695b2001-08-27 22:15:12 +000084
subrata_modak4bb656a2009-02-26 12:02:09 +000085 /*
plars865695b2001-08-27 22:15:12 +000086 * Call mmap to map the temporary file 'TEMPFILE'
subrata_modak56207ce2009-03-23 13:35:39 +000087 * with execute access.
plars865695b2001-08-27 22:15:12 +000088 */
subrata_modak56207ce2009-03-23 13:35:39 +000089 errno = 0;
90 addr = mmap(0, page_sz, PROT_EXEC,
91 MAP_FILE | MAP_SHARED, fildes, 0);
plars865695b2001-08-27 22:15:12 +000092
93 /* Check for the return value of mmap() */
robbiewd5c21122002-03-22 16:22:40 +000094 if (addr == MAP_FAILED) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080095 tst_resm(TFAIL | TERRNO, "mmap() failed on %s",
96 TEMPFILE);
plars865695b2001-08-27 22:15:12 +000097 continue;
98 }
Cyril Hrubis5efee332013-06-04 20:14:58 +020099
Cyril Hrubise38b9612014-06-02 17:20:57 +0200100 /*
101 * Read the file contents into the dummy
102 * variable.
103 */
104 if (read(fildes, dummy, page_sz) < 0) {
105 tst_brkm(TFAIL | TERRNO, cleanup,
106 "reading %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000107 }
108
Cyril Hrubise38b9612014-06-02 17:20:57 +0200109 /*
110 * Check whether the mapped memory region
111 * has the file contents.
112 *
113 * with ia64 and PARISC/hppa, this should
114 * generate a SIGSEGV which will be caught below.
115 *
116 */
117
118 if (sigsetjmp(env, 1) == 0) {
119 if (memcmp(dummy, addr, page_sz)) {
120 tst_resm(TFAIL,
121 "mapped memory region "
122 "contains invalid data");
123 } else {
124 tst_resm(TPASS,
125 "mmap() functionality is "
126 "correct");
127 }
128 }
129#if defined(__ia64__) || defined(__hppa__)
130 if (pass) {
131 tst_resm(TPASS, "Got SIGSEGV as expected");
132 } else {
133 tst_resm(TFAIL, "Mapped memory region with NO "
134 "access is accessible");
135 }
136#endif
137
plars865695b2001-08-27 22:15:12 +0000138 /* Clean up things in case we are looping */
139 /* Unmap the mapped memory */
140 if (munmap(addr, page_sz) != 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 tst_brkm(TFAIL | TERRNO, cleanup,
142 "failed to unmap the mmapped pages");
plars865695b2001-08-27 22:15:12 +0000143 }
robbiew30d1bed2003-05-07 15:50:36 +0000144 pass = 0;
plars865695b2001-08-27 22:15:12 +0000145
Garrett Cooper2c282152010-12-16 00:55:50 -0800146 }
plars865695b2001-08-27 22:15:12 +0000147
plars865695b2001-08-27 22:15:12 +0000148 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800149 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800150}
plars865695b2001-08-27 22:15:12 +0000151
Cyril Hrubis5efee332013-06-04 20:14:58 +0200152static void setup(void)
plars865695b2001-08-27 22:15:12 +0000153{
Cyril Hrubis5efee332013-06-04 20:14:58 +0200154 char *tst_buff;
plars865695b2001-08-27 22:15:12 +0000155
robbiew30d1bed2003-05-07 15:50:36 +0000156 tst_sig(NOFORK, sig_handler, cleanup);
plars865695b2001-08-27 22:15:12 +0000157
plars865695b2001-08-27 22:15:12 +0000158 TEST_PAUSE;
159
Cyril Hrubisec22fb22013-06-04 20:37:05 +0200160 page_sz = getpagesize();
plars865695b2001-08-27 22:15:12 +0000161
162 /* Allocate space for the test buffer */
Cyril Hrubis5efee332013-06-04 20:14:58 +0200163 if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800164 tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)");
plars865695b2001-08-27 22:15:12 +0000165 }
166
167 /* Fill the test buffer with the known data */
168 memset(tst_buff, 'A', page_sz);
169
plars865695b2001-08-27 22:15:12 +0000170 tst_tmpdir();
171
172 /* Creat a temporary file used for mapping */
173 if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) {
plars865695b2001-08-27 22:15:12 +0000174 free(tst_buff);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800175 tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
176 TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000177 }
178
179 /* Write test buffer contents into temporary file */
robbiew91361372003-07-09 17:51:16 +0000180 if (write(fildes, tst_buff, page_sz) < page_sz) {
plars865695b2001-08-27 22:15:12 +0000181 free(tst_buff);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800182 tst_brkm(TFAIL | TERRNO, cleanup, "writing to %s failed",
183 TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000184 }
185
186 /* Free the memory allocated for test buffer */
187 free(tst_buff);
188
189 /* Make sure proper permissions set on file */
Garrett Cooper11d51042010-11-22 20:47:29 -0800190 if (fchmod(fildes, 0555) < 0) {
191 tst_brkm(TFAIL, cleanup, "fchmod of %s failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000192 }
193
194 /* Close the temporary file opened for write */
195 if (close(fildes) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800196 tst_brkm(TFAIL | TERRNO, cleanup, "closing %s failed",
197 TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000198 }
199
200 /* Allocate and initialize dummy string of system page size bytes */
Cyril Hrubis5efee332013-06-04 20:14:58 +0200201 if ((dummy = calloc(page_sz, sizeof(char))) == NULL) {
Garrett Cooper11d51042010-11-22 20:47:29 -0800202 tst_brkm(TFAIL, cleanup, "calloc failed (dummy)");
plars865695b2001-08-27 22:15:12 +0000203 }
204
205 /* Open the temporary file again for reading */
206 if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800207 tst_brkm(TFAIL | TERRNO, cleanup,
208 "opening %s read-only failed", TEMPFILE);
plars865695b2001-08-27 22:15:12 +0000209 }
210}
211
212/*
robbiew30d1bed2003-05-07 15:50:36 +0000213 * This function gets executed when the test process receives
214 * the signal SIGSEGV while trying to access the contents of memory which
215 * is not accessible.
216 */
Cyril Hrubis5efee332013-06-04 20:14:58 +0200217static void sig_handler(int sig)
robbiew30d1bed2003-05-07 15:50:36 +0000218{
subrata_modak56207ce2009-03-23 13:35:39 +0000219 if (sig == SIGSEGV) {
220 /* set the global variable and jump back */
221 pass = 1;
222 siglongjmp(env, 1);
Garrett Cooper52626672010-12-20 15:03:21 -0800223 } else
subrata_modak56207ce2009-03-23 13:35:39 +0000224 tst_brkm(TBROK, cleanup, "received an unexpected signal");
robbiew30d1bed2003-05-07 15:50:36 +0000225}
226
Cyril Hrubis5efee332013-06-04 20:14:58 +0200227static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000228{
subrata_modak56207ce2009-03-23 13:35:39 +0000229 close(fildes);
Cyril Hrubis5efee332013-06-04 20:14:58 +0200230 free(dummy);
plars865695b2001-08-27 22:15:12 +0000231 tst_rmdir();
Garrett Cooper52626672010-12-20 15:03:21 -0800232}