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