158310Sache/* $NetBSD: t_socket.c,v 1.5 2017/01/13 21:30:41 christos Exp $ */ 258310Sache 358310Sache#include <sys/types.h> 4157184Sache#include <sys/mount.h> 558310Sache#include <sys/socket.h> 658310Sache#include <sys/un.h> 758310Sache 858310Sache#include <rump/rump.h> 958310Sache#include <rump/rump_syscalls.h> 1058310Sache 1158310Sache#include <atf-c.h> 1258310Sache#include <fcntl.h> 1358310Sache#include <err.h> 1458310Sache#include <errno.h> 1558310Sache#include <stdio.h> 1658310Sache#include <stdlib.h> 1758310Sache#include <string.h> 1858310Sache#include <unistd.h> 1958310Sache#include <util.h> 2058310Sache 2158310Sache#include "h_macros.h" 2258310Sache 2358310SacheATF_TC(cmsg_sendfd_bounds); 2458310SacheATF_TC_HEAD(cmsg_sendfd_bounds, tc) 2558310Sache{ 2658310Sache atf_tc_set_md_var(tc, "descr", "Checks that attempting to pass an " 2758310Sache "invalid fd returns an error"); 2858310Sache} 29119610Sache 3058310SacheATF_TC_BODY(cmsg_sendfd_bounds, tc) 3158310Sache{ 3258310Sache struct cmsghdr *cmp; 33157184Sache struct msghdr msg; 34157184Sache struct iovec iov; 35157184Sache int s[2]; 36157184Sache int fd; 37157184Sache 38157184Sache rump_init(); 39157184Sache 40157184Sache if (rump_sys_socketpair(AF_LOCAL, SOCK_STREAM, 0, s) == -1) 41157184Sache atf_tc_fail("rump_sys_socket"); 42157184Sache 43157184Sache cmp = malloc(CMSG_SPACE(sizeof(int))); 44157184Sache 45157184Sache iov.iov_base = &fd; 46157184Sache iov.iov_len = sizeof(int); 47157184Sache 48157184Sache cmp->cmsg_level = SOL_SOCKET; 49157184Sache cmp->cmsg_type = SCM_RIGHTS; 50157184Sache cmp->cmsg_len = CMSG_LEN(sizeof(int)); 51157184Sache 52157184Sache msg.msg_iov = &iov; 53157184Sache msg.msg_iovlen = 1; 54157184Sache msg.msg_name = NULL; 55157184Sache msg.msg_namelen = 0; 56157184Sache msg.msg_control = cmp; 57157184Sache msg.msg_controllen = CMSG_SPACE(sizeof(int)); 58157184Sache 59157184Sache /* 60157184Sache * ERROR HERE: trying to pass invalid fd 61157184Sache * (This value was previously directly used to index the fd 62157184Sache * array and therefore we are passing a hyperspace index) 63157184Sache */ 64157184Sache *(int *)CMSG_DATA(cmp) = 0x12345678; 65157184Sache 66157184Sache rump_sys_sendmsg(s[0], &msg, 0); 67157184Sache if (errno != EBADF) 68157184Sache atf_tc_fail("descriptor passing failed: expected EBADF (9), " 69157184Sache "got %d\n(%s)", errno, strerror(errno)); 70157184Sache} 71157184Sache 72157184Sache 73157184SacheATF_TC(cmsg_sendfd); 74157184SacheATF_TC_HEAD(cmsg_sendfd, tc) 75157184Sache{ 76157184Sache atf_tc_set_md_var(tc, "descr", "Checks that fd passing works"); 77157184Sache atf_tc_set_md_var(tc, "timeout", "10"); 78157184Sache} 79157184Sache 80157184SacheATF_TC_BODY(cmsg_sendfd, tc) 81157184Sache{ 82157184Sache char buf[128]; 83157184Sache struct cmsghdr *cmp; 84157184Sache struct msghdr msg; 85157184Sache struct sockaddr_un sun; 86157184Sache struct lwp *l1; 87157184Sache struct iovec iov; 88157184Sache socklen_t sl; 89157184Sache int s1, s2, sgot; 90157184Sache int rfd, fd[2], storage; 91157184Sache 92157184Sache rump_init(); 93157184Sache 94157184Sache RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 95157184Sache l1 = rump_pub_lwproc_curlwp(); 96157184Sache 97157184Sache /* create unix socket and bind it to a path */ 98157184Sache memset(&sun, 0, sizeof(sun)); 99157184Sache sun.sun_family = AF_LOCAL; 100157184Sache#define SOCKPATH "/com" 101157184Sache strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH)); 102157184Sache s1 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0); 103157184Sache if (s1 == -1) 104157184Sache atf_tc_fail_errno("socket 1"); 105157184Sache if (rump_sys_bind(s1, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1) 106157184Sache atf_tc_fail_errno("socket 1 bind"); 107157184Sache if (rump_sys_listen(s1, 1) == -1) 108157184Sache atf_tc_fail_errno("socket 1 listen"); 109157184Sache 110157184Sache /* create second process for test */ 111157184Sache RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 112157184Sache (void)rump_pub_lwproc_curlwp(); 113157184Sache 114157184Sache /* connect to unix domain socket */ 115157184Sache memset(&sun, 0, sizeof(sun)); 116157184Sache sun.sun_family = AF_LOCAL; 117157184Sache strncpy(sun.sun_path, SOCKPATH, sizeof(SOCKPATH)); 118157184Sache s2 = rump_sys_socket(AF_LOCAL, SOCK_STREAM, 0); 119157184Sache if (s2 == -1) 120157184Sache atf_tc_fail_errno("socket 2"); 121157184Sache if (rump_sys_connect(s2, (struct sockaddr *)&sun, SUN_LEN(&sun)) == -1) 12258310Sache atf_tc_fail_errno("socket 2 connect"); 12358310Sache 12458310Sache /* open a pipe and write stuff to it */ 12558310Sache if (rump_sys_pipe(fd) == -1) 12658310Sache atf_tc_fail_errno("can't open pipe"); 12758310Sache#define MAGICSTRING "duam xnaht" 12858310Sache if (rump_sys_write(fd[1], MAGICSTRING, sizeof(MAGICSTRING)) != 12958310Sache sizeof(MAGICSTRING)) 13058310Sache atf_tc_fail_errno("pipe write"); /* XXX: errno */ 13158310Sache 13258310Sache cmp = malloc(CMSG_SPACE(sizeof(int))); 13358310Sache 13458310Sache iov.iov_base = &storage; 13558310Sache iov.iov_len = sizeof(int); 13658310Sache 13758310Sache cmp->cmsg_level = SOL_SOCKET; 13858310Sache cmp->cmsg_type = SCM_RIGHTS; 13958310Sache cmp->cmsg_len = CMSG_LEN(sizeof(int)); 14058310Sache 14158310Sache msg.msg_iov = &iov; 14258310Sache msg.msg_iovlen = 1; 14358310Sache msg.msg_name = NULL; 144119610Sache msg.msg_namelen = 0; 14558310Sache msg.msg_control = cmp; 146157184Sache msg.msg_controllen = CMSG_SPACE(sizeof(int)); 147157184Sache *(int *)CMSG_DATA(cmp) = fd[0]; 14858310Sache 14958310Sache /* pass the fd */ 15058310Sache if (rump_sys_sendmsg(s2, &msg, 0) == -1) 15158310Sache atf_tc_fail_errno("sendmsg failed"); 15258310Sache 15358310Sache /* 15458310Sache * We will read to the same cmsg space. Overwrite the space 15558310Sache * with an invalid fd to make sure we get an explicit error 15658310Sache * if we don't manage to read the fd. 15758310Sache */ 15858310Sache *(int *)CMSG_DATA(cmp) = -1; 15958310Sache 16058310Sache /* switch back to original proc */ 161119610Sache rump_pub_lwproc_switch(l1); 16258310Sache 16358310Sache /* accept connection and read fd */ 164119610Sache sl = sizeof(sun); 16558310Sache sgot = rump_sys_accept(s1, (struct sockaddr *)&sun, &sl); 16658310Sache if (sgot == -1) 167119610Sache atf_tc_fail_errno("accept"); 16858310Sache if (rump_sys_recvmsg(sgot, &msg, 0) == -1) 16958310Sache atf_tc_fail_errno("recvmsg failed"); 170119610Sache rfd = *(int *)CMSG_DATA(cmp); 17158310Sache 17258310Sache /* read from the fd */ 17358310Sache memset(buf, 0, sizeof(buf)); 17458310Sache if (rump_sys_read(rfd, buf, sizeof(buf)) == -1) 17558310Sache atf_tc_fail_errno("read rfd"); 17658310Sache 17758310Sache /* check that we got the right stuff */ 17858310Sache if (strcmp(buf, MAGICSTRING) != 0) 17958310Sache atf_tc_fail("expected \"%s\", got \"%s\"", MAGICSTRING, buf); 18058310Sache} 18158310Sache 18258310SacheATF_TC(sock_cloexec); 18358310SacheATF_TC_HEAD(sock_cloexec, tc) 18458310Sache{ 18558310Sache atf_tc_set_md_var(tc, "descr", "SOCK_CLOEXEC kernel invariant failure"); 18658310Sache} 18758310Sache 18858310SacheATF_TC_BODY(sock_cloexec, tc) 18958310Sache{ 190119610Sache 191119610Sache rump_init(); 192119610Sache rump_pub_lwproc_rfork(RUMP_RFFDG); 19358310Sache if (rump_sys_socket(-1, SOCK_CLOEXEC, 0) != -1) 194157184Sache atf_tc_fail("invalid socket parameters unexpectedly worked"); 195157184Sache rump_pub_lwproc_releaselwp(); 196157184Sache} 197157184Sache 198157184SacheATF_TP_ADD_TCS(tp) 199157184Sache{ 200157184Sache ATF_TP_ADD_TC(tp, cmsg_sendfd); 201157184Sache ATF_TP_ADD_TC(tp, cmsg_sendfd_bounds); 202157184Sache ATF_TP_ADD_TC(tp, sock_cloexec); 203157184Sache 20458310Sache return atf_no_error(); 20558310Sache} 20658310Sache