1 /* 2 * Copyright (c) 2013 FNST, DAN LI <li.dan (at) cn.fujitsu.com> 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 * Verify error signal SIGBUS. 22 * "Attempted access to a portion of the buffer that does not correspond 23 * to the file." 24 * 25 * Expected Result: 26 * mmap() should succeed returning the address of the mapped region, 27 * and an attempt to access the memory which does not correspond to the file 28 * should rise the signal SIGBUS. 29 */ 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <sys/types.h> 33 #include <errno.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <signal.h> 38 #include <sys/stat.h> 39 #include <sys/mman.h> 40 #include <setjmp.h> 41 42 #include "test.h" 43 44 #define TEMPFILE "mmapfile" 45 46 char *TCID = "mmap13"; 47 int TST_TOTAL = 1; 48 49 static size_t page_sz; 50 static char *addr; 51 static int fildes; 52 static volatile sig_atomic_t pass; 53 static sigjmp_buf env; 54 55 static void setup(void); 56 static void cleanup(void); 57 static void sig_handler(int sig); 58 59 int main(int argc, char *argv[]) 60 { 61 int lc; 62 char *ch; 63 64 tst_parse_opts(argc, argv, NULL, NULL); 65 66 setup(); 67 68 for (lc = 0; TEST_LOOPING(lc); lc++) { 69 tst_count = 0; 70 71 addr = mmap(NULL, page_sz * 2, PROT_READ | PROT_WRITE, 72 MAP_FILE | MAP_SHARED, fildes, 0); 73 74 if (addr == MAP_FAILED) { 75 tst_resm(TFAIL | TERRNO, "mmap() failed on %s", 76 TEMPFILE); 77 continue; 78 } 79 80 if (sigsetjmp(env, 1) == 0) { 81 ch = addr + page_sz + 1; 82 *ch = 0; 83 } 84 85 if (pass) 86 tst_resm(TPASS, "Got SIGBUS " 87 "as expected"); 88 else 89 tst_resm(TFAIL, "Invalid access not " 90 "rise SIGBUS"); 91 92 if (munmap(addr, page_sz * 2) != 0) 93 tst_brkm(TFAIL | TERRNO, cleanup, 94 "failed to unmap the mmapped pages"); 95 96 pass = 0; 97 } 98 99 cleanup(); 100 tst_exit(); 101 } 102 103 static void setup(void) 104 { 105 tst_sig(NOFORK, sig_handler, cleanup); 106 107 TEST_PAUSE; 108 109 page_sz = getpagesize(); 110 111 tst_tmpdir(); 112 113 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0766); 114 if (fildes < 0) 115 tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed", 116 TEMPFILE); 117 118 if (ftruncate(fildes, page_sz / 2) == -1) 119 tst_brkm(TFAIL | TERRNO, cleanup, "ftruncate %s failed", 120 TEMPFILE); 121 } 122 123 /* 124 * This function gets executed when the test process receives 125 * the signal SIGBUS while trying to access the memory which 126 * does not correspond to the file. 127 */ 128 static void sig_handler(int sig) 129 { 130 if (sig == SIGBUS) { 131 pass = 1; 132 siglongjmp(env, 1); 133 } else { 134 tst_brkm(TBROK, cleanup, "received an unexpected signal"); 135 } 136 } 137 138 static void cleanup(void) 139 { 140 close(fildes); 141 tst_rmdir(); 142 } 143