t_socket.c revision 314817
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
23ATF_TC(cmsg_sendfd_bounds);
24ATF_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
30ATF_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
73ATF_TC(cmsg_sendfd);
74ATF_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
80ATF_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
182ATF_TC(sock_cloexec);
183ATF_TC_HEAD(sock_cloexec, tc)
184{
185	atf_tc_set_md_var(tc, "descr", "SOCK_CLOEXEC kernel invariant failure");
186}
187
188ATF_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
198ATF_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