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