diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/include.am | 17 | ||||
-rw-r--r-- | src/test/test-memwipe.c | 204 | ||||
-rwxr-xr-x | src/test/test-network.sh | 2 | ||||
-rw-r--r-- | src/test/test_address.c | 176 | ||||
-rw-r--r-- | src/test/test_workqueue.c | 4 |
5 files changed, 395 insertions, 8 deletions
diff --git a/src/test/include.am b/src/test/include.am index c56e887ca0..c857ec2f89 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -1,10 +1,11 @@ -TESTS += src/test/test src/test/test-slow +TESTS += src/test/test src/test/test-slow src/test/test-memwipe noinst_PROGRAMS+= src/test/bench if UNITTESTS_ENABLED noinst_PROGRAMS+= \ src/test/test \ src/test/test-slow \ + src/test/test-memwipe \ src/test/test-child \ src/test/test_workqueue endif @@ -73,10 +74,13 @@ src_test_test_slow_SOURCES = \ src/test/testing_common.c \ src/ext/tinytest.c +src_test_test_memwipe_SOURCES = \ + src/test/test-memwipe.c + src_test_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) +src_test_test_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) src_test_bench_SOURCES = \ src/test/bench.c @@ -89,7 +93,7 @@ src_test_test_workqueue_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \ - src/common/libor-crypto-testing.a $(LIBDONNA) \ + src/common/libor-crypto-testing.a $(LIBDONNA) src/common/libor.a \ src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @@ -100,6 +104,11 @@ src_test_test_slow_CFLAGS = $(src_test_test_CFLAGS) src_test_test_slow_LDADD = $(src_test_test_LDADD) src_test_test_slow_LDFLAGS = $(src_test_test_LDFLAGS) +src_test_test_memwipe_CPPFLAGS = $(src_test_test_CPPFLAGS) +src_test_test_memwipe_CFLAGS = $(src_test_test_CFLAGS) +src_test_test_memwipe_LDADD = $(src_test_test_LDADD) +src_test_test_memwipe_LDFLAGS = $(src_test_test_LDFLAGS) + src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \ @@ -151,7 +160,7 @@ src_test_test_bt_cl_LDADD = src/common/libor-testing.a \ @TOR_LIB_MATH@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) -src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) +src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) check-local: $(NTOR_TEST_DEPS) $(CMDLINE_TEST_TOR) diff --git a/src/test/test-memwipe.c b/src/test/test-memwipe.c new file mode 100644 index 0000000000..a721a8e728 --- /dev/null +++ b/src/test/test-memwipe.c @@ -0,0 +1,204 @@ +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <stdlib.h> + +#include "crypto.h" +#include "compat.h" + +#undef MIN +#define MIN(a,b) ( ((a)<(b)) ? (a) : (b) ) + +static unsigned fill_a_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_a_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_a_buffer_nothing(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memset(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_memwipe(void) __attribute__((noinline)); +static unsigned fill_heap_buffer_nothing(void) __attribute__((noinline)); +static unsigned check_a_buffer(void) __attribute__((noinline)); + +const char *s = NULL; + +#define FILL_BUFFER_IMPL() \ + unsigned int i; \ + unsigned sum = 0; \ + \ + /* Fill up a 1k buffer with a recognizable pattern. */ \ + for (i = 0; i < 2048; i += strlen(s)) { \ + memcpy(buf+i, s, MIN(strlen(s), 2048-i)); \ + } \ + \ + /* Use the buffer as input to a computation so the above can't get */ \ + /* optimized away. */ \ + for (i = 0; i < 2048; ++i) { \ + sum += (unsigned char)buf[i]; \ + } + +static unsigned +fill_a_buffer_memset(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memset(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_memwipe(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + memwipe(buf, 0, sizeof(buf)); + return sum; +} + +static unsigned +fill_a_buffer_nothing(void) +{ + char buf[2048]; + FILL_BUFFER_IMPL() + return sum; +} + +static INLINE int +vmemeq(volatile char *a, const char *b, size_t n) +{ + while (n--) { + if (*a++ != *b++) + return 0; + } + return 1; +} + +static unsigned +check_a_buffer(void) +{ + unsigned int i; + volatile char buf[1024]; + unsigned sum = 0; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM AN UNINITIALIZED + BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static char *heap_buf = NULL; + +static unsigned +fill_heap_buffer_memset(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memset(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_memwipe(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + memwipe(buf, 0, 2048); + free(buf); + return sum; +} + +static unsigned +fill_heap_buffer_nothing(void) +{ + char *buf = heap_buf = malloc(2048); + FILL_BUFFER_IMPL() + free(buf); + return sum; +} + +static unsigned +check_heap_buffer(void) +{ + unsigned int i; + unsigned sum = 0; + volatile char *buf = heap_buf; + + /* See if this buffer has the string in it. + + YES, THIS DOES INVOKE UNDEFINED BEHAVIOR BY READING FROM A FREED BUFFER. + + If you know a better way to figure out whether the compiler eliminated + the memset/memwipe calls or not, please let me know. + */ + for (i = 0; i < sizeof(buf); ++i) { + if (vmemeq(buf+i, s, strlen(s))) + ++sum; + } + + return sum; +} + +static struct testcase { + const char *name; + unsigned (*fill_fn)(void); + unsigned (*check_fn)(void); +} testcases[] = { + { "nil", fill_a_buffer_nothing, check_a_buffer }, + { "nil-heap", fill_heap_buffer_nothing, check_heap_buffer }, + { "memset", fill_a_buffer_memset, check_a_buffer }, + { "memset-heap", fill_heap_buffer_memset, check_heap_buffer }, + { "memwipe", fill_a_buffer_memwipe, check_a_buffer }, + { "memwipe-heap", fill_heap_buffer_memwipe, check_heap_buffer }, + { NULL, NULL, NULL } +}; + +int +main(int argc, char **argv) +{ + unsigned x, x2; + int i; + int working = 1; + unsigned found[6]; + (void) argc; (void) argv; + + s = "squamous haberdasher gallimaufry"; + + memset(found, 0, sizeof(found)); + + for (i = 0; testcases[i].name; ++i) { + x = testcases[i].fill_fn(); + found[i] = testcases[i].check_fn(); + + x2 = fill_a_buffer_nothing(); + + if (x != x2) { + working = 0; + } + } + + if (!working || !found[0] || !found[1]) { + printf("It appears that this test case may not give you reliable " + "information. Sorry.\n"); + } + + if (!found[2] && !found[3]) { + printf("It appears that memset is good enough on this platform. Good.\n"); + } + + if (found[4] || found[5]) { + printf("ERROR: memwipe does not wipe data!\n"); + return 1; + } else { + printf("OKAY: memwipe seems to work."); + return 0; + } +} + diff --git a/src/test/test-network.sh b/src/test/test-network.sh index be57cafb7f..ccfb5df424 100755 --- a/src/test/test-network.sh +++ b/src/test/test-network.sh @@ -13,7 +13,7 @@ do export TOR_DIR="$2" shift ;; - --flavo?r|--network-flavo?r) + --flavor|--flavour|--network-flavor|--network-flavour) export NETWORK_FLAVOUR="$2" shift ;; diff --git a/src/test/test_address.c b/src/test/test_address.c index 424a6352b0..4bd631d39c 100644 --- a/src/test/test_address.c +++ b/src/test/test_address.c @@ -130,8 +130,8 @@ test_address_ifaddrs_to_smartlist(void *arg) ipv6_sockaddr = tor_malloc(sizeof(struct sockaddr_in6)); ipv6_sockaddr->sin6_family = AF_INET6; ipv6_sockaddr->sin6_port = 0; - inet_pton(AF_INET6, "2001:db8:8714:3a90::12", - &(ipv6_sockaddr->sin6_addr)); + tor_inet_pton(AF_INET6, "2001:db8:8714:3a90::12", + &(ipv6_sockaddr->sin6_addr)); ifa = tor_malloc(sizeof(struct ifaddrs)); ifa_ipv4 = tor_malloc(sizeof(struct ifaddrs)); @@ -452,10 +452,182 @@ test_address_get_if_addrs_ioctl(void *arg) #endif +#define FAKE_SOCKET_FD (42) + +static tor_socket_t +fake_open_socket(int domain, int type, int protocol) +{ + (void)domain; + (void)type; + (void)protocol; + + return FAKE_SOCKET_FD; +} + +static int last_connected_socket_fd = 0; + +static int connect_retval = 0; + +static tor_socket_t +pretend_to_connect(tor_socket_t socket, const struct sockaddr *address, + socklen_t address_len) +{ + (void)address; + (void)address_len; + + last_connected_socket_fd = socket; + + return connect_retval; +} + +static struct sockaddr *mock_addr = NULL; + +static int +fake_getsockname(tor_socket_t socket, struct sockaddr *address, + socklen_t *address_len) +{ + socklen_t bytes_to_copy = 0; + (void) socket; + + if (!mock_addr) + return -1; + + if (mock_addr->sa_family == AF_INET) { + bytes_to_copy = sizeof(struct sockaddr_in); + } else if (mock_addr->sa_family == AF_INET6) { + bytes_to_copy = sizeof(struct sockaddr_in6); + } else { + return -1; + } + + if (*address_len < bytes_to_copy) { + return -1; + } + + memcpy(address,mock_addr,bytes_to_copy); + *address_len = bytes_to_copy; + + return 0; +} + +static void +test_address_udp_socket_trick_whitebox(void *arg) +{ + int hack_retval; + tor_addr_t *addr_from_hack = tor_malloc_zero(sizeof(tor_addr_t)); + struct sockaddr_in6 *mock_addr6; + struct sockaddr_in6 *ipv6_to_check = + tor_malloc_zero(sizeof(struct sockaddr_in6)); + + (void)arg; + + MOCK(tor_open_socket,fake_open_socket); + MOCK(tor_connect_socket,pretend_to_connect); + MOCK(tor_getsockname,fake_getsockname); + + mock_addr = tor_malloc_zero(sizeof(struct sockaddr_storage)); + sockaddr_in_from_string("23.32.246.118",(struct sockaddr_in *)mock_addr); + + hack_retval = + get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET, addr_from_hack); + + tt_int_op(hack_retval,==,0); + tt_assert(tor_addr_eq_ipv4h(addr_from_hack, 0x1720f676)); + + /* Now, lets do an IPv6 case. */ + memset(mock_addr,0,sizeof(struct sockaddr_storage)); + + mock_addr6 = (struct sockaddr_in6 *)mock_addr; + mock_addr6->sin6_family = AF_INET6; + mock_addr6->sin6_port = 0; + tor_inet_pton(AF_INET6,"2001:cdba::3257:9652",&(mock_addr6->sin6_addr)); + + hack_retval = + get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET6, addr_from_hack); + + tt_int_op(hack_retval,==,0); + + tor_addr_to_sockaddr(addr_from_hack,0,(struct sockaddr *)ipv6_to_check, + sizeof(struct sockaddr_in6)); + + tt_assert(sockaddr_in6_are_equal(mock_addr6,ipv6_to_check)); + + UNMOCK(tor_open_socket); + UNMOCK(tor_connect_socket); + UNMOCK(tor_getsockname); + + done: + tor_free(ipv6_to_check); + tor_free(mock_addr); + tor_free(addr_from_hack); + return; +} + +static void +test_address_udp_socket_trick_blackbox(void *arg) +{ + /* We want get_interface_address6_via_udp_socket_hack() to yield + * the same valid address that get_interface_address6() returns. + * If the latter is unable to find a valid address, we want + * _hack() to fail and return-1. + * + * Furthermore, we want _hack() never to crash, even if + * get_interface_addresses_raw() is returning NULL. + */ + + tor_addr_t addr4; + tor_addr_t addr4_to_check; + tor_addr_t addr6; + tor_addr_t addr6_to_check; + int retval, retval_reference; + + (void)arg; + + retval_reference = get_interface_address6(LOG_DEBUG,AF_INET,&addr4); + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET, + &addr4_to_check); + + tt_int_op(retval,==,retval_reference); + tt_assert( (retval == -1 && retval_reference == -1) || + (tor_addr_compare(&addr4,&addr4_to_check,CMP_EXACT) == 0) ); + + //[XXX: Skipping the AF_INET6 case because bug #12377 makes it fail.] + (void)addr6_to_check; + (void)addr6; +#if 0 + retval_reference = get_interface_address6(LOG_DEBUG,AF_INET6,&addr6); + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_INET6, + &addr6_to_check); + + tt_int_op(retval,==,retval_reference); + tt_assert( (retval == -1 && retval_reference == -1) || + (tor_addr_compare(&addr6,&addr6_to_check,CMP_EXACT) == 0) ); + +#endif + + /* When family is neither AF_INET nor AF_INET6, we want _hack to + * fail and return -1. + */ + + retval = get_interface_address6_via_udp_socket_hack(LOG_DEBUG, + AF_CCITT,&addr4); + + tt_assert(retval == -1); + + done: + return; +} + #define ADDRESS_TEST(name, flags) \ { #name, test_address_ ## name, flags, NULL, NULL } struct testcase_t address_tests[] = { + ADDRESS_TEST(udp_socket_trick_whitebox, TT_FORK), + ADDRESS_TEST(udp_socket_trick_blackbox, TT_FORK), #ifdef HAVE_IFADDRS_TO_SMARTLIST ADDRESS_TEST(get_if_addrs_ifaddrs, TT_FORK), ADDRESS_TEST(ifaddrs_to_smartlist, 0), diff --git a/src/test/test_workqueue.c b/src/test/test_workqueue.c index aaff5069be..83f6f3e215 100644 --- a/src/test/test_workqueue.c +++ b/src/test/test_workqueue.c @@ -18,6 +18,8 @@ #include <event.h> #endif +#define MAX_INFLIGHT (1<<16) + static int opt_verbose = 0; static int opt_n_threads = 8; static int opt_n_items = 10000; @@ -348,7 +350,7 @@ main(int argc, char **argv) } if (opt_n_threads < 1 || opt_n_items < 1 || opt_n_inflight < 1 || opt_n_lowwater < 0 || - opt_n_cancel > opt_n_inflight || + opt_n_cancel > opt_n_inflight || opt_n_inflight > MAX_INFLIGHT || opt_ratio_rsa < 0) { help(); return 1; |