ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/IO-FDPass/FDPass.xs
(Generate patch)

Comparing IO-FDPass/FDPass.xs (file contents):
Revision 1.3 by root, Fri Apr 5 04:32:50 2013 UTC vs.
Revision 1.9 by root, Tue Sep 6 10:49:13 2022 UTC

17 17
18 #include <windows.h> 18 #include <windows.h>
19 #include <io.h> 19 #include <io.h>
20 #include <sys/cygwin.h> 20 #include <sys/cygwin.h>
21 21
22 #define ioctlsocket(a,b,c) ioctl (a, b, c)
23 #define _open_osfhandle(h,m) cygwin_attach_handle_to_fd ("/dev/pipe", -1, (HANDLE)h, 1, GENERIC_READ | GENERIC_WRITE) 22 #define _open_osfhandle(h,m) cygwin_attach_handle_to_fd ("/dev/tcp", -1, (HANDLE)h, 1, GENERIC_READ | GENERIC_WRITE)
24 typedef int SOCKET; 23 typedef int SOCKET;
25 24
26#else 25#else
27 26
28 #include <stddef.h> // needed by broken bsds for NULL used in sys/uio.h 27 #include <stddef.h> // needed by broken bsds for NULL used in sys/uio.h
33 #include <sys/types.h> 32 #include <sys/types.h>
34 #include <sys/uio.h> 33 #include <sys/uio.h>
35 #include <sys/socket.h> 34 #include <sys/socket.h>
36 35
37 #ifndef CMSG_SPACE 36 #ifndef CMSG_SPACE
38 # define CMSG_SPACE(len) (sizeof (cmsghdr) + len) 37 # define CMSG_SPACE(len) (sizeof (struct cmsghdr) + len)
39 #endif 38 #endif
40 39
41 #ifndef CMSG_LEN 40 #ifndef CMSG_LEN
42 # define CMSG_LEN(len) (sizeof (cmsghdr) + len) 41 # define CMSG_LEN(len) (sizeof (struct cmsghdr) + len)
43 #endif 42 #endif
44 43
45#endif 44#endif
46 45
47#if defined(WIN32) 46#if defined(WIN32)
55 int got = 0; 54 int got = 0;
56 55
57 while (got != len) 56 while (got != len)
58 { 57 {
59 int sze = wr 58 int sze = wr
60 ? send ((SOCKET)fd, buf, len, 0) /* we assume send and recv are macros with arguments */ 59 ? send ((SOCKET)fd, buf, len - got, 0) /* we assume send and recv are macros with arguments */
61 : recv ((SOCKET)fd, buf, len, 0); /* to be on the safe side */ 60 : recv ((SOCKET)fd, buf, len - got, 0); /* to be on the safe side */
62 61
63 if (sze <= 0) 62 if (sze < 0)
64 { 63 {
65 if (errno == EAGAIN || errno == WSAEWOULDBLOCK) 64 if (errno == EAGAIN || errno == WSAEWOULDBLOCK)
66 { 65 {
67 ioctlsocket (fd, FIONBIO, &nbio); 66 ioctl (fd, FIONBIO, (void *)&nbio);
68 nbio = 1; 67 nbio = 1;
69 } 68 }
70 else 69 else
71 break; 70 break;
72 } 71 }
72 else if (sze == 0)
73 break;
73 else 74 else
74 got += sze; 75 got += sze;
75 } 76 }
76 77
77 if (nbio) 78 if (nbio)
78 ioctlsocket (fd, FIONBIO, &nbio); 79 ioctl (fd, FIONBIO, (void *)&nbio);
79 80
80 return got == len; 81 return got == len;
81} 82}
82#endif 83#endif
83 84
84static int 85static int
85fd_send (int socket, int fd) 86fd_send (int socket, int fd)
86{ 87{
87#if defined(WIN32) 88#if defined(WIN32)
88 DWORD pid; 89 DWORD pid;
89 HANDLE target, h; 90 HANDLE hdl;
91
92 pid = GetCurrentProcessId ();
90 93
91 /* seriously, there is no way to query whether a socket is non-blocking?? */
92 if (!rw (0, socket, (char *)&pid, sizeof (pid))) 94 if (!rw (1, socket, (char *)&pid, sizeof (pid)))
93 return 0; 95 return 0;
94 96
95 target = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid); 97 errno = EBADF;
96 if (!target)
97 croak ("AnyEvent::ProcessPool::fd_recv: OpenProcess failed");
98
99 if (!DuplicateHandle ((HANDLE)-1, (HANDLE)_get_osfhandle (fd), target, &h, 0, FALSE, DUPLICATE_SAME_ACCESS)) 98 if (!DuplicateHandle ((HANDLE)-1, (HANDLE)_get_osfhandle (fd), (HANDLE)-1, &hdl, 0, FALSE, DUPLICATE_SAME_ACCESS))
100 croak ("AnyEvent::ProcessPool::fd_recv: DuplicateHandle failed");
101
102 CloseHandle (target);
103
104 if (!rw (1, socket, (char *)&h , sizeof (h )))
105 return 0; 99 return 0;
100
101 if (!rw (1, socket, (char *)&hdl, sizeof (hdl)))
102 {
103 CloseHandle (hdl);
104 return 0;
105 }
106 106
107 return 1; 107 return 1;
108 108
109#else 109#else
110 void *buf = malloc (CMSG_SPACE (sizeof (int))); 110 void *buf = malloc (CMSG_SPACE (sizeof (int)));
144 144
145static int 145static int
146fd_recv (int socket) 146fd_recv (int socket)
147{ 147{
148#if defined(WIN32) 148#if defined(WIN32)
149 DWORD pid = GetCurrentProcessId (); 149 DWORD pid;
150 HANDLE h; 150 HANDLE source, rhd, lhd;
151 151
152 if (!rw (1, socket, (char *)&pid, sizeof (pid))) 152 if (!rw (0, socket, (char *)&pid, sizeof (pid)))
153 return -1; 153 return -1;
154 154
155 if (!rw (0, socket, (char *)&h , sizeof (h ))) 155 if (!rw (0, socket, (char *)&rhd, sizeof (rhd)))
156 return -1; 156 return -1;
157 157
158 source = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
159 errno = EACCES;
160 if (!source)
161 return -1;
162
163 pid = DuplicateHandle (source, rhd, (HANDLE)-1, &lhd,
164 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
165
166 CloseHandle (source);
167
168 errno = EBADF;
169 if (!pid)
170 return -1;
171
158 return _open_osfhandle ((intptr_t)h, 0); 172 return _open_osfhandle ((intptr_t)lhd, 0);
159#else 173#else
160 void *buf = malloc (CMSG_SPACE (sizeof (int))); 174 void *buf = malloc (CMSG_SPACE (sizeof (int)));
161 175
162 if (!buf) 176 if (!buf)
163 return -1; 177 return -1;
175 msg.msg_iovlen = 1; 189 msg.msg_iovlen = 1;
176 msg.msg_control = buf; 190 msg.msg_control = buf;
177 msg.msg_controllen = CMSG_SPACE (sizeof (int)); 191 msg.msg_controllen = CMSG_SPACE (sizeof (int));
178 192
179 if (recvmsg (socket, &msg, 0) <= 0) 193 if (recvmsg (socket, &msg, 0) <= 0)
194 {
195 free (buf);
180 return -1; 196 return -1;
197 }
181 198
182 int fd = -1; 199 int fd = -1;
183 200
201 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
202
203 if (cmsg)
204 {
205 // some operating systems (i.e. osx) allow msg->cmsg_len to be larger than
206 // msg.msg_controllen, so limit the size here
207 if (cmsg->cmsg_len > CMSG_SPACE (sizeof (int)))
208 cmsg->cmsg_len = CMSG_SPACE (sizeof (int));
209
210 if ( cmsg->cmsg_level == SOL_SOCKET
211 && cmsg->cmsg_type == SCM_RIGHTS
212 && cmsg->cmsg_len >= CMSG_LEN (sizeof (int)))
213 {
214 // close any extra fd's that might have been passed.
215 // this does not work around osx/freebsad bugs where a malicious sender
216 // can send usw more fds than we can receive, leaking the extra fds,
217 // which must be fixed in the kernel, really.
218 for (fd = 1; cmsg->cmsg_len >= CMSG_LEN (sizeof (int) * (fd + 1)); ++fd)
219 close (((int *)CMSG_DATA (cmsg))[fd]);
220
221 fd = *(int *)CMSG_DATA (cmsg);
222 }
223 }
224
225 free (buf);
226
227 if (data != 0)
228 {
229 close (fd);
230 fd = -1;
231 }
232
184 errno = EDOM; 233 errno = EDOM;
185
186 if (
187 data == 0
188#if __OpenBSD__
189 && msg.msg_controllen >= CMSG_LEN (sizeof (int)) /* work around a bug in at least openbsd 4.5 and 4.8 */
190#else
191 && msg.msg_controllen >= CMSG_SPACE (sizeof (int))
192#endif
193 ) {
194 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
195
196 if (cmsg->cmsg_level == SOL_SOCKET
197 && cmsg->cmsg_type == SCM_RIGHTS
198 && cmsg->cmsg_len >= CMSG_LEN (sizeof (int)))
199 fd = *(int *)CMSG_DATA (cmsg);
200 }
201
202 free (buf);
203 234
204 return fd; 235 return fd;
205#endif 236#endif
206} 237}
207 238

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines