From c17b915eb8c558df1ce4089f763e520b75ad71df Mon Sep 17 00:00:00 2001 From: akr Date: Wed, 25 Feb 2009 14:03:42 +0000 Subject: [PATCH] * ext/socket/unixsocket.c (unix_recv_io): prevent FD leak when 2 fd is sent on LP64 platform. * ext/socket/rubysocket.h (rsock_discard_cmsg_resource): declared. * ext/socket/ancdata.c (rsock_discard_cmsg_resource): renamed from discard_cmsg_resource. export it. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22630 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++++++++ ext/socket/ancdata.c | 14 +++++++------- ext/socket/rubysocket.h | 4 ++++ ext/socket/unixsocket.c | 26 ++++++++++++++++---------- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1004acbf21..01b95a8e5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Wed Feb 25 23:01:26 2009 Tanaka Akira + + * ext/socket/unixsocket.c (unix_recv_io): prevent FD leak when 2 fd is + sent on LP64 platform. + + * ext/socket/rubysocket.h (rsock_discard_cmsg_resource): declared. + + * ext/socket/ancdata.c (rsock_discard_cmsg_resource): renamed from + discard_cmsg_resource. export it. + Wed Feb 25 17:31:32 2009 NAKAMURA Usaku * io.c (sysopen_func, rb_sysopen_internal, rb_sysopen): open file diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index 788e5307a8..a4aa000174 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -1300,10 +1300,10 @@ rb_recvmsg(int fd, struct msghdr *msg, int flags) return rb_thread_blocking_region(nogvl_recvmsg_func, &args, RUBY_UBF_IO, 0); } -static void -discard_cmsg_resource(struct msghdr *mh) -{ #if defined(HAVE_ST_MSG_CONTROL) +void +rsock_discard_cmsg_resource(struct msghdr *mh) +{ struct cmsghdr *cmh; if (mh->msg_controllen == 0) @@ -1319,8 +1319,8 @@ discard_cmsg_resource(struct msghdr *mh) } } } -#endif } +#endif #if defined(HAVE_ST_MSG_CONTROL) static void @@ -1505,7 +1505,7 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) /* there are big space bug truncated. * file descriptors limit? */ if (!gc_done) { - discard_cmsg_resource(&mh); + rsock_discard_cmsg_resource(&mh); goto gc_and_retry; } } @@ -1526,14 +1526,14 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) } #endif if (grown) { - discard_cmsg_resource(&mh); + rsock_discard_cmsg_resource(&mh); goto retry; } else { grow_buffer = 0; if (flags != orig_flags) { flags = orig_flags; - discard_cmsg_resource(&mh); + rsock_discard_cmsg_resource(&mh); goto retry; } } diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 3fd0b48ac5..51bf06655c 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -259,6 +259,10 @@ VALUE s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, s VALUE sockopt_new(int family, int level, int optname, VALUE data); +#ifdef HAVE_ST_MSG_CONTROL +void rsock_discard_cmsg_resource(struct msghdr *mh); +#endif + void Init_basicsocket(void); void Init_ipsocket(void); void Init_tcpsocket(void); diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c index 93d2d107a3..5f8b86099d 100644 --- a/ext/socket/unixsocket.c +++ b/ext/socket/unixsocket.c @@ -334,6 +334,21 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock) rb_sys_fail("recvmsg(2)"); #if FD_PASSING_BY_MSG_CONTROL + if (arg.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)arg.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 (arg.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)", @@ -345,20 +360,11 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock) (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int))); } if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) { + rsock_discard_cmsg_resource(&arg.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 (arg.msg.msg_accrightslen != sizeof(fd)) { rb_raise(rb_eSocket,