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