From 877433494e4a848d6c6a10d0e6521061e6a10118 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 21 Mar 2011 10:57:30 -0700 Subject: inet_diag: FD_CLOEXEC for inet_diag sockets by default Very few programs can take advantage of inheriting FDs across exec() boundaries, and inet_diag sockets have no reason to be used in this way. --- ext/raindrops/linux_inet_diag.c | 21 +++++++++++++++++++-- test/test_inet_diag_socket.rb | 3 +++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ext/raindrops/linux_inet_diag.c b/ext/raindrops/linux_inet_diag.c index 7fef77c..7f9caaa 100644 --- a/ext/raindrops/linux_inet_diag.c +++ b/ext/raindrops/linux_inet_diag.c @@ -43,6 +43,7 @@ rb_thread_blocking_region( #include #include #include +#include #include #include #include @@ -74,6 +75,21 @@ struct nogvl_args { int fd; }; +#ifdef SOCK_CLOEXEC +# define my_SOCK_RAW (SOCK_RAW|SOCK_CLOEXEC) +# define FORCE_CLOEXEC(v) (v) +#else +# define my_SOCK_RAW SOCK_RAW +static VALUE FORCE_CLOEXEC(VALUE io) +{ + int fd = my_fileno(io); + int flags = fcntl(fd, F_SETFD, FD_CLOEXEC); + if (flags == -1) + rb_sys_fail("fcntl(F_SETFD, FD_CLOEXEC)"); + return io; +} +#endif + /* * call-seq: * Raindrops::InetDiagSocket.new -> Socket @@ -83,11 +99,12 @@ struct nogvl_args { static VALUE ids_s_new(VALUE klass) { VALUE argv[3]; + argv[0] = INT2NUM(AF_NETLINK); - argv[1] = INT2NUM(SOCK_RAW); + argv[1] = INT2NUM(my_SOCK_RAW); argv[2] = INT2NUM(NETLINK_INET_DIAG); - return rb_call_super(3, argv); + return FORCE_CLOEXEC(rb_call_super(3, argv)); } /* creates a Ruby ListenStats Struct based on our internal listen_stats */ diff --git a/test/test_inet_diag_socket.rb b/test/test_inet_diag_socket.rb index c40d50e..047dff3 100644 --- a/test/test_inet_diag_socket.rb +++ b/test/test_inet_diag_socket.rb @@ -1,6 +1,7 @@ # -*- encoding: binary -*- require 'test/unit' require 'raindrops' +require 'fcntl' $stderr.sync = $stdout.sync = true class TestInetDiagSocket < Test::Unit::TestCase @@ -8,6 +9,8 @@ class TestInetDiagSocket < Test::Unit::TestCase sock = Raindrops::InetDiagSocket.new assert_kind_of Socket, sock assert_kind_of Fixnum, sock.fileno + flags = sock.fcntl(Fcntl::F_GETFD) + assert_equal Fcntl::FD_CLOEXEC, flags & Fcntl::FD_CLOEXEC assert_nil sock.close end end if RUBY_PLATFORM =~ /linux/ -- cgit v1.2.3-24-ge0c7