… | |
… | |
32 | #include <sys/types.h> |
32 | #include <sys/types.h> |
33 | #include <sys/uio.h> |
33 | #include <sys/uio.h> |
34 | #include <sys/socket.h> |
34 | #include <sys/socket.h> |
35 | |
35 | |
36 | #ifndef CMSG_SPACE |
36 | #ifndef CMSG_SPACE |
37 | # define CMSG_SPACE(len) (sizeof (cmsghdr) + len) |
37 | # define CMSG_SPACE(len) (sizeof (struct cmsghdr) + len) |
38 | #endif |
38 | #endif |
39 | |
39 | |
40 | #ifndef CMSG_LEN |
40 | #ifndef CMSG_LEN |
41 | # define CMSG_LEN(len) (sizeof (cmsghdr) + len) |
41 | # define CMSG_LEN(len) (sizeof (struct cmsghdr) + len) |
42 | #endif |
42 | #endif |
43 | |
43 | |
44 | #endif |
44 | #endif |
45 | |
45 | |
46 | #if defined(WIN32) |
46 | #if defined(WIN32) |
… | |
… | |
189 | msg.msg_iovlen = 1; |
189 | msg.msg_iovlen = 1; |
190 | msg.msg_control = buf; |
190 | msg.msg_control = buf; |
191 | msg.msg_controllen = CMSG_SPACE (sizeof (int)); |
191 | msg.msg_controllen = CMSG_SPACE (sizeof (int)); |
192 | |
192 | |
193 | if (recvmsg (socket, &msg, 0) <= 0) |
193 | if (recvmsg (socket, &msg, 0) <= 0) |
|
|
194 | { |
|
|
195 | free (buf); |
194 | return -1; |
196 | return -1; |
|
|
197 | } |
195 | |
198 | |
196 | int fd = -1; |
199 | int fd = -1; |
197 | |
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 | |
198 | errno = EDOM; |
233 | errno = EDOM; |
199 | |
|
|
200 | if ( |
|
|
201 | data == 0 |
|
|
202 | #if __OpenBSD__ |
|
|
203 | && msg.msg_controllen >= CMSG_LEN (sizeof (int)) /* work around a bug in at least openbsd 4.5 and 4.8 */ |
|
|
204 | #else |
|
|
205 | && msg.msg_controllen >= CMSG_SPACE (sizeof (int)) |
|
|
206 | #endif |
|
|
207 | ) { |
|
|
208 | struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); |
|
|
209 | |
|
|
210 | if (cmsg->cmsg_level == SOL_SOCKET |
|
|
211 | && cmsg->cmsg_type == SCM_RIGHTS |
|
|
212 | && cmsg->cmsg_len >= CMSG_LEN (sizeof (int))) |
|
|
213 | fd = *(int *)CMSG_DATA (cmsg); |
|
|
214 | } |
|
|
215 | |
|
|
216 | free (buf); |
|
|
217 | |
234 | |
218 | return fd; |
235 | return fd; |
219 | #endif |
236 | #endif |
220 | } |
237 | } |
221 | |
238 | |