From a30e45f1d709cee2f3807cc461f250dab2d89630 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Sat, 2 Jun 2012 23:40:32 +0700 Subject: [PATCH] unix: remap fds 0-2 to /dev/null if ignore flag set --- src/unix/process.c | 113 +++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 45 deletions(-) diff --git a/src/unix/process.c b/src/unix/process.c index 7584d928..d3eb998c 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef __APPLE__ # include @@ -217,6 +218,68 @@ static void uv__process_close_stream(uv_stdio_container_t* container) { uv__stream_close((uv_stream_t*)container->data.stream); } + +static void uv__process_child_init(uv_process_options_t options, + int stdio_count, + int* pipes) { + int i; + + if (options.flags & UV_PROCESS_DETACHED) { + setsid(); + } + + /* Dup fds */ + for (i = 0; i < stdio_count; i++) { + /* + * stdin has swapped ends of pipe + * (it's the only one readable stream) + */ + int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2]; + int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1]; + + if (use_fd >= 0) { + close(close_fd); + } else if (i < 3) { + /* `/dev/null` stdin, stdout, stderr even if they've flag UV_IGNORE */ + use_fd = open("/dev/null", i == 0 ? O_RDONLY : O_RDWR); + + if (use_fd < 0) { + perror("failed to open stdio"); + _exit(127); + } + } else { + continue; + } + + if (i != use_fd) { + dup2(use_fd, i); + close(use_fd); + } + } + + if (options.cwd && chdir(options.cwd)) { + perror("chdir()"); + _exit(127); + } + + if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) { + perror("setgid()"); + _exit(127); + } + + if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) { + perror("setuid()"); + _exit(127); + } + + environ = options.env; + + execvp(options.file, options.args); + perror("execvp()"); + _exit(127); +} + + #ifndef SPAWN_WAIT_EXEC # define SPAWN_WAIT_EXEC 1 #endif @@ -229,7 +292,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, */ char** save_our_env = environ; - int* pipes = malloc(2 * options.stdio_count * sizeof(int)); + int stdio_count = options.stdio_count < 3 ? 3 : options.stdio_count; + int* pipes = malloc(2 * stdio_count * sizeof(int)); #if SPAWN_WAIT_EXEC int signal_pipe[2] = { -1, -1 }; @@ -258,7 +322,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, process->exit_cb = options.exit_cb; /* Init pipe pairs */ - for (i = 0; i < options.stdio_count; i++) { + for (i = 0; i < stdio_count; i++) { pipes[i * 2] = -1; pipes[i * 2 + 1] = -1; } @@ -308,49 +372,8 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, if (pid == 0) { /* Child */ - if (options.flags & UV_PROCESS_DETACHED) { - setsid(); - } + uv__process_child_init(options, stdio_count, pipes); - /* Dup fds */ - for (i = 0; i < options.stdio_count; i++) { - /* - * stdin has swapped ends of pipe - * (it's the only one readable stream) - */ - int close_fd = i == 0 ? pipes[i * 2 + 1] : pipes[i * 2]; - int use_fd = i == 0 ? pipes[i * 2] : pipes[i * 2 + 1]; - - if (use_fd >= 0) { - close(close_fd); - dup2(use_fd, i); - } else { - /* Reset flags that might be set by Node */ - uv__cloexec(i, 0); - uv__nonblock(i, 0); - } - } - - if (options.cwd && chdir(options.cwd)) { - perror("chdir()"); - _exit(127); - } - - if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) { - perror("setgid()"); - _exit(127); - } - - if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) { - perror("setuid()"); - _exit(127); - } - - environ = options.env; - - execvp(options.file, options.args); - perror("execvp()"); - _exit(127); /* Execution never reaches here. */ } @@ -399,7 +422,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, error: uv__set_sys_error(process->loop, errno); - for (i = 0; i < options.stdio_count; i++) { + for (i = 0; i < stdio_count; i++) { close(pipes[i * 2]); close(pipes[i * 2 + 1]); }