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