[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]