From b9979f380f1dc8bbde89c16b0fa25a67f9bc1830 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 21 Apr 2013 03:22:26 +0000 Subject: [PATCH] set close-on-exec in pipe size modification check This prevents a file descriptor leak in case another thread forks and execs while we are in the middle of loading. This places a hard dependency on pipe2, but pipe2 appeared in Linux before pipe size modification. --- ext/io_splice/extconf.rb | 1 + ext/io_splice/io_splice_ext.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ext/io_splice/extconf.rb b/ext/io_splice/extconf.rb index 27127c8..52dab83 100644 --- a/ext/io_splice/extconf.rb +++ b/ext/io_splice/extconf.rb @@ -3,6 +3,7 @@ $CPPFLAGS << ' -D_GNU_SOURCE=1' have_func('splice', %w(fcntl.h)) or abort 'splice(2) not defined' have_func('tee', %w(fcntl.h)) or abort 'tee(2) not defined' +have_func('pipe2', %w(fcntl.h unistd.h)) have_func('rb_thread_blocking_region') have_macro('F_GETPIPE_SZ', %w(fcntl.h)) have_macro('F_SETPIPE_SZ', %w(fcntl.h)) diff --git a/ext/io_splice/io_splice_ext.c b/ext/io_splice/io_splice_ext.c index e429266..1c938c3 100644 --- a/ext/io_splice/io_splice_ext.c +++ b/ext/io_splice/io_splice_ext.c @@ -619,8 +619,14 @@ static VALUE set_pipe_size(VALUE self, VALUE size) static int can_mod_pipe_size(void) { + /* + * pipe2 appeared in Linux 2.6.27, F_*PIPE_SZ appeared in 2.6.35, + * thus not having pipe2 automatically disqualifies us from having + * F_*PIPE_SZ support + */ +#ifdef HAVE_PIPE2 int fds[2]; - int rc = pipe(fds); + int rc = pipe2(fds, O_CLOEXEC); if (rc == 0) { rc = fcntl(fds[0], F_GETPIPE_SZ); @@ -629,11 +635,17 @@ static int can_mod_pipe_size(void) (void)close(fds[0]); (void)close(fds[1]); } else { - /* weird error, but don't raise during init */ + /* + * weird error, but don't raise during init, this could be + * ENOSYS, even.. + */ rc = 0; } errno = 0; return rc; +#else /* ! HAVE_PIPE2 */ + return 0; +#endif /* ! HAVE_PIPE2 */ } void Init_io_splice_ext(void) -- 2.11.4.GIT