xref: /freebsd/lib/libc/tests/secure/fortify_stdlib_test.c (revision d0b7445904f592bf379d64932fb6f1fdc29c4aa7)
1 /* @generated by `generate-fortify-tests.lua "stdlib"` */
2 
3 #define	_FORTIFY_SOURCE	2
4 #define	TMPFILE_SIZE	(1024 * 32)
5 
6 #include <sys/param.h>
7 #include <sys/resource.h>
8 #include <sys/time.h>
9 #include <sys/wait.h>
10 #include <dirent.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <limits.h>
14 #include <poll.h>
15 #include <signal.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <strings.h>
20 #include <sysexits.h>
21 #include <unistd.h>
22 #include <atf-c.h>
23 
24 static FILE * __unused
25 new_fp(size_t __len)
26 {
27 	static char fpbuf[LINE_MAX];
28 	FILE *fp;
29 
30 	ATF_REQUIRE(__len <= sizeof(fpbuf));
31 
32 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
33 	fpbuf[sizeof(fpbuf) - 1] = '\0';
34 
35 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
36 	ATF_REQUIRE(fp != NULL);
37 
38 	return (fp);
39 }
40 
41 /*
42  * Create a new symlink to use for readlink(2) style tests, we'll just use a
43  * random target name to have something interesting to look at.
44  */
45 static const char * __unused
46 new_symlink(size_t __len)
47 {
48 	static const char linkname[] = "link";
49 	char target[MAXNAMLEN];
50 	int error;
51 
52 	ATF_REQUIRE(__len <= sizeof(target));
53 
54 	arc4random_buf(target, sizeof(target));
55 
56 	error = unlink(linkname);
57 	ATF_REQUIRE(error == 0 || errno == ENOENT);
58 
59 	error = symlink(target, linkname);
60 	ATF_REQUIRE(error == 0);
61 
62 	return (linkname);
63 }
64 
65 /*
66  * Constructs a tmpfile that we can use for testing read(2) and friends.
67  */
68 static int __unused
69 new_tmpfile(void)
70 {
71 	char buf[1024];
72 	ssize_t rv;
73 	size_t written;
74 	int fd;
75 
76 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
77 	ATF_REQUIRE(fd >= 0);
78 
79 	written = 0;
80 	while (written < TMPFILE_SIZE) {
81 		rv = write(fd, buf, sizeof(buf));
82 		ATF_REQUIRE(rv > 0);
83 
84 		written += rv;
85 	}
86 
87 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
88 	return (fd);
89 }
90 
91 static void
92 disable_coredumps(void)
93 {
94 	struct rlimit rl = { 0 };
95 
96 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
97 		_exit(EX_OSERR);
98 }
99 
100 /*
101  * Replaces stdin with a file that we can actually read from, for tests where
102  * we want a FILE * or fd that we can get data from.
103  */
104 static void __unused
105 replace_stdin(void)
106 {
107 	int fd;
108 
109 	fd = new_tmpfile();
110 
111 	(void)dup2(fd, STDIN_FILENO);
112 	if (fd != STDIN_FILENO)
113 		close(fd);
114 }
115 
116 ATF_TC_WITHOUT_HEAD(arc4random_buf_before_end);
117 ATF_TC_BODY(arc4random_buf_before_end, tc)
118 {
119 #define BUF &__stack.__buf
120 	struct {
121 		uint8_t padding_l;
122 		unsigned char __buf[42];
123 		uint8_t padding_r;
124 	} __stack;
125 	const size_t __bufsz __unused = sizeof(__stack.__buf);
126 	const size_t __len = 42 - 1;
127 	const size_t __idx __unused = __len - 1;
128 
129 	arc4random_buf(__stack.__buf, __len);
130 #undef BUF
131 
132 }
133 
134 ATF_TC_WITHOUT_HEAD(arc4random_buf_end);
135 ATF_TC_BODY(arc4random_buf_end, tc)
136 {
137 #define BUF &__stack.__buf
138 	struct {
139 		uint8_t padding_l;
140 		unsigned char __buf[42];
141 		uint8_t padding_r;
142 	} __stack;
143 	const size_t __bufsz __unused = sizeof(__stack.__buf);
144 	const size_t __len = 42;
145 	const size_t __idx __unused = __len - 1;
146 
147 	arc4random_buf(__stack.__buf, __len);
148 #undef BUF
149 
150 }
151 
152 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_before_end);
153 ATF_TC_BODY(arc4random_buf_heap_before_end, tc)
154 {
155 #define BUF __stack.__buf
156 	struct {
157 		uint8_t padding_l;
158 		unsigned char * __buf;
159 		uint8_t padding_r;
160 	} __stack;
161 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
162 	const size_t __len = 42 - 1;
163 	const size_t __idx __unused = __len - 1;
164 
165 	__stack.__buf = malloc(__bufsz);
166 
167 	arc4random_buf(__stack.__buf, __len);
168 #undef BUF
169 
170 }
171 
172 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_end);
173 ATF_TC_BODY(arc4random_buf_heap_end, tc)
174 {
175 #define BUF __stack.__buf
176 	struct {
177 		uint8_t padding_l;
178 		unsigned char * __buf;
179 		uint8_t padding_r;
180 	} __stack;
181 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
182 	const size_t __len = 42;
183 	const size_t __idx __unused = __len - 1;
184 
185 	__stack.__buf = malloc(__bufsz);
186 
187 	arc4random_buf(__stack.__buf, __len);
188 #undef BUF
189 
190 }
191 
192 ATF_TC_WITHOUT_HEAD(arc4random_buf_heap_after_end);
193 ATF_TC_BODY(arc4random_buf_heap_after_end, tc)
194 {
195 #define BUF __stack.__buf
196 	struct {
197 		uint8_t padding_l;
198 		unsigned char * __buf;
199 		uint8_t padding_r;
200 	} __stack;
201 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
202 	const size_t __len = 42 + 1;
203 	const size_t __idx __unused = __len - 1;
204 	pid_t __child;
205 	int __status;
206 
207 	__child = fork();
208 	ATF_REQUIRE(__child >= 0);
209 	if (__child > 0)
210 		goto monitor;
211 
212 	/* Child */
213 	disable_coredumps();
214 	__stack.__buf = malloc(__bufsz);
215 
216 	arc4random_buf(__stack.__buf, __len);
217 	_exit(EX_SOFTWARE);	/* Should have aborted. */
218 
219 monitor:
220 	while (waitpid(__child, &__status, 0) != __child) {
221 		ATF_REQUIRE_EQ(EINTR, errno);
222 	}
223 
224 	if (!WIFSIGNALED(__status)) {
225 		switch (WEXITSTATUS(__status)) {
226 		case EX_SOFTWARE:
227 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
228 			break;
229 		case EX_OSERR:
230 			atf_tc_fail("setrlimit(2) failed");
231 			break;
232 		default:
233 			atf_tc_fail("child exited with status %d",
234 			    WEXITSTATUS(__status));
235 		}
236 	} else {
237 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
238 	}
239 #undef BUF
240 
241 }
242 
243 ATF_TC_WITHOUT_HEAD(realpath_before_end);
244 ATF_TC_BODY(realpath_before_end, tc)
245 {
246 #define BUF &__stack.__buf
247 	struct {
248 		uint8_t padding_l;
249 		unsigned char __buf[PATH_MAX + 1];
250 		uint8_t padding_r;
251 	} __stack;
252 	const size_t __bufsz __unused = sizeof(__stack.__buf);
253 	const size_t __len = PATH_MAX + 1;
254 	const size_t __idx __unused = __len - 1;
255 
256 	realpath(".", __stack.__buf);
257 #undef BUF
258 
259 }
260 
261 ATF_TC_WITHOUT_HEAD(realpath_end);
262 ATF_TC_BODY(realpath_end, tc)
263 {
264 #define BUF &__stack.__buf
265 	struct {
266 		uint8_t padding_l;
267 		unsigned char __buf[PATH_MAX];
268 		uint8_t padding_r;
269 	} __stack;
270 	const size_t __bufsz __unused = sizeof(__stack.__buf);
271 	const size_t __len = PATH_MAX;
272 	const size_t __idx __unused = __len - 1;
273 
274 	realpath(".", __stack.__buf);
275 #undef BUF
276 
277 }
278 
279 ATF_TC_WITHOUT_HEAD(realpath_heap_before_end);
280 ATF_TC_BODY(realpath_heap_before_end, tc)
281 {
282 #define BUF __stack.__buf
283 	struct {
284 		uint8_t padding_l;
285 		unsigned char * __buf;
286 		uint8_t padding_r;
287 	} __stack;
288 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX + 1);
289 	const size_t __len = PATH_MAX + 1;
290 	const size_t __idx __unused = __len - 1;
291 
292 	__stack.__buf = malloc(__bufsz);
293 
294 	realpath(".", __stack.__buf);
295 #undef BUF
296 
297 }
298 
299 ATF_TC_WITHOUT_HEAD(realpath_heap_end);
300 ATF_TC_BODY(realpath_heap_end, tc)
301 {
302 #define BUF __stack.__buf
303 	struct {
304 		uint8_t padding_l;
305 		unsigned char * __buf;
306 		uint8_t padding_r;
307 	} __stack;
308 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX);
309 	const size_t __len = PATH_MAX;
310 	const size_t __idx __unused = __len - 1;
311 
312 	__stack.__buf = malloc(__bufsz);
313 
314 	realpath(".", __stack.__buf);
315 #undef BUF
316 
317 }
318 
319 ATF_TC_WITHOUT_HEAD(realpath_heap_after_end);
320 ATF_TC_BODY(realpath_heap_after_end, tc)
321 {
322 #define BUF __stack.__buf
323 	struct {
324 		uint8_t padding_l;
325 		unsigned char * __buf;
326 		uint8_t padding_r;
327 	} __stack;
328 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (PATH_MAX - 1);
329 	const size_t __len = PATH_MAX - 1;
330 	const size_t __idx __unused = __len - 1;
331 	pid_t __child;
332 	int __status;
333 
334 	__child = fork();
335 	ATF_REQUIRE(__child >= 0);
336 	if (__child > 0)
337 		goto monitor;
338 
339 	/* Child */
340 	disable_coredumps();
341 	__stack.__buf = malloc(__bufsz);
342 
343 	realpath(".", __stack.__buf);
344 	_exit(EX_SOFTWARE);	/* Should have aborted. */
345 
346 monitor:
347 	while (waitpid(__child, &__status, 0) != __child) {
348 		ATF_REQUIRE_EQ(EINTR, errno);
349 	}
350 
351 	if (!WIFSIGNALED(__status)) {
352 		switch (WEXITSTATUS(__status)) {
353 		case EX_SOFTWARE:
354 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
355 			break;
356 		case EX_OSERR:
357 			atf_tc_fail("setrlimit(2) failed");
358 			break;
359 		default:
360 			atf_tc_fail("child exited with status %d",
361 			    WEXITSTATUS(__status));
362 		}
363 	} else {
364 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
365 	}
366 #undef BUF
367 
368 }
369 
370 ATF_TP_ADD_TCS(tp)
371 {
372 	ATF_TP_ADD_TC(tp, arc4random_buf_before_end);
373 	ATF_TP_ADD_TC(tp, arc4random_buf_end);
374 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_before_end);
375 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_end);
376 	ATF_TP_ADD_TC(tp, arc4random_buf_heap_after_end);
377 	ATF_TP_ADD_TC(tp, realpath_before_end);
378 	ATF_TP_ADD_TC(tp, realpath_end);
379 	ATF_TP_ADD_TC(tp, realpath_heap_before_end);
380 	ATF_TP_ADD_TC(tp, realpath_heap_end);
381 	ATF_TP_ADD_TC(tp, realpath_heap_after_end);
382 	return (atf_no_error());
383 }
384