xref: /freebsd-src/contrib/netbsd-tests/include/sys/t_socket.c (revision 57718be8fa0bd5edc11ab9a72e68cc71982939a6)
1*57718be8SEnji Cooper /*	$NetBSD: t_socket.c,v 1.3 2013/10/19 17:45:00 christos Exp $	*/
2*57718be8SEnji Cooper 
3*57718be8SEnji Cooper #include <sys/types.h>
4*57718be8SEnji Cooper #include <sys/mount.h>
5*57718be8SEnji Cooper #include <sys/socket.h>
6*57718be8SEnji Cooper #include <sys/un.h>
7*57718be8SEnji Cooper 
8*57718be8SEnji Cooper #include <rump/rump.h>
9*57718be8SEnji Cooper #include <rump/rump_syscalls.h>
10*57718be8SEnji Cooper 
11*57718be8SEnji Cooper #include <atf-c.h>
12*57718be8SEnji Cooper #include <fcntl.h>
13*57718be8SEnji Cooper #include <err.h>
14*57718be8SEnji Cooper #include <errno.h>
15*57718be8SEnji Cooper #include <stdio.h>
16*57718be8SEnji Cooper #include <stdlib.h>
17*57718be8SEnji Cooper #include <string.h>
18*57718be8SEnji Cooper #include <unistd.h>
19*57718be8SEnji Cooper #include <util.h>
20*57718be8SEnji Cooper 
21*57718be8SEnji Cooper #include "../../h_macros.h"
22*57718be8SEnji Cooper 
23*57718be8SEnji Cooper ATF_TC(cmsg_sendfd_bounds);
24*57718be8SEnji Cooper ATF_TC_HEAD(cmsg_sendfd_bounds, tc)
25*57718be8SEnji Cooper {
26*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks that attempting to pass an "
27*57718be8SEnji Cooper 	    "invalid fd returns an error");
28*57718be8SEnji Cooper }
29*57718be8SEnji Cooper 
30*57718be8SEnji Cooper ATF_TC_BODY(cmsg_sendfd_bounds, tc)
31*57718be8SEnji Cooper {
32*57718be8SEnji Cooper 	struct cmsghdr *cmp;
33*57718be8SEnji Cooper 	struct msghdr msg;
34*57718be8SEnji Cooper 	struct iovec iov;
35*57718be8SEnji Cooper 	int s[2];
36*57718be8SEnji Cooper 	int fd;
37*57718be8SEnji Cooper 
38*57718be8SEnji Cooper 	rump_init();
39*57718be8SEnji Cooper 
40*57718be8SEnji Cooper 	if (rump_sys_socketpair(AF_LOCAL, SOCK_STREAM, 0, s) == -1)
41*57718be8SEnji Cooper 		atf_tc_fail("rump_sys_socket");
42*57718be8SEnji Cooper 
43*57718be8SEnji Cooper 	cmp = malloc(CMSG_SPACE(sizeof(int)));
44*57718be8SEnji Cooper 
45*57718be8SEnji Cooper 	iov.iov_base = &fd;
46*57718be8SEnji Cooper 	iov.iov_len = sizeof(int);
47*57718be8SEnji Cooper 
48*57718be8SEnji Cooper 	cmp->cmsg_level = SOL_SOCKET;
49*57718be8SEnji Cooper 	cmp->cmsg_type = SCM_RIGHTS;
50*57718be8SEnji Cooper 	cmp->cmsg_len = CMSG_LEN(sizeof(int));
51*57718be8SEnji Cooper 
52*57718be8SEnji Cooper 	msg.msg_iov = &iov;
53*57718be8SEnji Cooper 	msg.msg_iovlen = 1;
54*57718be8SEnji Cooper 	msg.msg_name = NULL;
55*57718be8SEnji Cooper 	msg.msg_namelen = 0;
56*57718be8SEnji Cooper 	msg.msg_control = cmp;
57*57718be8SEnji Cooper 	msg.msg_controllen = CMSG_SPACE(sizeof(int));
58*57718be8SEnji Cooper 
59*57718be8SEnji Cooper 	/*
60*57718be8SEnji Cooper 	 * ERROR HERE: trying to pass invalid fd
61*57718be8SEnji Cooper 	 * (This value was previously directly used to index the fd
62*57718be8SEnji Cooper 	 *  array and therefore we are passing a hyperspace index)
63*57718be8SEnji Cooper 	 */
64*57718be8SEnji Cooper 	*(int *)CMSG_DATA(cmp) = 0x12345678;
65*57718be8SEnji Cooper 
66*57718be8SEnji Cooper 	rump_sys_sendmsg(s[0], &msg, 0);
67*57718be8SEnji Cooper 	if (errno != EBADF)
68*57718be8SEnji Cooper 		atf_tc_fail("descriptor passing failed: expected EBADF (9), "
69*57718be8SEnji Cooper 		    "got %d\n(%s)", errno, strerror(errno));
70*57718be8SEnji Cooper }
71*57718be8SEnji Cooper 
72*57718be8SEnji Cooper 
73*57718be8SEnji Cooper ATF_TC(cmsg_sendfd);
74*57718be8SEnji Cooper ATF_TC_HEAD(cmsg_sendfd, tc)
75*57718be8SEnji Cooper {
76*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Checks that fd passing works");
77*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "timeout", "2");
78*57718be8SEnji Cooper }
79*57718be8SEnji Cooper 
80*57718be8SEnji Cooper ATF_TC_BODY(cmsg_sendfd, tc)
81*57718be8SEnji Cooper {
82*57718be8SEnji Cooper 	char buf[128];
83*57718be8SEnji Cooper 	struct cmsghdr *cmp;
84*57718be8SEnji Cooper 	struct msghdr msg;
85*57718be8SEnji Cooper 	struct sockaddr_un sun;
86*57718be8SEnji Cooper 	struct lwp *l1;
87*57718be8SEnji Cooper 	struct iovec iov;
88*57718be8SEnji Cooper 	socklen_t sl;
89*57718be8SEnji Cooper 	int s1, s2, sgot;
90*57718be8SEnji Cooper 	int rfd, fd[2], storage;
91*57718be8SEnji Cooper 
92*57718be8SEnji Cooper 	rump_init();
93*57718be8SEnji Cooper 
94*57718be8SEnji Cooper 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
95*57718be8SEnji Cooper 	l1 = rump_pub_lwproc_curlwp();
96*57718be8SEnji Cooper 
97*57718be8SEnji Cooper 	/* create unix socket and bind it to a path */
98*57718be8SEnji Cooper 	memset(&sun, 0, sizeof(sun));
99*57718be8SEnji Cooper 	sun.sun_family = AF_LOCAL;
100*57718be8SEnji Cooper #define SOCKPATH "/com"
101*57718be8SEnji Cooper 	strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH));
102*57718be8SEnji Cooper 	s1 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0);
103*57718be8SEnji Cooper 	if (s1 == -1)
104*57718be8SEnji Cooper 		atf_tc_fail_errno("socket 1");
105*57718be8SEnji Cooper 	if (rump_sys_bind(s1, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1)
106*57718be8SEnji Cooper 		atf_tc_fail_errno("socket 1 bind");
107*57718be8SEnji Cooper 	if (rump_sys_listen(s1, 1) == -1)
108*57718be8SEnji Cooper 		atf_tc_fail_errno("socket 1 listen");
109*57718be8SEnji Cooper 
110*57718be8SEnji Cooper 	/* create second process for test */
111*57718be8SEnji Cooper 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
112*57718be8SEnji Cooper 	(void)rump_pub_lwproc_curlwp();
113*57718be8SEnji Cooper 
114*57718be8SEnji Cooper 	/* connect to unix domain socket */
115*57718be8SEnji Cooper 	memset(&sun, 0, sizeof(sun));
116*57718be8SEnji Cooper 	sun.sun_family = AF_LOCAL;
117*57718be8SEnji Cooper 	strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH));
118*57718be8SEnji Cooper 	s2 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0);
119*57718be8SEnji Cooper 	if (s2 == -1)
120*57718be8SEnji Cooper 		atf_tc_fail_errno("socket 2");
121*57718be8SEnji Cooper 	if (rump_sys_connect(s2, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1)
122*57718be8SEnji Cooper 		atf_tc_fail_errno("socket 2 connect");
123*57718be8SEnji Cooper 
124*57718be8SEnji Cooper 	/* open a pipe and write stuff to it */
125*57718be8SEnji Cooper 	if (rump_sys_pipe(fd) == -1)
126*57718be8SEnji Cooper 		atf_tc_fail_errno("can't open pipe");
127*57718be8SEnji Cooper #define MAGICSTRING "duam xnaht"
128*57718be8SEnji Cooper 	if (rump_sys_write(fd[1], MAGICSTRING, sizeof(MAGICSTRING)) !=
129*57718be8SEnji Cooper 	    sizeof(MAGICSTRING))
130*57718be8SEnji Cooper 		atf_tc_fail_errno("pipe write"); /* XXX: errno */
131*57718be8SEnji Cooper 
132*57718be8SEnji Cooper 	cmp = malloc(CMSG_SPACE(sizeof(int)));
133*57718be8SEnji Cooper 
134*57718be8SEnji Cooper 	iov.iov_base = &storage;
135*57718be8SEnji Cooper 	iov.iov_len = sizeof(int);
136*57718be8SEnji Cooper 
137*57718be8SEnji Cooper 	cmp->cmsg_level = SOL_SOCKET;
138*57718be8SEnji Cooper 	cmp->cmsg_type = SCM_RIGHTS;
139*57718be8SEnji Cooper 	cmp->cmsg_len = CMSG_LEN(sizeof(int));
140*57718be8SEnji Cooper 
141*57718be8SEnji Cooper 	msg.msg_iov = &iov;
142*57718be8SEnji Cooper 	msg.msg_iovlen = 1;
143*57718be8SEnji Cooper 	msg.msg_name = NULL;
144*57718be8SEnji Cooper 	msg.msg_namelen = 0;
145*57718be8SEnji Cooper 	msg.msg_control = cmp;
146*57718be8SEnji Cooper 	msg.msg_controllen = CMSG_SPACE(sizeof(int));
147*57718be8SEnji Cooper 	*(int *)CMSG_DATA(cmp) = fd[0];
148*57718be8SEnji Cooper 
149*57718be8SEnji Cooper 	/* pass the fd */
150*57718be8SEnji Cooper 	if (rump_sys_sendmsg(s2, &msg, 0) == -1)
151*57718be8SEnji Cooper 		atf_tc_fail_errno("sendmsg failed");
152*57718be8SEnji Cooper 
153*57718be8SEnji Cooper 	/*
154*57718be8SEnji Cooper 	 * We will read to the same cmsg space.  Overwrite the space
155*57718be8SEnji Cooper 	 * with an invalid fd to make sure we get an explicit error
156*57718be8SEnji Cooper 	 * if we don't manage to read the fd.
157*57718be8SEnji Cooper 	 */
158*57718be8SEnji Cooper 	*(int *)CMSG_DATA(cmp) = -1;
159*57718be8SEnji Cooper 
160*57718be8SEnji Cooper 	/* switch back to original proc */
161*57718be8SEnji Cooper 	rump_pub_lwproc_switch(l1);
162*57718be8SEnji Cooper 
163*57718be8SEnji Cooper 	/* accept connection and read fd */
164*57718be8SEnji Cooper 	sl = sizeof(sun);
165*57718be8SEnji Cooper 	sgot = rump_sys_accept(s1, (struct sockaddr *)&sun, &sl);
166*57718be8SEnji Cooper 	if (sgot == -1)
167*57718be8SEnji Cooper 		atf_tc_fail_errno("accept");
168*57718be8SEnji Cooper 	if (rump_sys_recvmsg(sgot, &msg, 0) == -1)
169*57718be8SEnji Cooper 		atf_tc_fail_errno("recvmsg failed");
170*57718be8SEnji Cooper 	rfd = *(int *)CMSG_DATA(cmp);
171*57718be8SEnji Cooper 
172*57718be8SEnji Cooper 	/* read from the fd */
173*57718be8SEnji Cooper 	memset(buf, 0, sizeof(buf));
174*57718be8SEnji Cooper 	if (rump_sys_read(rfd, buf, sizeof(buf)) == -1)
175*57718be8SEnji Cooper 		atf_tc_fail_errno("read rfd");
176*57718be8SEnji Cooper 
177*57718be8SEnji Cooper 	/* check that we got the right stuff */
178*57718be8SEnji Cooper 	if (strcmp(buf, MAGICSTRING) != 0)
179*57718be8SEnji Cooper 		atf_tc_fail("expected \"%s\", got \"%s\"", MAGICSTRING, buf);
180*57718be8SEnji Cooper }
181*57718be8SEnji Cooper 
182*57718be8SEnji Cooper ATF_TC(sock_cloexec);
183*57718be8SEnji Cooper ATF_TC_HEAD(sock_cloexec, tc)
184*57718be8SEnji Cooper {
185*57718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "SOCK_CLOEXEC kernel invariant failure");
186*57718be8SEnji Cooper }
187*57718be8SEnji Cooper 
188*57718be8SEnji Cooper ATF_TC_BODY(sock_cloexec, tc)
189*57718be8SEnji Cooper {
190*57718be8SEnji Cooper 
191*57718be8SEnji Cooper 	rump_init();
192*57718be8SEnji Cooper 	rump_pub_lwproc_rfork(RUMP_RFFDG);
193*57718be8SEnji Cooper 	if (rump_sys_socket(-1, SOCK_CLOEXEC, 0) != -1)
194*57718be8SEnji Cooper 		atf_tc_fail("invalid socket parameters unexpectedly worked");
195*57718be8SEnji Cooper 	rump_pub_lwproc_releaselwp();
196*57718be8SEnji Cooper }
197*57718be8SEnji Cooper 
198*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
199*57718be8SEnji Cooper {
200*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, cmsg_sendfd);
201*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, cmsg_sendfd_bounds);
202*57718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, sock_cloexec);
203*57718be8SEnji Cooper 
204*57718be8SEnji Cooper 	return atf_no_error();
205*57718be8SEnji Cooper }
206