From 66647bf934760b2bb5e498169e462d9cc9a62fd6 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 27 Apr 2012 21:05:15 +0200 Subject: [PATCH] Test for setuid/setgid --- test/test-list.h | 10 ++- test/test-spawn.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 1 deletion(-) diff --git a/test/test-list.h b/test/test-list.h index 5aad6331e..8c6e9f112 100644 --- a/test/test-list.h +++ b/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) diff --git a/test/test-spawn.c b/test/test-spawn.c index 68720114b..690605174 100644 --- a/test/test-spawn.c +++ b/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