diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-07-31 13:51:15 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-07-31 13:51:15 -0400 |
commit | 904a58d10f144b95a689b35c88f6780371243da8 (patch) | |
tree | 174369db1cb98f3011124c306f3b06ae2b78b10d | |
parent | d5a5a6a2534e114b6c89c7ddb7840ab3040657b8 (diff) | |
parent | 8a0eedbbb08199818cd7c2c6998f062c03e33122 (diff) | |
download | tor-904a58d10f144b95a689b35c88f6780371243da8.tar.gz tor-904a58d10f144b95a689b35c88f6780371243da8.zip |
Merge branch 'bug9288_rebased'
Conflicts:
src/test/test_pt.c
-rw-r--r-- | changes/bug9288 | 4 | ||||
-rw-r--r-- | src/common/util.c | 10 | ||||
-rw-r--r-- | src/common/util.h | 21 | ||||
-rw-r--r-- | src/or/statefile.c | 4 | ||||
-rw-r--r-- | src/or/statefile.h | 2 | ||||
-rw-r--r-- | src/or/transports.c | 28 | ||||
-rw-r--r-- | src/or/transports.h | 2 | ||||
-rw-r--r-- | src/test/test_pt.c | 89 |
8 files changed, 131 insertions, 29 deletions
diff --git a/changes/bug9288 b/changes/bug9288 new file mode 100644 index 0000000000..59bf414ea1 --- /dev/null +++ b/changes/bug9288 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Fix an invalid memory read that occured when a pluggable + transport proxy failed its configuration protocol. + Fixes bug 9288. diff --git a/src/common/util.c b/src/common/util.c index 0e8d34eafd..849a7178c6 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -3966,9 +3966,9 @@ tor_spawn_background(const char *const filename, const char **argv, * <b>process_handle</b>. * If <b>also_terminate_process</b> is true, also terminate the * process of the process handle. */ -void -tor_process_handle_destroy(process_handle_t *process_handle, - int also_terminate_process) +MOCK_IMPL(void, +tor_process_handle_destroy,(process_handle_t *process_handle, + int also_terminate_process)) { if (!process_handle) return; @@ -4567,8 +4567,8 @@ log_from_handle(HANDLE *pipe, int severity) /** Return a smartlist containing lines outputted from * <b>handle</b>. Return NULL on error, and set * <b>stream_status_out</b> appropriately. */ -smartlist_t * -tor_get_lines_from_handle(FILE *handle, enum stream_status *stream_status_out) +MOCK_IMPL(smartlist_t *, +tor_get_lines_from_handle,(FILE *handle, enum stream_status *stream_status_out)) { enum stream_status stream_status; char stdout_buf[400]; diff --git a/src/common/util.h b/src/common/util.h index 0a8e4a23fc..dd7a169a1b 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -492,18 +492,21 @@ FILE *tor_process_get_stdout_pipe(process_handle_t *process_handle); #endif #ifdef _WIN32 -struct smartlist_t * -tor_get_lines_from_handle(HANDLE *handle, - enum stream_status *stream_status); +MOCK_DECL(struct smartlist_t *, +tor_get_lines_from_handle,(HANDLE *handle, + enum stream_status *stream_status)); #else -struct smartlist_t * -tor_get_lines_from_handle(FILE *handle, - enum stream_status *stream_status); +MOCK_DECL(struct smartlist_t *, +tor_get_lines_from_handle,(FILE *handle, + enum stream_status *stream_status)); #endif -int tor_terminate_process(process_handle_t *process_handle); -void tor_process_handle_destroy(process_handle_t *process_handle, - int also_terminate_process); +int +tor_terminate_process(process_handle_t *process_handle); + +MOCK_DECL(void, +tor_process_handle_destroy,(process_handle_t *process_handle, + int also_terminate_process)); /* ===== Insecure rng */ typedef struct tor_weak_rng_t { diff --git a/src/or/statefile.c b/src/or/statefile.c index bcb7b07417..aac8850b16 100644 --- a/src/or/statefile.c +++ b/src/or/statefile.c @@ -117,8 +117,8 @@ static const config_format_t state_format = { static or_state_t *global_state = NULL; /** Return the persistent state struct for this Tor. */ -or_state_t * -get_or_state(void) +MOCK_IMPL(or_state_t *, +get_or_state, (void)) { tor_assert(global_state); return global_state; diff --git a/src/or/statefile.h b/src/or/statefile.h index dcdee6c604..762b0f5ee1 100644 --- a/src/or/statefile.h +++ b/src/or/statefile.h @@ -7,7 +7,7 @@ #ifndef TOR_STATEFILE_H #define TOR_STATEFILE_H -or_state_t *get_or_state(void); +MOCK_DECL(or_state_t *,get_or_state,(void)); int did_last_state_file_write_fail(void); int or_state_save(time_t now); diff --git a/src/or/transports.c b/src/or/transports.c index 15faa98d40..62cc1a864f 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -103,8 +103,6 @@ create_managed_proxy_environment(const managed_proxy_t *mp); static INLINE int proxy_configuration_finished(const managed_proxy_t *mp); static void handle_finished_proxy(managed_proxy_t *mp); -static void configure_proxy(managed_proxy_t *mp); - static void parse_method_error(const char *line, int is_server_method); #define parse_server_method_error(l) parse_method_error(l, 1) #define parse_client_method_error(l) parse_method_error(l, 0) @@ -574,10 +572,8 @@ pt_configure_remaining_proxies(void) /* If the proxy is not fully configured, try to configure it futher. */ if (!proxy_configuration_finished(mp)) - configure_proxy(mp); - - if (proxy_configuration_finished(mp)) - at_least_a_proxy_config_finished = 1; + if (configure_proxy(mp) == 1) + at_least_a_proxy_config_finished = 1; } SMARTLIST_FOREACH_END(mp); @@ -589,10 +585,14 @@ pt_configure_remaining_proxies(void) mark_my_descriptor_dirty("configured managed proxies"); } -/** Attempt to continue configuring managed proxy <b>mp</b>. */ -static void +/** Attempt to continue configuring managed proxy <b>mp</b>. + * Return 1 if the transport configuration finished, and return 0 + * otherwise (if we still have more configuring to do for this + * proxy). */ +STATIC int configure_proxy(managed_proxy_t *mp) { + int configuration_finished = 0; smartlist_t *proxy_output = NULL; enum stream_status stream_status = 0; @@ -602,7 +602,7 @@ configure_proxy(managed_proxy_t *mp) mp->conf_state = PT_PROTO_FAILED_LAUNCH; handle_finished_proxy(mp); } - return; + return 0; } tor_assert(mp->conf_state != PT_PROTO_INFANT); @@ -634,13 +634,17 @@ configure_proxy(managed_proxy_t *mp) done: /* if the proxy finished configuring, exit the loop. */ - if (proxy_configuration_finished(mp)) + if (proxy_configuration_finished(mp)) { handle_finished_proxy(mp); + configuration_finished = 1; + } if (proxy_output) { SMARTLIST_FOREACH(proxy_output, char *, cp, tor_free(cp)); smartlist_free(proxy_output); } + + return configuration_finished; } /** Register server managed proxy <b>mp</b> transports to state */ @@ -709,7 +713,8 @@ managed_proxy_destroy(managed_proxy_t *mp, smartlist_free(mp->transports_to_launch); /* remove it from the list of managed proxies */ - smartlist_remove(managed_proxy_list, mp); + if (managed_proxy_list) + smartlist_remove(managed_proxy_list, mp); /* free the argv */ free_execve_args(mp->argv); @@ -746,7 +751,6 @@ handle_finished_proxy(managed_proxy_t *mp) } unconfigured_proxies_n--; - tor_assert(unconfigured_proxies_n >= 0); } /** Return true if the configuration of the managed proxy <b>mp</b> is diff --git a/src/or/transports.h b/src/or/transports.h index 1c6fc419b7..7b524f2073 100644 --- a/src/or/transports.h +++ b/src/or/transports.h @@ -121,6 +121,8 @@ STATIC void managed_proxy_destroy(managed_proxy_t *mp, STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list, char **proxy_argv, int is_server); +STATIC int configure_proxy(managed_proxy_t *mp); + #endif #endif diff --git a/src/test/test_pt.c b/src/test/test_pt.c index ac97cf9fb0..f969457d0e 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -5,11 +5,14 @@ #include "orconfig.h" #define PT_PRIVATE +#define UTIL_PRIVATE #include "or.h" #include "config.h" #include "confparse.h" #include "transports.h" #include "circuitbuild.h" +#include "util.h" +#include "statefile.h" #include "test.h" static void @@ -269,6 +272,90 @@ test_pt_get_extrainfo_string(void *arg) tor_free(s); } +#ifdef _WIN32 +#define STDIN_HANDLE HANDLE +#else +#define STDIN_HANDLE FILE +#endif + +static smartlist_t * +tor_get_lines_from_handle_replacement(STDIN_HANDLE *handle, + enum stream_status *stream_status_out) +{ + static int times_called = 0; + smartlist_t *retval_sl = smartlist_new(); + + (void) handle; + (void) stream_status_out; + + /* Generate some dummy CMETHOD lines the first 5 times. The 6th + time, send 'CMETHODS DONE' to finish configuring the proxy. */ + if (times_called++ != 5) { + smartlist_add_asprintf(retval_sl, "CMETHOD mock%d socks5 127.0.0.1:555%d", + times_called, times_called); + } else { + smartlist_add(retval_sl, tor_strdup("CMETHODS DONE")); + } + + return retval_sl; +} + +/* NOP mock */ +static void +tor_process_handle_destroy_replacement(process_handle_t *process_handle, + int also_terminate_process) +{ + (void) process_handle; + (void) also_terminate_process; +} + +static or_state_t *dummy_state = NULL; + +static or_state_t * +get_or_state_replacement(void) +{ + return dummy_state; +} + +/* Test the configure_proxy() function. */ +static void +test_pt_configure_proxy(void *arg) +{ + int i; + managed_proxy_t *mp = NULL; + (void) arg; + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + MOCK(tor_get_lines_from_handle, + tor_get_lines_from_handle_replacement); + MOCK(tor_process_handle_destroy, + tor_process_handle_destroy_replacement); + MOCK(get_or_state, + get_or_state_replacement); + + mp = tor_malloc(sizeof(managed_proxy_t)); + mp->conf_state = PT_PROTO_ACCEPTING_METHODS; + mp->transports = smartlist_new(); + mp->transports_to_launch = smartlist_new(); + mp->process_handle = tor_malloc_zero(sizeof(process_handle_t)); + mp->argv = tor_malloc_zero(sizeof(char*)*2); + mp->argv[0] = tor_strdup("<testcase>"); + + /* Test the return value of configure_proxy() by calling it some + times while it is uninitialized and then finally finalizing its + configuration. */ + for (i = 0 ; i < 5 ; i++) { + test_assert(configure_proxy(mp) == 0); + } + test_assert(configure_proxy(mp) == 1); + + done: + tor_free(dummy_state); + UNMOCK(tor_get_lines_from_handle); + UNMOCK(tor_process_handle_destroy); +} + #define PT_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name } @@ -279,6 +366,8 @@ struct testcase_t pt_tests[] = { NULL, NULL }, { "get_extrainfo_string", test_pt_get_extrainfo_string, TT_FORK, NULL, NULL }, + { "configure_proxy",test_pt_configure_proxy, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; |