1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/socket/socket.c (unix_recv_io): prevent FD leak when 2 fd is

sent on LP64 platform.
  (rsock_discard_cmsg_resource): new function.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@22633 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2009-02-25 14:39:15 +00:00
parent 5f305864e5
commit 52a6728bd2
2 changed files with 51 additions and 17 deletions

View file

@ -1,3 +1,9 @@
Wed Feb 25 23:37:56 2009 Tanaka Akira <akr@fsij.org>
* ext/socket/socket.c (unix_recv_io): prevent FD leak when 2 fd is
sent on LP64 platform.
(rsock_discard_cmsg_resource): new function.
Wed Feb 25 22:54:13 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/Makefile.sub (config.status): use un.rb as cp instead of

View file

@ -1950,15 +1950,15 @@ unix_recvfrom(argc, argv, sock)
}
#if defined(HAVE_ST_MSG_CONTROL) && defined(SCM_RIGHTS)
#define FD_PASSING_BY_MSG_CONTROL 1
# define FD_PASSING_BY_MSG_CONTROL 1
#else
#define FD_PASSING_BY_MSG_CONTROL 0
# define FD_PASSING_BY_MSG_CONTROL 0
#endif
#if defined(HAVE_ST_MSG_ACCRIGHTS)
#define FD_PASSING_BY_MSG_ACCRIGHTS 1
# define FD_PASSING_BY_MSG_ACCRIGHTS 1
#else
#define FD_PASSING_BY_MSG_ACCRIGHTS 0
# define FD_PASSING_BY_MSG_ACCRIGHTS 0
#endif
static VALUE
@ -2027,6 +2027,28 @@ unix_send_io(sock, val)
#endif
}
#if defined(HAVE_RECVMSG) && FD_PASSING_BY_MSG_CONTROL
void
rsock_discard_cmsg_resource(struct msghdr *mh)
{
struct cmsghdr *cmh;
if (mh->msg_controllen == 0)
return;
for (cmh = CMSG_FIRSTHDR(mh); cmh != NULL; cmh = CMSG_NXTHDR(mh, cmh)) {
if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {
int *fdp = (int *)CMSG_DATA(cmh);
int *end = (int *)((char *)cmh + cmh->cmsg_len);
while (fdp < end) {
close(*fdp);
fdp++;
}
}
}
}
#endif
#if defined(HAVE_RECVMSG) && (FD_PASSING_BY_MSG_CONTROL || FD_PASSING_BY_MSG_ACCRIGHTS)
static void
thread_read_select(fd)
@ -2097,6 +2119,21 @@ unix_recv_io(argc, argv, sock)
rb_sys_fail("recvmsg(2)");
#if FD_PASSING_BY_MSG_CONTROL
if (msg.msg_controllen < sizeof(struct cmsghdr)) {
rb_raise(rb_eSocket,
"file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)",
(int)msg.msg_controllen, (int)sizeof(struct cmsghdr));
}
if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_level=%d, %d expected)",
cmsg.hdr.cmsg_level, SOL_SOCKET);
}
if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_type=%d, %d expected)",
cmsg.hdr.cmsg_type, SCM_RIGHTS);
}
if (msg.msg_controllen < CMSG_LEN(sizeof(int))) {
rb_raise(rb_eSocket,
"file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)",
@ -2108,19 +2145,10 @@ unix_recv_io(argc, argv, sock)
(int)msg.msg_controllen, (int)CMSG_SPACE(sizeof(int)));
}
if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_len=%d, %d expected)",
cmsg.hdr.cmsg_len, CMSG_LEN(sizeof(int)));
}
if (cmsg.hdr.cmsg_level != SOL_SOCKET) {
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_level=%d, %d expected)",
cmsg.hdr.cmsg_level, SOL_SOCKET);
}
if (cmsg.hdr.cmsg_type != SCM_RIGHTS) {
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_type=%d, %d expected)",
cmsg.hdr.cmsg_type, SCM_RIGHTS);
rsock_discard_cmsg_resource(&msg);
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_len=%d, %d expected)",
(int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
}
#else
if (msg.msg_accrightslen != sizeof(fd)) {