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