summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-25 14:03:42 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-25 14:03:42 +0000
commitc17b915eb8c558df1ce4089f763e520b75ad71df (patch)
tree31e084992be8f5ae0fcc6c598cd7b56dd9c4d9bc /ext
parenta898f0fb4b8e31d86a372f7d1438823195015249 (diff)
* 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
Diffstat (limited to 'ext')
-rw-r--r--ext/socket/ancdata.c14
-rw-r--r--ext/socket/rubysocket.h4
-rw-r--r--ext/socket/unixsocket.c26
3 files changed, 27 insertions, 17 deletions
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 788e530..a4aa000 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 3fd0b48..51bf066 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 93d2d10..5f8b860 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,