Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

uv: upgrade to aea5db5da1

  • Loading branch information...
commit e221cd4a53160c87a1a021916c9a865d53783be2 1 parent 76de7c0
@piscisaureus piscisaureus authored
View
5 deps/uv/include/uv-private/uv-unix.h
@@ -33,6 +33,7 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
+#include <pwd.h>
#include <termios.h>
/* Note: May be cast to struct iovec. See writev(2). */
@@ -43,6 +44,10 @@ typedef struct {
typedef int uv_file;
+/* Platform-specific definitions for uv_spawn support. */
+typedef gid_t uv_gid_t;
+typedef uid_t uv_uid_t;
+
/* Platform-specific definitions for uv_dlopen support. */
typedef void* uv_lib_t;
#define UV_DYNAMIC /* empty */
View
4 deps/uv/include/uv-private/uv-win.h
@@ -137,6 +137,10 @@ typedef struct uv_buf_t {
typedef int uv_file;
+/* Platform-specific definitions for uv_spawn support. */
+typedef unsigned char uv_uid_t;
+typedef unsigned char uv_gid_t;
+
/* Platform-specific definitions for uv_dlopen support. */
typedef HMODULE uv_lib_t;
#define UV_DYNAMIC FAR WINAPI
View
28 deps/uv/include/uv.h
@@ -1058,6 +1058,34 @@ struct uv_process_s {
UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*,
uv_process_options_t options);
+
+/* Temporary fix for node. Do no use. */
+enum uv_process_flags {
+ UV_PROCESS_SETUID = (1 << 0),
+ UV_PROCESS_SETGID = (1 << 1),
+ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2)
+};
+
+/* Temporary fix for node. Do not use. */
+typedef struct uv_process_options2_s {
+ uv_exit_cb exit_cb; /* Called after the process exits. */
+ const char* file; /* Path to program to execute. */
+ char** args;
+ char** env;
+ char* cwd;
+ unsigned int flags;
+ uv_pipe_t* stdin_stream;
+ uv_pipe_t* stdout_stream;
+ uv_pipe_t* stderr_stream;
+ uv_uid_t uid;
+ uv_gid_t gid;
+} uv_process_options2_t;
+
+/* Temporary fix for node. Do not use. */
+UV_EXTERN int uv_spawn2(uv_loop_t*, uv_process_t*,
+ uv_process_options2_t options);
+
+
/*
* Kills the process with the specified signal. The user must still
* call uv_close on the process.
View
4 deps/uv/src/unix/error.c
@@ -68,6 +68,9 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case EBADF: return UV_EBADF;
case EPIPE: return UV_EPIPE;
case EAGAIN: return UV_EAGAIN;
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK: return UV_EAGAIN;
+#endif
case ECONNRESET: return UV_ECONNRESET;
case EFAULT: return UV_EFAULT;
case EMFILE: return UV_EMFILE;
@@ -91,6 +94,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
case EBUSY: return UV_EBUSY;
case ENOTEMPTY: return UV_ENOTEMPTY;
case ENOSPC: return UV_ENOSPC;
+ case ENOMEM: return UV_ENOMEM;
default: return UV_UNKNOWN;
}
View
1  deps/uv/src/unix/linux.c
@@ -271,6 +271,7 @@ int uv_fs_event_init(uv_loop_t* loop,
| IN_MODIFY
| IN_DELETE
| IN_DELETE_SELF
+ | IN_MOVE_SELF
| IN_MOVED_FROM
| IN_MOVED_TO;
View
7 deps/uv/src/unix/pipe.c
@@ -254,16 +254,15 @@ void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) {
sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr);
if (sockfd == -1) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- assert(0 && "EAGAIN on uv__accept(pipefd)");
- } else {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
uv__set_sys_error(pipe->loop, errno);
+ pipe->connection_cb((uv_stream_t*)pipe, -1);
}
} else {
pipe->accepted_fd = sockfd;
pipe->connection_cb((uv_stream_t*)pipe, 0);
if (pipe->accepted_fd == sockfd) {
- /* The user hasn't yet accepted called uv_accept() */
+ /* The user hasn't called uv_accept() yet */
ev_io_stop(pipe->loop->ev, &pipe->read_watcher);
}
}
View
20 deps/uv/src/unix/process.c
@@ -161,8 +161,8 @@ static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) {
# define SPAWN_WAIT_EXEC 1
#endif
-int uv_spawn(uv_loop_t* loop, uv_process_t* process,
- uv_process_options_t options) {
+int uv_spawn2(uv_loop_t* loop, uv_process_t* process,
+ uv_process_options2_t options) {
/*
* Save environ in the case that we get it clobbered
* by the child process.
@@ -179,6 +179,12 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
pid_t pid;
int flags;
+ assert(options.file != NULL);
+ assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
+ UV_PROCESS_SETGID |
+ UV_PROCESS_SETUID)));
+
+
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
loop->counters.process_init++;
@@ -268,6 +274,16 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
_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);
View
6 deps/uv/src/unix/stream.c
@@ -176,7 +176,7 @@ void uv__server_io(EV_P_ ev_io* watcher, int revents) {
fd = uv__accept(stream->fd, (struct sockaddr*)&addr, sizeof addr);
if (fd < 0) {
- if (errno == EAGAIN) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* No problem. */
return;
} else if (errno == EMFILE) {
@@ -416,7 +416,7 @@ static void uv__write(uv_stream_t* stream) {
}
if (n < 0) {
- if (errno != EAGAIN) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
/* Error */
req->error = errno;
stream->write_queue_size -= uv__write_req_size(req);
@@ -562,7 +562,7 @@ static void uv__read(uv_stream_t* stream) {
if (nread < 0) {
/* Error */
- if (errno == EAGAIN) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* Wait for the next one. */
if (stream->flags & UV_READING) {
ev_io_start(ev, &stream->read_watcher);
View
26 deps/uv/src/uv-common.c
@@ -261,3 +261,29 @@ int uv_tcp_connect6(uv_connect_t* req,
return uv__tcp_connect6(req, handle, address, cb);
}
+
+
+/* Thunk that converts uv_process_options_t into uv_process_options2_t, */
+/* and then calls uv_spawn2. */
+int uv_spawn(uv_loop_t* loop, uv_process_t* process,
+ uv_process_options_t options) {
+ uv_process_options2_t options2;
+
+ options2.exit_cb = options.exit_cb;
+ options2.file = options.file;
+ options2.args = options.args;
+ options2.cwd = options.cwd;
+ options2.env = options.env;
+ options2.stdin_stream = options.stdin_stream;
+ options2.stdout_stream = options.stdout_stream;
+ options2.stderr_stream = options.stderr_stream;
+
+ options2.flags = 0;
+ if (options.windows_verbatim_arguments) {
+ options2.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
+ }
+
+ /* No need to set gid and uid. */
+
+ return uv_spawn2(loop, process, options2);
+}
View
2  deps/uv/src/win/error.c
@@ -68,6 +68,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
switch (sys_errno) {
case ERROR_SUCCESS: return UV_OK;
case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
+ case ERROR_INVALID_NAME: return UV_ENOENT;
+ case ERROR_MOD_NOT_FOUND: return UV_ENOENT;
case ERROR_PATH_NOT_FOUND: return UV_ENOENT;
case ERROR_ACCESS_DENIED: return UV_EPERM;
case ERROR_NOACCESS: return UV_EACCES;
View
2  deps/uv/src/win/fs.c
@@ -913,7 +913,7 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) {
fs__fsync(req, (uv_file)req->arg0);
break;
case UV_FS_FTRUNCATE:
- fs__ftruncate(req, (uv_file)req->arg0, (off_t)req->stat.st_atime);
+ fs__ftruncate(req, (uv_file)req->arg0, req->stat.st_atime);
break;
case UV_FS_SENDFILE:
fs__sendfile(req,
View
15 deps/uv/src/win/process.c
@@ -860,8 +860,8 @@ static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
}
-int uv_spawn(uv_loop_t* loop, uv_process_t* process,
- uv_process_options_t options) {
+int uv_spawn2(uv_loop_t* loop, uv_process_t* process,
+ uv_process_options2_t options) {
int err = 0, keep_child_stdio_open = 0;
wchar_t* path = NULL;
int size;
@@ -872,17 +872,22 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
STARTUPINFOW startup;
PROCESS_INFORMATION info;
- if (!options.file) {
- uv__set_artificial_error(loop, UV_EINVAL);
+ if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
+ uv__set_sys_error(loop, UV_ENOTSUP);
return -1;
}
+ assert(options.file != NULL);
+ assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
+ UV_PROCESS_SETGID |
+ UV_PROCESS_SETUID)));
+
uv_process_init(loop, process);
process->exit_cb = options.exit_cb;
UTF8_TO_UTF16(options.file, application);
arguments = options.args ? make_program_args(options.args,
- options.windows_verbatim_arguments) : NULL;
+ options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS) : NULL;
env = options.env ? make_program_env(options.env) : NULL;
if (options.cwd) {
View
10 deps/uv/test/test-list.h
@@ -110,6 +110,8 @@ TEST_DECLARE (spawn_stdout)
TEST_DECLARE (spawn_stdin)
TEST_DECLARE (spawn_and_kill)
TEST_DECLARE (spawn_and_ping)
+TEST_DECLARE (spawn_setuid_fails)
+TEST_DECLARE (spawn_setgid_fails)
TEST_DECLARE (kill)
TEST_DECLARE (fs_file_noent)
TEST_DECLARE (fs_file_nametoolong)
@@ -133,7 +135,7 @@ TEST_DECLARE (fs_event_watch_file_current_dir)
TEST_DECLARE (fs_event_no_callback_on_close)
TEST_DECLARE (fs_event_immediate_close)
TEST_DECLARE (fs_event_close_with_pending_event)
-TEST_DECLARE (fs_event_close_in_callback);
+TEST_DECLARE (fs_event_close_in_callback)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (fs_readdir_file)
TEST_DECLARE (fs_open_dir)
@@ -147,6 +149,8 @@ TEST_DECLARE (environment_creation)
TEST_DECLARE (listen_with_simultaneous_accepts)
TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
+#else
+TEST_DECLARE (spawn_setuid_setgid)
#endif
HELPER_DECLARE (tcp4_echo_server)
HELPER_DECLARE (tcp6_echo_server)
@@ -289,6 +293,8 @@ TASK_LIST_START
TEST_ENTRY (spawn_stdin)
TEST_ENTRY (spawn_and_kill)
TEST_ENTRY (spawn_and_ping)
+ TEST_ENTRY (spawn_setuid_fails)
+ TEST_ENTRY (spawn_setgid_fails)
TEST_ENTRY (kill)
#ifdef _WIN32
TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows)
@@ -297,6 +303,8 @@ TASK_LIST_START
TEST_ENTRY (listen_with_simultaneous_accepts)
TEST_ENTRY (listen_no_simultaneous_accepts)
TEST_ENTRY (fs_stat_root)
+#else
+ TEST_ENTRY (spawn_setuid_setgid)
#endif
TEST_ENTRY (fs_file_noent)
View
173 deps/uv/test/test-spawn.c
@@ -30,6 +30,7 @@ static int exit_cb_called;
static uv_process_t process;
static uv_timer_t timer;
static uv_process_options_t options;
+static uv_process_options2_t options2;
static char exepath[1024];
static size_t exepath_size = 1024;
static char* args[3];
@@ -55,6 +56,22 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) {
}
+static void exit_cb_failure_expected(uv_process_t* process, int exit_status,
+ int term_signal) {
+ printf("exit_cb\n");
+ exit_cb_called++;
+ ASSERT(exit_status == 127);
+ ASSERT(term_signal == 0);
+ uv_close((uv_handle_t*)process, close_cb);
+}
+
+
+static void exit_cb_unexpected(uv_process_t* process, int exit_status,
+ int term_signal) {
+ ASSERT(0 && "should not have been called");
+}
+
+
static void kill_cb(uv_process_t* process, int exit_status, int term_signal) {
uv_err_t err;
@@ -116,6 +133,22 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) {
options.file = exepath;
options.args = args;
options.exit_cb = exit_cb;
+ options.windows_verbatim_arguments = 0;
+}
+
+
+static void init_process_options2(char* test, uv_exit_cb exit_cb) {
+ /* Note spawn_helper1 defined in test/run-tests.c */
+ int r = uv_exepath(exepath, &exepath_size);
+ ASSERT(r == 0);
+ exepath[exepath_size] = '\0';
+ args[0] = exepath;
+ args[1] = test;
+ args[2] = NULL;
+ options2.file = exepath;
+ options2.args = args;
+ options2.exit_cb = exit_cb;
+ options2.flags = 0;
}
@@ -466,3 +499,143 @@ TEST_IMPL(environment_creation) {
return 0;
}
#endif
+
+#ifndef _WIN32
+TEST_IMPL(spawn_setuid_setgid) {
+ int r;
+
+ /* if not root, then this will fail. */
+ uv_uid_t uid = getuid();
+ if (uid != 0) {
+ fprintf(stderr, "spawn_setuid_setgid skipped: not root\n");
+ return 0;
+ }
+
+ init_process_options2("spawn_helper1", exit_cb);
+
+ // become the "nobody" user.
+ struct passwd* pw;
+ pw = getpwnam("nobody");
+ ASSERT(pw != NULL);
+ options2.uid = pw->pw_uid;
+ options2.gid = pw->pw_gid;
+ options2.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID;
+
+ r = uv_spawn2(uv_default_loop(), &process, options2);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop());
+ ASSERT(r == 0);
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ return 0;
+}
+#endif
+
+
+#ifndef _WIN32
+TEST_IMPL(spawn_setuid_fails) {
+ int r;
+
+ /* if root, become nobody. */
+ uv_uid_t uid = getuid();
+ if (uid == 0) {
+ struct passwd* pw;
+ pw = getpwnam("nobody");
+ ASSERT(pw != NULL);
+ r = setuid(pw->pw_uid);
+ ASSERT(r == 0);
+ }
+
+ init_process_options2("spawn_helper1", exit_cb_failure_expected);
+
+ options2.flags |= UV_PROCESS_SETUID;
+ options2.uid = (uv_uid_t) -42424242;
+
+ r = uv_spawn2(uv_default_loop(), &process, options2);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop());
+ ASSERT(r == 0);
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ return 0;
+}
+
+
+TEST_IMPL(spawn_setgid_fails) {
+ int r;
+
+ /* if root, become nobody. */
+ uv_uid_t uid = getuid();
+ if (uid == 0) {
+ struct passwd* pw;
+ pw = getpwnam("nobody");
+ ASSERT(pw != NULL);
+ r = setuid(pw->pw_uid);
+ ASSERT(r == 0);
+ }
+
+ init_process_options2("spawn_helper1", exit_cb_failure_expected);
+
+ options2.flags |= UV_PROCESS_SETGID;
+ options2.gid = (uv_gid_t) -42424242;
+
+ r = uv_spawn2(uv_default_loop(), &process, options2);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop());
+ ASSERT(r == 0);
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ return 0;
+}
+#endif
+
+
+#ifdef _WIN32
+TEST_IMPL(spawn_setuid_fails) {
+ int r;
+
+ init_process_options2("spawn_helper1", exit_cb_unexpected);
+
+ options2.flags |= UV_PROCESS_SETUID;
+ options2.uid = (uv_uid_t) -42424242;
+
+ r = uv_spawn2(uv_default_loop(), &process, options2);
+ ASSERT(r == -1);
+
+ r = uv_run(uv_default_loop());
+ ASSERT(r == 0);
+
+ ASSERT(close_cb_called == 0);
+
+ return 0;
+}
+
+
+TEST_IMPL(spawn_setgid_fails) {
+ int r;
+
+ init_process_options2("spawn_helper1", exit_cb_unexpected);
+
+ options2.flags |= UV_PROCESS_SETGID;
+ options2.gid = (uv_gid_t) -42424242;
+
+ r = uv_spawn2(uv_default_loop(), &process, options2);
+ ASSERT(r == -1);
+
+ r = uv_run(uv_default_loop());
+ ASSERT(r == 0);
+
+ ASSERT(close_cb_called == 0);
+
+ return 0;
+}
+#endif
Please sign in to comment.
Something went wrong with that request. Please try again.