summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-07-23 08:13:37 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-07-23 08:13:37 +0000
commit2bcd502a71bc0a140f3b78ed0d148745fb648555 (patch)
tree45728da77bd3fb3308b21394f6f0aec15be24f9b
parentc93ed570a2991f5ec059526941f442eadacc3cb1 (diff)
* io.c (rb_update_max_fd): validate fd.
* ext/socket/rubysocket.h (rsock_discard_cmsg_resource): add msg_peek_p argument for the declaration. * ext/socket/ancdata.c (discard_cmsg): add msg_peek_p argument. assume FreeBSD, NetBSD and MacOS X doesn't generate passed fd when MSG_PEEK. (rsock_discard_cmsg_resource): add msg_peek_p argument. (bsock_recvmsg_internal): call rsock_discard_cmsg_resource with msg_peek_p argument. * ext/socket/unixsocket.c (unix_recv_io): call rsock_discard_cmsg_resource with msg_peek_p argument. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32638 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog17
-rw-r--r--ext/socket/ancdata.c36
-rw-r--r--ext/socket/rubysocket.h2
-rw-r--r--ext/socket/unixsocket.c2
-rw-r--r--io.c4
5 files changed, 42 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 28beb3c7e3..2dfae8e9a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+Sat Jul 23 17:06:25 2011 Tanaka Akira <akr@fsij.org>
+
+ * io.c (rb_update_max_fd): validate fd.
+
+ * ext/socket/rubysocket.h (rsock_discard_cmsg_resource): add
+ msg_peek_p argument for the declaration.
+
+ * ext/socket/ancdata.c (discard_cmsg): add msg_peek_p argument.
+ assume FreeBSD, NetBSD and MacOS X doesn't generate passed fd
+ when MSG_PEEK.
+ (rsock_discard_cmsg_resource): add msg_peek_p argument.
+ (bsock_recvmsg_internal): call rsock_discard_cmsg_resource with
+ msg_peek_p argument.
+
+ * ext/socket/unixsocket.c (unix_recv_io): call
+ rsock_discard_cmsg_resource with msg_peek_p argument.
+
Sat Jul 23 14:38:28 2011 Eric Hodel <drbrain@segment7.net>
* test/rake*: Remove dependencies on flexmock and session gems.
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 61e0576e6b..4fc7a561e6 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -1377,23 +1377,25 @@ rb_recvmsg(int fd, struct msghdr *msg, int flags)
#if defined(HAVE_ST_MSG_CONTROL)
static void
-discard_cmsg(struct cmsghdr *cmh, char *msg_end)
+discard_cmsg(struct cmsghdr *cmh, char *msg_end, int msg_peek_p)
{
+# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+ /*
+ * nagachika finds recvmsg with MSG_PEEK doesn't return fds on MacOS X Snow Leopard. [ruby-dev:44209]
+ * naruse finds FreeBSD behaves as so too and comment in kernel of FreeBSD 8.2.0. [ruby-dev:44189]
+ * kosaki finds same comment in MacOS X Snow Leopard. [ruby-dev:44192]
+ * Takahiro Kambe finds same comment since NetBSD 5. [ruby-dev:44205]
+ */
+ if (msg_peek_p)
+ return;
+# endif
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 ((char *)fdp + sizeof(int) <= (char *)end &&
(char *)fdp + sizeof(int) <= msg_end) {
- /*
- * xxx: nagachika said *fdp can be invalid fd on MacOS X Lion.
- * This workaround using fstat is clearly wrong.
- * we should investigate why *fdp contains invalid fd.
- */
- struct stat buf;
- if (fstat(*fdp, &buf) == 0) {
- rb_update_max_fd(*fdp);
- close(*fdp);
- }
+ rb_update_max_fd(*fdp);
+ close(*fdp);
fdp++;
}
}
@@ -1401,7 +1403,7 @@ discard_cmsg(struct cmsghdr *cmh, char *msg_end)
#endif
void
-rsock_discard_cmsg_resource(struct msghdr *mh)
+rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p)
{
#if defined(HAVE_ST_MSG_CONTROL)
struct cmsghdr *cmh;
@@ -1413,7 +1415,7 @@ rsock_discard_cmsg_resource(struct msghdr *mh)
msg_end = (char *)mh->msg_control + mh->msg_controllen;
for (cmh = CMSG_FIRSTHDR(mh); cmh != NULL; cmh = CMSG_NXTHDR(mh, cmh)) {
- discard_cmsg(cmh, msg_end);
+ discard_cmsg(cmh, msg_end, msg_peek_p);
}
#endif
}
@@ -1612,7 +1614,7 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
/* there are big space bug truncated.
* file descriptors limit? */
if (!gc_done) {
- rsock_discard_cmsg_resource(&mh);
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
goto gc_and_retry;
}
}
@@ -1633,14 +1635,14 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
}
#endif
if (grown) {
- rsock_discard_cmsg_resource(&mh);
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
goto retry;
}
else {
grow_buffer = 0;
if (flags != orig_flags) {
+ rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0);
flags = orig_flags;
- rsock_discard_cmsg_resource(&mh);
goto retry;
}
}
@@ -1680,7 +1682,7 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock)
if (request_scm_rights)
make_io_for_unix_rights(ctl, cmh, msg_end);
else
- discard_cmsg(cmh, msg_end);
+ discard_cmsg(cmh, msg_end, (flags & MSG_PEEK) != 0);
rb_ary_push(ret, ctl);
}
}
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index d7be138dfd..4c0efdb479 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -288,7 +288,7 @@ VALUE rsock_bsock_recvmsg_nonblock(int argc, VALUE *argv, VALUE sock);
#endif
#ifdef HAVE_ST_MSG_CONTROL
-void rsock_discard_cmsg_resource(struct msghdr *mh);
+void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
#endif
void rsock_init_basicsocket(void);
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
index 587caf88a0..f29724db25 100644
--- a/ext/socket/unixsocket.c
+++ b/ext/socket/unixsocket.c
@@ -367,7 +367,7 @@ 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);
+ rsock_discard_cmsg_resource(&arg.msg, 0);
rb_raise(rb_eSocket,
"file descriptor was not passed (cmsg_len=%d, %d expected)",
(int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int)));
diff --git a/io.c b/io.c
index b8d2e5bca5..a1742637df 100644
--- a/io.c
+++ b/io.c
@@ -154,6 +154,10 @@ static int max_file_descriptor = NOFILE;
void
rb_update_max_fd(int fd)
{
+ struct stat buf;
+ if (fstat(fd, &buf) != 0) {
+ rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
+ }
if (max_file_descriptor < fd) max_file_descriptor = fd;
}