1 /* IBM Corporation */
2 /* 01/02/2003 Port to LTP avenkat@us.ibm.com */
3 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
4
5 /*
6 * Copyright (c) International Business Machines Corp., 2003
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /* uiomove_phys_fail:
25 * Test a copyout/copyin failure in the kernel primitive uiomove_phys by
26 * reading into or writing from a mmaped regular file which lacks the
27 * needed permissions.
28 */
29
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <stdio.h>
37
38 extern time_t time(time_t *);
39 extern char *ctime(const time_t *);
40 extern void exit(int);
41
42 #define ERROR(M) (void)fprintf(stderr, "%s: errno = %d; " M "\n", \
43 argv[0], errno)
44 #define CLEANERROR(M) (void)unlink(tmpname); ERROR(M)
45 #define CATCH_SIG(SIG) \
46 if (sigaction(SIG, &sa, 0) == -1) { \
47 ERROR("couldn't catch signal " #SIG); \
48 exit(1); \
49 }
50
51 static char tmpname[] = "fileXXXXXX";
52 static int fd;
53 /***** LTP Port *****/
54 #include "test.h"
55 #define FAILED 0
56 #define PASSED 1
57
58 int local_flag = PASSED;
59 char *TCID = "mmapstress02"; //uiomove_phys_fail
60 FILE *temp;
61 int TST_TOTAL = 1;
62
63 int anyfail();
64 void ok_exit();
65 /***** ** ** *****/
66
67 /*ARGSUSED*/ static
cleanup(int sig)68 void cleanup(int sig)
69 {
70 /*
71 * Don't check error codes - we could be signaled before the file is
72 * created.
73 */
74 (void)close(fd);
75 (void)unlink(tmpname);
76 tst_rmdir();
77 tst_exit();
78 }
79
main(int argc,char * argv[])80 int main(int argc, char *argv[])
81 {
82 caddr_t mmapaddr;
83 size_t pagesize = sysconf(_SC_PAGE_SIZE);
84 time_t t;
85 int i;
86 struct sigaction sa;
87
88 tst_tmpdir();
89 if (!argc) {
90 (void)fprintf(stderr, "argc == 0\n");
91 return 1;
92 }
93 if (argc != 1) {
94 (void)fprintf(stderr, "usage: %s\n", argv[0]);
95 return 1;
96 }
97 (void)time(&t);
98 if ((fd = mkstemp(tmpname)) == -1) {
99 ERROR("mkstemp failed");
100 anyfail();
101 }
102 sa.sa_handler = cleanup;
103 sa.sa_flags = 0;
104 if (sigemptyset(&sa.sa_mask)) {
105 ERROR("sigemptyset failed");
106 anyfail();
107 }
108 CATCH_SIG(SIGINT);
109 CATCH_SIG(SIGQUIT);
110 CATCH_SIG(SIGTERM);
111 if (sbrk(2 * pagesize - ((ulong) sbrk(0) & (pagesize - 1))) ==
112 (char *)-1) {
113 CLEANERROR("couldn't round up brk");
114 anyfail();
115 }
116 if ((mmapaddr = sbrk(0)) == (caddr_t) - 1) {
117 CLEANERROR("couldn't find top of brk");
118 anyfail();
119 }
120 /* Write a page of garbage into the file, so we can mmap it without
121 * asking for PROT_WRITE.
122 */
123 for (i = pagesize; i; i--)
124 *(mmapaddr - i) = 'a';
125 if (write(fd, (char *)mmapaddr - pagesize, pagesize) != pagesize) {
126 CLEANERROR("write failed");
127 anyfail();
128 }
129 if (mmap(mmapaddr, pagesize, PROT_NONE,
130 MAP_FIXED | MAP_PRIVATE | MAP_FILE, fd, 0) != mmapaddr) {
131 CLEANERROR("couldn't mmap file");
132 anyfail();
133 }
134 /*
135 * Since the file is mmapped, mmreg_new and uiomove_phys handle all
136 * I/O
137 */
138 if (lseek(fd, 0, SEEK_SET) != 0) {
139 CLEANERROR("lseek failed");
140 anyfail();
141 }
142 if (read(fd, (char *)mmapaddr, pagesize) != -1) {
143 CLEANERROR("read succeded");
144 anyfail();
145 }
146 if (errno != EFAULT) {
147 CLEANERROR("read didn't set errno = EFAULT");
148 anyfail();
149 }
150 if (write(fd, (char *)mmapaddr, pagesize) != -1) {
151 CLEANERROR("write succeded");
152 anyfail();
153 }
154 if (errno != EFAULT) {
155 CLEANERROR("write didn't set errno = EFAULT");
156 anyfail();
157 }
158 if (close(fd) == -1) {
159 CLEANERROR("close failed");
160 anyfail();
161 }
162 if (munmap(mmapaddr, pagesize) == -1) {
163 CLEANERROR("munmap failed");
164 anyfail();
165 }
166 if (unlink(tmpname) == -1) {
167 ERROR("unlink failed");
168 anyfail();
169 }
170 (void)time(&t);
171 // (void)printf("%s: Finished %s", argv[0], ctime(&t));
172 ok_exit(); /* LTP Port */
173 tst_exit();
174 }
175
176 /***** LTP Port *****/
ok_exit(void)177 void ok_exit(void)
178 {
179 tst_resm(TPASS, "Test passed\n");
180 tst_rmdir();
181 tst_exit();
182 }
183
anyfail(void)184 int anyfail(void)
185 {
186 tst_brkm(TFAIL, tst_rmdir, "Test failed");
187 }
188
189 /***** ** ** *****/
190