xref: /freebsd/lib/libc/tests/secure/fortify_signal_test.c (revision b0334450aa527ccbac7a3c37d1ba75ef96c7be91)
1*b0334450SRicardo Branco /* @generated by `generate-fortify-tests.lua "signal"` */
2*b0334450SRicardo Branco 
3*b0334450SRicardo Branco #define	_FORTIFY_SOURCE	2
4*b0334450SRicardo Branco #define	TMPFILE_SIZE	(1024 * 32)
5*b0334450SRicardo Branco 
6*b0334450SRicardo Branco #include <sys/param.h>
7*b0334450SRicardo Branco #include <sys/jail.h>
8*b0334450SRicardo Branco #include <sys/random.h>
9*b0334450SRicardo Branco #include <sys/resource.h>
10*b0334450SRicardo Branco #include <sys/select.h>
11*b0334450SRicardo Branco #include <sys/socket.h>
12*b0334450SRicardo Branco #include <sys/time.h>
13*b0334450SRicardo Branco #include <sys/uio.h>
14*b0334450SRicardo Branco #include <sys/wait.h>
15*b0334450SRicardo Branco #include <dirent.h>
16*b0334450SRicardo Branco #include <errno.h>
17*b0334450SRicardo Branco #include <fcntl.h>
18*b0334450SRicardo Branco #include <limits.h>
19*b0334450SRicardo Branco #include <poll.h>
20*b0334450SRicardo Branco #include <signal.h>
21*b0334450SRicardo Branco #include <stdio.h>
22*b0334450SRicardo Branco #include <stdlib.h>
23*b0334450SRicardo Branco #include <string.h>
24*b0334450SRicardo Branco #include <strings.h>
25*b0334450SRicardo Branco #include <sysexits.h>
26*b0334450SRicardo Branco #include <unistd.h>
27*b0334450SRicardo Branco #include <wchar.h>
28*b0334450SRicardo Branco #include <atf-c.h>
29*b0334450SRicardo Branco 
30*b0334450SRicardo Branco static FILE * __unused
new_fp(size_t __len)31*b0334450SRicardo Branco new_fp(size_t __len)
32*b0334450SRicardo Branco {
33*b0334450SRicardo Branco 	static char fpbuf[LINE_MAX];
34*b0334450SRicardo Branco 	FILE *fp;
35*b0334450SRicardo Branco 
36*b0334450SRicardo Branco 	ATF_REQUIRE(__len <= sizeof(fpbuf));
37*b0334450SRicardo Branco 
38*b0334450SRicardo Branco 	memset(fpbuf, 'A', sizeof(fpbuf) - 1);
39*b0334450SRicardo Branco 	fpbuf[sizeof(fpbuf) - 1] = '\0';
40*b0334450SRicardo Branco 
41*b0334450SRicardo Branco 	fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
42*b0334450SRicardo Branco 	ATF_REQUIRE(fp != NULL);
43*b0334450SRicardo Branco 
44*b0334450SRicardo Branco 	return (fp);
45*b0334450SRicardo Branco }
46*b0334450SRicardo Branco 
47*b0334450SRicardo Branco /*
48*b0334450SRicardo Branco  * Create a new symlink to use for readlink(2) style tests, we'll just use a
49*b0334450SRicardo Branco  * random target name to have something interesting to look at.
50*b0334450SRicardo Branco  */
51*b0334450SRicardo Branco static const char * __unused
new_symlink(size_t __len)52*b0334450SRicardo Branco new_symlink(size_t __len)
53*b0334450SRicardo Branco {
54*b0334450SRicardo Branco 	static const char linkname[] = "link";
55*b0334450SRicardo Branco 	char target[MAXNAMLEN];
56*b0334450SRicardo Branco 	int error;
57*b0334450SRicardo Branco 
58*b0334450SRicardo Branco 	ATF_REQUIRE(__len <= sizeof(target));
59*b0334450SRicardo Branco 
60*b0334450SRicardo Branco 	arc4random_buf(target, sizeof(target));
61*b0334450SRicardo Branco 
62*b0334450SRicardo Branco 	error = unlink(linkname);
63*b0334450SRicardo Branco 	ATF_REQUIRE(error == 0 || errno == ENOENT);
64*b0334450SRicardo Branco 
65*b0334450SRicardo Branco 	error = symlink(target, linkname);
66*b0334450SRicardo Branco 	ATF_REQUIRE(error == 0);
67*b0334450SRicardo Branco 
68*b0334450SRicardo Branco 	return (linkname);
69*b0334450SRicardo Branco }
70*b0334450SRicardo Branco 
71*b0334450SRicardo Branco /*
72*b0334450SRicardo Branco  * For our purposes, first descriptor will be the reader; we'll send both
73*b0334450SRicardo Branco  * raw data and a control message over it so that the result can be used for
74*b0334450SRicardo Branco  * any of our recv*() tests.
75*b0334450SRicardo Branco  */
76*b0334450SRicardo Branco static void __unused
new_socket(int sock[2])77*b0334450SRicardo Branco new_socket(int sock[2])
78*b0334450SRicardo Branco {
79*b0334450SRicardo Branco 	unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
80*b0334450SRicardo Branco 	static char sockbuf[256];
81*b0334450SRicardo Branco 	ssize_t rv;
82*b0334450SRicardo Branco 	size_t total = 0;
83*b0334450SRicardo Branco 	struct msghdr hdr = { 0 };
84*b0334450SRicardo Branco 	struct cmsghdr *cmsg;
85*b0334450SRicardo Branco 	int error, fd;
86*b0334450SRicardo Branco 
87*b0334450SRicardo Branco 	error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
88*b0334450SRicardo Branco 	ATF_REQUIRE(error == 0);
89*b0334450SRicardo Branco 
90*b0334450SRicardo Branco 	while (total != sizeof(sockbuf)) {
91*b0334450SRicardo Branco 		rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
92*b0334450SRicardo Branco 
93*b0334450SRicardo Branco 		ATF_REQUIRE_MSG(rv > 0,
94*b0334450SRicardo Branco 		    "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
95*b0334450SRicardo Branco 		    rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
96*b0334450SRicardo Branco 		ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
97*b0334450SRicardo Branco 		    "%zd exceeds total %zu", rv, sizeof(sockbuf));
98*b0334450SRicardo Branco 		total += rv;
99*b0334450SRicardo Branco 	}
100*b0334450SRicardo Branco 
101*b0334450SRicardo Branco 	hdr.msg_control = ctrl;
102*b0334450SRicardo Branco 	hdr.msg_controllen = sizeof(ctrl);
103*b0334450SRicardo Branco 
104*b0334450SRicardo Branco 	cmsg = CMSG_FIRSTHDR(&hdr);
105*b0334450SRicardo Branco 	cmsg->cmsg_level = SOL_SOCKET;
106*b0334450SRicardo Branco 	cmsg->cmsg_type = SCM_RIGHTS;
107*b0334450SRicardo Branco 	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
108*b0334450SRicardo Branco 	fd = STDIN_FILENO;
109*b0334450SRicardo Branco 	memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
110*b0334450SRicardo Branco 
111*b0334450SRicardo Branco 	error = sendmsg(sock[1], &hdr, 0);
112*b0334450SRicardo Branco 	ATF_REQUIRE(error != -1);
113*b0334450SRicardo Branco }
114*b0334450SRicardo Branco 
115*b0334450SRicardo Branco /*
116*b0334450SRicardo Branco  * Constructs a tmpfile that we can use for testing read(2) and friends.
117*b0334450SRicardo Branco  */
118*b0334450SRicardo Branco static int __unused
new_tmpfile(void)119*b0334450SRicardo Branco new_tmpfile(void)
120*b0334450SRicardo Branco {
121*b0334450SRicardo Branco 	char buf[1024];
122*b0334450SRicardo Branco 	ssize_t rv;
123*b0334450SRicardo Branco 	size_t written;
124*b0334450SRicardo Branco 	int fd;
125*b0334450SRicardo Branco 
126*b0334450SRicardo Branco 	fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
127*b0334450SRicardo Branco 	ATF_REQUIRE(fd >= 0);
128*b0334450SRicardo Branco 
129*b0334450SRicardo Branco 	written = 0;
130*b0334450SRicardo Branco 	while (written < TMPFILE_SIZE) {
131*b0334450SRicardo Branco 		rv = write(fd, buf, sizeof(buf));
132*b0334450SRicardo Branco 		ATF_REQUIRE(rv > 0);
133*b0334450SRicardo Branco 
134*b0334450SRicardo Branco 		written += rv;
135*b0334450SRicardo Branco 	}
136*b0334450SRicardo Branco 
137*b0334450SRicardo Branco 	ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET));
138*b0334450SRicardo Branco 	return (fd);
139*b0334450SRicardo Branco }
140*b0334450SRicardo Branco 
141*b0334450SRicardo Branco static void
disable_coredumps(void)142*b0334450SRicardo Branco disable_coredumps(void)
143*b0334450SRicardo Branco {
144*b0334450SRicardo Branco 	struct rlimit rl = { 0 };
145*b0334450SRicardo Branco 
146*b0334450SRicardo Branco 	if (setrlimit(RLIMIT_CORE, &rl) == -1)
147*b0334450SRicardo Branco 		_exit(EX_OSERR);
148*b0334450SRicardo Branco }
149*b0334450SRicardo Branco 
150*b0334450SRicardo Branco /*
151*b0334450SRicardo Branco  * Replaces stdin with a file that we can actually read from, for tests where
152*b0334450SRicardo Branco  * we want a FILE * or fd that we can get data from.
153*b0334450SRicardo Branco  */
154*b0334450SRicardo Branco static void __unused
replace_stdin(void)155*b0334450SRicardo Branco replace_stdin(void)
156*b0334450SRicardo Branco {
157*b0334450SRicardo Branco 	int fd;
158*b0334450SRicardo Branco 
159*b0334450SRicardo Branco 	fd = new_tmpfile();
160*b0334450SRicardo Branco 
161*b0334450SRicardo Branco 	(void)dup2(fd, STDIN_FILENO);
162*b0334450SRicardo Branco 	if (fd != STDIN_FILENO)
163*b0334450SRicardo Branco 		close(fd);
164*b0334450SRicardo Branco }
165*b0334450SRicardo Branco 
166*b0334450SRicardo Branco ATF_TC(sig2str_before_end);
ATF_TC_HEAD(sig2str_before_end,tc)167*b0334450SRicardo Branco ATF_TC_HEAD(sig2str_before_end, tc)
168*b0334450SRicardo Branco {
169*b0334450SRicardo Branco }
ATF_TC_BODY(sig2str_before_end,tc)170*b0334450SRicardo Branco ATF_TC_BODY(sig2str_before_end, tc)
171*b0334450SRicardo Branco {
172*b0334450SRicardo Branco #define BUF &__stack.__buf
173*b0334450SRicardo Branco 	struct {
174*b0334450SRicardo Branco 		uint8_t padding_l;
175*b0334450SRicardo Branco 		unsigned char __buf[SIG2STR_MAX + 1];
176*b0334450SRicardo Branco 		uint8_t padding_r;
177*b0334450SRicardo Branco 	} __stack;
178*b0334450SRicardo Branco 	const size_t __bufsz __unused = sizeof(__stack.__buf);
179*b0334450SRicardo Branco 	const size_t __len = SIG2STR_MAX + 1;
180*b0334450SRicardo Branco 	const size_t __idx __unused = __len - 1;
181*b0334450SRicardo Branco 
182*b0334450SRicardo Branco 	sig2str(1, __stack.__buf);
183*b0334450SRicardo Branco #undef BUF
184*b0334450SRicardo Branco 
185*b0334450SRicardo Branco }
186*b0334450SRicardo Branco 
187*b0334450SRicardo Branco ATF_TC(sig2str_end);
ATF_TC_HEAD(sig2str_end,tc)188*b0334450SRicardo Branco ATF_TC_HEAD(sig2str_end, tc)
189*b0334450SRicardo Branco {
190*b0334450SRicardo Branco }
ATF_TC_BODY(sig2str_end,tc)191*b0334450SRicardo Branco ATF_TC_BODY(sig2str_end, tc)
192*b0334450SRicardo Branco {
193*b0334450SRicardo Branco #define BUF &__stack.__buf
194*b0334450SRicardo Branco 	struct {
195*b0334450SRicardo Branco 		uint8_t padding_l;
196*b0334450SRicardo Branco 		unsigned char __buf[SIG2STR_MAX];
197*b0334450SRicardo Branco 		uint8_t padding_r;
198*b0334450SRicardo Branco 	} __stack;
199*b0334450SRicardo Branco 	const size_t __bufsz __unused = sizeof(__stack.__buf);
200*b0334450SRicardo Branco 	const size_t __len = SIG2STR_MAX;
201*b0334450SRicardo Branco 	const size_t __idx __unused = __len - 1;
202*b0334450SRicardo Branco 
203*b0334450SRicardo Branco 	sig2str(1, __stack.__buf);
204*b0334450SRicardo Branco #undef BUF
205*b0334450SRicardo Branco 
206*b0334450SRicardo Branco }
207*b0334450SRicardo Branco 
208*b0334450SRicardo Branco ATF_TC(sig2str_heap_before_end);
ATF_TC_HEAD(sig2str_heap_before_end,tc)209*b0334450SRicardo Branco ATF_TC_HEAD(sig2str_heap_before_end, tc)
210*b0334450SRicardo Branco {
211*b0334450SRicardo Branco }
ATF_TC_BODY(sig2str_heap_before_end,tc)212*b0334450SRicardo Branco ATF_TC_BODY(sig2str_heap_before_end, tc)
213*b0334450SRicardo Branco {
214*b0334450SRicardo Branco #define BUF __stack.__buf
215*b0334450SRicardo Branco 	struct {
216*b0334450SRicardo Branco 		uint8_t padding_l;
217*b0334450SRicardo Branco 		unsigned char * __buf;
218*b0334450SRicardo Branco 		uint8_t padding_r;
219*b0334450SRicardo Branco 	} __stack;
220*b0334450SRicardo Branco 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX + 1);
221*b0334450SRicardo Branco 	const size_t __len = SIG2STR_MAX + 1;
222*b0334450SRicardo Branco 	const size_t __idx __unused = __len - 1;
223*b0334450SRicardo Branco 
224*b0334450SRicardo Branco 	__stack.__buf = malloc(__bufsz);
225*b0334450SRicardo Branco 
226*b0334450SRicardo Branco 	sig2str(1, __stack.__buf);
227*b0334450SRicardo Branco #undef BUF
228*b0334450SRicardo Branco 
229*b0334450SRicardo Branco }
230*b0334450SRicardo Branco 
231*b0334450SRicardo Branco ATF_TC(sig2str_heap_end);
ATF_TC_HEAD(sig2str_heap_end,tc)232*b0334450SRicardo Branco ATF_TC_HEAD(sig2str_heap_end, tc)
233*b0334450SRicardo Branco {
234*b0334450SRicardo Branco }
ATF_TC_BODY(sig2str_heap_end,tc)235*b0334450SRicardo Branco ATF_TC_BODY(sig2str_heap_end, tc)
236*b0334450SRicardo Branco {
237*b0334450SRicardo Branco #define BUF __stack.__buf
238*b0334450SRicardo Branco 	struct {
239*b0334450SRicardo Branco 		uint8_t padding_l;
240*b0334450SRicardo Branco 		unsigned char * __buf;
241*b0334450SRicardo Branco 		uint8_t padding_r;
242*b0334450SRicardo Branco 	} __stack;
243*b0334450SRicardo Branco 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX);
244*b0334450SRicardo Branco 	const size_t __len = SIG2STR_MAX;
245*b0334450SRicardo Branco 	const size_t __idx __unused = __len - 1;
246*b0334450SRicardo Branco 
247*b0334450SRicardo Branco 	__stack.__buf = malloc(__bufsz);
248*b0334450SRicardo Branco 
249*b0334450SRicardo Branco 	sig2str(1, __stack.__buf);
250*b0334450SRicardo Branco #undef BUF
251*b0334450SRicardo Branco 
252*b0334450SRicardo Branco }
253*b0334450SRicardo Branco 
254*b0334450SRicardo Branco ATF_TC(sig2str_heap_after_end);
ATF_TC_HEAD(sig2str_heap_after_end,tc)255*b0334450SRicardo Branco ATF_TC_HEAD(sig2str_heap_after_end, tc)
256*b0334450SRicardo Branco {
257*b0334450SRicardo Branco }
ATF_TC_BODY(sig2str_heap_after_end,tc)258*b0334450SRicardo Branco ATF_TC_BODY(sig2str_heap_after_end, tc)
259*b0334450SRicardo Branco {
260*b0334450SRicardo Branco #define BUF __stack.__buf
261*b0334450SRicardo Branco 	struct {
262*b0334450SRicardo Branco 		uint8_t padding_l;
263*b0334450SRicardo Branco 		unsigned char * __buf;
264*b0334450SRicardo Branco 		uint8_t padding_r;
265*b0334450SRicardo Branco 	} __stack;
266*b0334450SRicardo Branco 	const size_t __bufsz __unused = sizeof(*__stack.__buf) * (SIG2STR_MAX - 1);
267*b0334450SRicardo Branco 	const size_t __len = SIG2STR_MAX - 1;
268*b0334450SRicardo Branco 	const size_t __idx __unused = __len - 1;
269*b0334450SRicardo Branco 	pid_t __child;
270*b0334450SRicardo Branco 	int __status;
271*b0334450SRicardo Branco 
272*b0334450SRicardo Branco 	__child = fork();
273*b0334450SRicardo Branco 	ATF_REQUIRE(__child >= 0);
274*b0334450SRicardo Branco 	if (__child > 0)
275*b0334450SRicardo Branco 		goto monitor;
276*b0334450SRicardo Branco 
277*b0334450SRicardo Branco 	/* Child */
278*b0334450SRicardo Branco 	disable_coredumps();
279*b0334450SRicardo Branco 	__stack.__buf = malloc(__bufsz);
280*b0334450SRicardo Branco 
281*b0334450SRicardo Branco 	sig2str(1, __stack.__buf);
282*b0334450SRicardo Branco 	_exit(EX_SOFTWARE);	/* Should have aborted. */
283*b0334450SRicardo Branco 
284*b0334450SRicardo Branco monitor:
285*b0334450SRicardo Branco 	while (waitpid(__child, &__status, 0) != __child) {
286*b0334450SRicardo Branco 		ATF_REQUIRE_EQ(EINTR, errno);
287*b0334450SRicardo Branco 	}
288*b0334450SRicardo Branco 
289*b0334450SRicardo Branco 	if (!WIFSIGNALED(__status)) {
290*b0334450SRicardo Branco 		switch (WEXITSTATUS(__status)) {
291*b0334450SRicardo Branco 		case EX_SOFTWARE:
292*b0334450SRicardo Branco 			atf_tc_fail("FORTIFY_SOURCE failed to abort");
293*b0334450SRicardo Branco 			break;
294*b0334450SRicardo Branco 		case EX_OSERR:
295*b0334450SRicardo Branco 			atf_tc_fail("setrlimit(2) failed");
296*b0334450SRicardo Branco 			break;
297*b0334450SRicardo Branco 		default:
298*b0334450SRicardo Branco 			atf_tc_fail("child exited with status %d",
299*b0334450SRicardo Branco 			    WEXITSTATUS(__status));
300*b0334450SRicardo Branco 		}
301*b0334450SRicardo Branco 	} else {
302*b0334450SRicardo Branco 		ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
303*b0334450SRicardo Branco 	}
304*b0334450SRicardo Branco #undef BUF
305*b0334450SRicardo Branco 
306*b0334450SRicardo Branco }
307*b0334450SRicardo Branco 
ATF_TP_ADD_TCS(tp)308*b0334450SRicardo Branco ATF_TP_ADD_TCS(tp)
309*b0334450SRicardo Branco {
310*b0334450SRicardo Branco 	ATF_TP_ADD_TC(tp, sig2str_before_end);
311*b0334450SRicardo Branco 	ATF_TP_ADD_TC(tp, sig2str_end);
312*b0334450SRicardo Branco 	ATF_TP_ADD_TC(tp, sig2str_heap_before_end);
313*b0334450SRicardo Branco 	ATF_TP_ADD_TC(tp, sig2str_heap_end);
314*b0334450SRicardo Branco 	ATF_TP_ADD_TC(tp, sig2str_heap_after_end);
315*b0334450SRicardo Branco 	return (atf_no_error());
316*b0334450SRicardo Branco }
317