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