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