blob: 77f0beedca580af59d72004d45dd03b327d41f26 [file] [log] [blame]
DAN LI8329ed82013-06-24 16:03:57 +08001/*
2 * Copyright (c) 2013 FNST, DAN LI <li.dan@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"
DAN LI8329ed82013-06-24 16:03:57 +080043
44#define TEMPFILE "mmapfile"
45
46char *TCID = "mmap13";
47int TST_TOTAL = 1;
48
49static size_t page_sz;
50static char *addr;
51static int fildes;
52static volatile sig_atomic_t pass;
53static sigjmp_buf env;
54
55static void setup(void);
56static void cleanup(void);
57static void sig_handler(int sig);
58
59int main(int argc, char *argv[])
60{
61 int lc;
62 char *ch;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020063 const char *msg;
DAN LI8329ed82013-06-24 16:03:57 +080064
65 msg = parse_opts(argc, argv, NULL, NULL);
66 if (msg != NULL)
67 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
68
69 setup();
70
71 for (lc = 0; TEST_LOOPING(lc); lc++) {
72 tst_count = 0;
73
74 addr = mmap(NULL, page_sz * 2, PROT_READ | PROT_WRITE,
75 MAP_FILE | MAP_SHARED, fildes, 0);
76
77 if (addr == MAP_FAILED) {
78 tst_resm(TFAIL | TERRNO, "mmap() failed on %s",
79 TEMPFILE);
80 continue;
81 }
82
Cyril Hrubise38b9612014-06-02 17:20:57 +020083 if (sigsetjmp(env, 1) == 0) {
84 ch = addr + page_sz + 1;
85 *ch = 0;
DAN LI8329ed82013-06-24 16:03:57 +080086 }
87
Cyril Hrubise38b9612014-06-02 17:20:57 +020088 if (pass)
89 tst_resm(TPASS, "Got SIGBUS "
90 "as expected");
91 else
92 tst_resm(TFAIL, "Invalid access not "
93 "rise SIGBUS");
94
DAN LI8329ed82013-06-24 16:03:57 +080095 if (munmap(addr, page_sz * 2) != 0)
96 tst_brkm(TFAIL | TERRNO, cleanup,
97 "failed to unmap the mmapped pages");
98
99 pass = 0;
100 }
101
102 cleanup();
103 tst_exit();
104}
105
106static void setup(void)
107{
108 tst_sig(NOFORK, sig_handler, cleanup);
109
110 TEST_PAUSE;
111
112 page_sz = getpagesize();
113
114 tst_tmpdir();
115
116 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0766);
117 if (fildes < 0)
118 tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
119 TEMPFILE);
120
121 if (ftruncate(fildes, page_sz / 2) == -1)
122 tst_brkm(TFAIL | TERRNO, cleanup, "ftruncate %s failed",
123 TEMPFILE);
124}
125
126/*
127 * This function gets executed when the test process receives
128 * the signal SIGBUS while trying to access the memory which
129 * does not correspond to the file.
130 */
131static void sig_handler(int sig)
132{
133 if (sig == SIGBUS) {
134 pass = 1;
135 siglongjmp(env, 1);
136 } else {
137 tst_brkm(TBROK, cleanup, "received an unexpected signal");
138 }
139}
140
141static void cleanup(void)
142{
143 close(fildes);
DAN LI8329ed82013-06-24 16:03:57 +0800144 tst_rmdir();
145}