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
main(void)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
sendfd(int s,int fd)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
recvfd(int s)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