1 #include <sys/types.h> 2 #include <sys/wait.h> 3 #include <sys/socket.h> 4 #include <sys/uio.h> 5 #include <unistd.h> 6 #include <err.h> 7 #include <errno.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 /* workaround leaky case */ 13 #ifndef MSG_CMSG_CLOEXEC 14 #define MSG_CMSG_CLOEXEC 0 15 #endif 16 17 #define CHECKFD_CMD "checkfd" 18 #define CHECKFD_PATH "/usr/local/bin/" CHECKFD_CMD 19 20 int sendfd(int s, int fd); 21 int recvfd(int s); 22 23 int main(void) 24 { 25 pid_t pid; 26 int s[2], status, ecode; 27 28 socketpair(AF_UNIX, SOCK_STREAM, 0, s); 29 30 pid = fork(); 31 if (pid < 0) { 32 err(1, "fork failed"); 33 } else if (pid == 0) { 34 close(0); 35 close(1); 36 /* close(2); */ 37 38 int mysecretfd = recvfd(s[0]); 39 40 write(mysecretfd, "hello secret\n", 14); 41 42 char fd[8]; 43 snprintf(fd, sizeof(fd), "%d", mysecretfd); 44 if (execl(CHECKFD_PATH, CHECKFD_CMD, fd, NULL) < 0) 45 err(3, "execl failed"); 46 } else { 47 sendfd(s[1], 1); 48 } 49 50 if (waitpid(pid, &status, 0) < 0) 51 err(1, "waitpid failed"); 52 53 if (!WIFEXITED(status)) 54 errx(1, CHECKFD_CMD " did not exit"); 55 56 ecode = WEXITSTATUS(status); 57 if (ecode != 0) { 58 warnx("exit code %d", ecode); 59 abort(); 60 } 61 62 fprintf(stderr, "passed\n"); 63 exit(0); 64 65 } 66 67 int 68 sendfd(int s, int fd) 69 { 70 char buf[1]; 71 struct iovec iov; 72 struct msghdr msg; 73 struct cmsghdr *cmsg; 74 int n; 75 char cms[CMSG_SPACE(sizeof(int))]; 76 77 buf[0] = 0; 78 iov.iov_base = buf; 79 iov.iov_len = 1; 80 81 memset(&msg, 0, sizeof msg); 82 msg.msg_iov = &iov; 83 msg.msg_iovlen = 1; 84 msg.msg_control = (caddr_t)cms; 85 msg.msg_controllen = CMSG_LEN(sizeof(int)); 86 87 cmsg = CMSG_FIRSTHDR(&msg); 88 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 89 cmsg->cmsg_level = SOL_SOCKET; 90 cmsg->cmsg_type = SCM_RIGHTS; 91 memmove(CMSG_DATA(cmsg), &fd, sizeof(int)); 92 93 if ((n=sendmsg(s, &msg, 0)) != (int)iov.iov_len) 94 return -1; 95 return 0; 96 } 97 98 int 99 recvfd(int s) 100 { 101 int n; 102 int fd; 103 char buf[1]; 104 struct iovec iov; 105 struct msghdr msg; 106 struct cmsghdr *cmsg; 107 char cms[CMSG_SPACE(sizeof(int))]; 108 109 iov.iov_base = buf; 110 iov.iov_len = 1; 111 112 memset(&msg, 0, sizeof msg); 113 msg.msg_name = 0; 114 msg.msg_namelen = 0; 115 msg.msg_iov = &iov; 116 msg.msg_iovlen = 1; 117 118 msg.msg_control = (caddr_t)cms; 119 msg.msg_controllen = sizeof cms; 120 121 if ((n=recvmsg(s, &msg, MSG_CMSG_CLOEXEC)) < 0) 122 return -1; 123 if (n == 0){ 124 return -1; 125 } 126 cmsg = CMSG_FIRSTHDR(&msg); 127 memmove(&fd, CMSG_DATA(cmsg), sizeof(int)); 128 return fd; 129 } 130