diff --git a/test/test-list.h b/test/test-list.h index e43f0525..84782b2a 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -118,6 +118,8 @@ TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) TEST_DECLARE (spawn_and_kill_with_std) 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) @@ -142,7 +144,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) @@ -164,6 +166,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) @@ -316,6 +320,8 @@ TASK_LIST_START TEST_ENTRY (spawn_and_kill) TEST_ENTRY (spawn_and_kill_with_std) 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) @@ -324,6 +330,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) diff --git a/test/test-spawn.c b/test/test-spawn.c index 2e1d2759..fbe92335 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -55,6 +55,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; @@ -115,6 +131,7 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) { options.file = exepath; options.args = args; options.exit_cb = exit_cb; + options.flags = 0; } @@ -517,3 +534,145 @@ 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_options("spawn_helper1", exit_cb); + + // become the "nobody" user. + struct passwd* pw; + pw = getpwnam("nobody"); + ASSERT(pw != NULL); + options.uid = pw->pw_uid; + options.gid = pw->pw_gid; + options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; + + r = uv_spawn(uv_default_loop(), &process, options); + 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_options("spawn_helper1", exit_cb_failure_expected); + + options.flags |= UV_PROCESS_SETUID; + options.uid = (uv_uid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + 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_options("spawn_helper1", exit_cb_failure_expected); + + options.flags |= UV_PROCESS_SETGID; + options.gid = (uv_gid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + 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_options("spawn_helper1", exit_cb_unexpected); + + options.flags |= UV_PROCESS_SETUID; + options.uid = (uv_uid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == -1); + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP); + + 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_options("spawn_helper1", exit_cb_unexpected); + + options.flags |= UV_PROCESS_SETGID; + options.gid = (uv_gid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == -1); + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(close_cb_called == 0); + + return 0; +} +#endif