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