… | |
… | |
195 | free (buf); |
195 | free (buf); |
196 | return -1; |
196 | return -1; |
197 | } |
197 | } |
198 | |
198 | |
199 | int fd = -1; |
199 | int fd = -1; |
|
|
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 | |
200 | errno = EDOM; |
233 | errno = EDOM; |
201 | |
|
|
202 | struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); |
|
|
203 | |
|
|
204 | if (data == 0 |
|
|
205 | && cmsg |
|
|
206 | && cmsg->cmsg_level == SOL_SOCKET |
|
|
207 | && cmsg->cmsg_type == SCM_RIGHTS |
|
|
208 | && cmsg->cmsg_len >= CMSG_LEN (sizeof (int))) |
|
|
209 | fd = *(int *)CMSG_DATA (cmsg); |
|
|
210 | |
|
|
211 | free (buf); |
|
|
212 | |
234 | |
213 | return fd; |
235 | return fd; |
214 | #endif |
236 | #endif |
215 | } |
237 | } |
216 | |
238 | |