ruby-changes:11041
From: akr <ko1@a...>
Date: Wed, 25 Feb 2009 23:42:17 +0900 (JST)
Subject: [ruby-changes:11041] Ruby:r22633 (ruby_1_8): * ext/socket/socket.c (unix_recv_io): prevent FD leak when 2 fd is
akr 2009-02-25 23:39:15 +0900 (Wed, 25 Feb 2009) New Revision: 22633 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=22633 Log: * ext/socket/socket.c (unix_recv_io): prevent FD leak when 2 fd is sent on LP64 platform. (rsock_discard_cmsg_resource): new function. Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/ext/socket/socket.c Index: ruby_1_8/ext/socket/socket.c =================================================================== --- ruby_1_8/ext/socket/socket.c (revision 22632) +++ ruby_1_8/ext/socket/socket.c (revision 22633) @@ -1950,15 +1950,15 @@ } #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 @@ #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 @@ 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,20 +2145,11 @@ (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))); + 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))); } - 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); - } #else if (msg.msg_accrightslen != sizeof(fd)) { rb_raise(rb_eSocket, Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 22632) +++ ruby_1_8/ChangeLog (revision 22633) @@ -1,3 +1,9 @@ +Wed Feb 25 23:37:56 2009 Tanaka Akira <akr@f...> + + * 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@r...> * win32/Makefile.sub (config.status): use un.rb as cp instead of -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/