1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 5f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 6f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 7f08c3bdfSopenharmony_ci * (at your option) any later version. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 10f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 15f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 16f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17f08c3bdfSopenharmony_ci */ 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci/* 20f08c3bdfSopenharmony_ci * Test Description: 21f08c3bdfSopenharmony_ci * Call mmap() to map a file creating a mapped region with execute access 22f08c3bdfSopenharmony_ci * under the following conditions - 23f08c3bdfSopenharmony_ci * - The prot parameter is set to PROT_EXE 24f08c3bdfSopenharmony_ci * - The file descriptor is open for read 25f08c3bdfSopenharmony_ci * - The file being mapped has execute permission bit set. 26f08c3bdfSopenharmony_ci * - The minimum file permissions should be 0555. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * The call should succeed to map the file creating mapped memory with the 29f08c3bdfSopenharmony_ci * required attributes. 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * Expected Result: 32f08c3bdfSopenharmony_ci * mmap() should succeed returning the address of the mapped region, 33f08c3bdfSopenharmony_ci * and the mapped region should contain the contents of the mapped file. 34f08c3bdfSopenharmony_ci * but with ia64 and PARISC/hppa, 35f08c3bdfSopenharmony_ci * an attempt to access the contents of the mapped region should give 36f08c3bdfSopenharmony_ci * rise to the signal SIGSEGV. 37f08c3bdfSopenharmony_ci * 38f08c3bdfSopenharmony_ci * HISTORY 39f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 40f08c3bdfSopenharmony_ci */ 41f08c3bdfSopenharmony_ci#include <stdio.h> 42f08c3bdfSopenharmony_ci#include <stdlib.h> 43f08c3bdfSopenharmony_ci#include <sys/types.h> 44f08c3bdfSopenharmony_ci#include <errno.h> 45f08c3bdfSopenharmony_ci#include <unistd.h> 46f08c3bdfSopenharmony_ci#include <fcntl.h> 47f08c3bdfSopenharmony_ci#include <string.h> 48f08c3bdfSopenharmony_ci#include <signal.h> 49f08c3bdfSopenharmony_ci#include <sys/stat.h> 50f08c3bdfSopenharmony_ci#include <sys/mman.h> 51f08c3bdfSopenharmony_ci#include <setjmp.h> 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci#include "test.h" 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci#define TEMPFILE "mmapfile" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cichar *TCID = "mmap03"; 58f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic size_t page_sz; 61f08c3bdfSopenharmony_cistatic char *addr; 62f08c3bdfSopenharmony_cistatic char *dummy; 63f08c3bdfSopenharmony_cistatic int fildes; 64f08c3bdfSopenharmony_cistatic volatile int pass = 0; 65f08c3bdfSopenharmony_cistatic sigjmp_buf env; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_cistatic void setup(void); 68f08c3bdfSopenharmony_cistatic void cleanup(void); 69f08c3bdfSopenharmony_cistatic void sig_handler(int sig); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ciint main(int ac, char **av) 72f08c3bdfSopenharmony_ci{ 73f08c3bdfSopenharmony_ci int lc; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci setup(); 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci tst_count = 0; 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci /* 84f08c3bdfSopenharmony_ci * Call mmap to map the temporary file 'TEMPFILE' 85f08c3bdfSopenharmony_ci * with execute access. 86f08c3bdfSopenharmony_ci */ 87f08c3bdfSopenharmony_ci errno = 0; 88f08c3bdfSopenharmony_ci addr = mmap(0, page_sz, PROT_EXEC, 89f08c3bdfSopenharmony_ci MAP_FILE | MAP_SHARED, fildes, 0); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci /* Check for the return value of mmap() */ 92f08c3bdfSopenharmony_ci if (addr == MAP_FAILED) { 93f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, "mmap() failed on %s", 94f08c3bdfSopenharmony_ci TEMPFILE); 95f08c3bdfSopenharmony_ci continue; 96f08c3bdfSopenharmony_ci } 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci /* 99f08c3bdfSopenharmony_ci * Read the file contents into the dummy 100f08c3bdfSopenharmony_ci * variable. 101f08c3bdfSopenharmony_ci */ 102f08c3bdfSopenharmony_ci if (read(fildes, dummy, page_sz) < 0) { 103f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, 104f08c3bdfSopenharmony_ci "reading %s failed", TEMPFILE); 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci /* 108f08c3bdfSopenharmony_ci * Check whether the mapped memory region 109f08c3bdfSopenharmony_ci * has the file contents. 110f08c3bdfSopenharmony_ci * 111f08c3bdfSopenharmony_ci * with ia64 and PARISC/hppa, this should 112f08c3bdfSopenharmony_ci * generate a SIGSEGV which will be caught below. 113f08c3bdfSopenharmony_ci * 114f08c3bdfSopenharmony_ci */ 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (sigsetjmp(env, 1) == 0) { 117f08c3bdfSopenharmony_ci if (memcmp(dummy, addr, page_sz)) { 118f08c3bdfSopenharmony_ci tst_resm(TFAIL, 119f08c3bdfSopenharmony_ci "mapped memory region " 120f08c3bdfSopenharmony_ci "contains invalid data"); 121f08c3bdfSopenharmony_ci } else { 122f08c3bdfSopenharmony_ci tst_resm(TPASS, 123f08c3bdfSopenharmony_ci "mmap() functionality is " 124f08c3bdfSopenharmony_ci "correct"); 125f08c3bdfSopenharmony_ci } 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci#if defined(__ia64__) || defined(__hppa__) || defined(__mips__) 128f08c3bdfSopenharmony_ci if (pass) { 129f08c3bdfSopenharmony_ci tst_resm(TPASS, "Got SIGSEGV as expected"); 130f08c3bdfSopenharmony_ci } else { 131f08c3bdfSopenharmony_ci tst_resm(TFAIL, "Mapped memory region with NO " 132f08c3bdfSopenharmony_ci "access is accessible"); 133f08c3bdfSopenharmony_ci } 134f08c3bdfSopenharmony_ci#endif 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci /* Clean up things in case we are looping */ 137f08c3bdfSopenharmony_ci /* Unmap the mapped memory */ 138f08c3bdfSopenharmony_ci if (munmap(addr, page_sz) != 0) { 139f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, 140f08c3bdfSopenharmony_ci "failed to unmap the mmapped pages"); 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci pass = 0; 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci cleanup(); 147f08c3bdfSopenharmony_ci tst_exit(); 148f08c3bdfSopenharmony_ci} 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_cistatic void setup(void) 151f08c3bdfSopenharmony_ci{ 152f08c3bdfSopenharmony_ci char *tst_buff; 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci tst_sig(NOFORK, sig_handler, cleanup); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci TEST_PAUSE; 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci page_sz = getpagesize(); 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci /* Allocate space for the test buffer */ 161f08c3bdfSopenharmony_ci if ((tst_buff = calloc(page_sz, sizeof(char))) == NULL) { 162f08c3bdfSopenharmony_ci tst_brkm(TFAIL, NULL, "calloc failed (tst_buff)"); 163f08c3bdfSopenharmony_ci } 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci /* Fill the test buffer with the known data */ 166f08c3bdfSopenharmony_ci memset(tst_buff, 'A', page_sz); 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci tst_tmpdir(); 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci /* Creat a temporary file used for mapping */ 171f08c3bdfSopenharmony_ci if ((fildes = open(TEMPFILE, O_WRONLY | O_CREAT, 0666)) < 0) { 172f08c3bdfSopenharmony_ci free(tst_buff); 173f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed", 174f08c3bdfSopenharmony_ci TEMPFILE); 175f08c3bdfSopenharmony_ci } 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci /* Write test buffer contents into temporary file */ 178f08c3bdfSopenharmony_ci if (write(fildes, tst_buff, page_sz) < (long)page_sz) { 179f08c3bdfSopenharmony_ci free(tst_buff); 180f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, "writing to %s failed", 181f08c3bdfSopenharmony_ci TEMPFILE); 182f08c3bdfSopenharmony_ci } 183f08c3bdfSopenharmony_ci 184f08c3bdfSopenharmony_ci /* Free the memory allocated for test buffer */ 185f08c3bdfSopenharmony_ci free(tst_buff); 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci /* Make sure proper permissions set on file */ 188f08c3bdfSopenharmony_ci if (fchmod(fildes, 0555) < 0) { 189f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "fchmod of %s failed", TEMPFILE); 190f08c3bdfSopenharmony_ci } 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci /* Close the temporary file opened for write */ 193f08c3bdfSopenharmony_ci if (close(fildes) < 0) { 194f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, "closing %s failed", 195f08c3bdfSopenharmony_ci TEMPFILE); 196f08c3bdfSopenharmony_ci } 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci /* Allocate and initialize dummy string of system page size bytes */ 199f08c3bdfSopenharmony_ci if ((dummy = calloc(page_sz, sizeof(char))) == NULL) { 200f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "calloc failed (dummy)"); 201f08c3bdfSopenharmony_ci } 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci /* Open the temporary file again for reading */ 204f08c3bdfSopenharmony_ci if ((fildes = open(TEMPFILE, O_RDONLY)) < 0) { 205f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, 206f08c3bdfSopenharmony_ci "opening %s read-only failed", TEMPFILE); 207f08c3bdfSopenharmony_ci } 208f08c3bdfSopenharmony_ci} 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci/* 211f08c3bdfSopenharmony_ci * This function gets executed when the test process receives 212f08c3bdfSopenharmony_ci * the signal SIGSEGV while trying to access the contents of memory which 213f08c3bdfSopenharmony_ci * is not accessible. 214f08c3bdfSopenharmony_ci */ 215f08c3bdfSopenharmony_cistatic void sig_handler(int sig) 216f08c3bdfSopenharmony_ci{ 217f08c3bdfSopenharmony_ci if (sig == SIGSEGV) { 218f08c3bdfSopenharmony_ci /* set the global variable and jump back */ 219f08c3bdfSopenharmony_ci pass = 1; 220f08c3bdfSopenharmony_ci siglongjmp(env, 1); 221f08c3bdfSopenharmony_ci } else 222f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "received an unexpected signal"); 223f08c3bdfSopenharmony_ci} 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_cistatic void cleanup(void) 226f08c3bdfSopenharmony_ci{ 227f08c3bdfSopenharmony_ci close(fildes); 228f08c3bdfSopenharmony_ci free(dummy); 229f08c3bdfSopenharmony_ci tst_rmdir(); 230f08c3bdfSopenharmony_ci} 231