From 74299cf58fefb3cdde23444bd12e6e212a4c99af Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 14 Jun 2021 11:11:16 +1000 Subject: test: add threading test for object creation In addition, rework the multi tests to use common code. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15713) (cherry picked from commit 0855591e1f3559313641c13e4b7ce900ce42321c) Reviewed-by: Hugo Landau --- test/threadstest.c | 273 ++++++++++++++++++++++++++--------------------------- 1 file changed, 135 insertions(+), 138 deletions(-) (limited to 'test') diff --git a/test/threadstest.c b/test/threadstest.c index 289565c14b..c4e86465e1 100644 --- a/test/threadstest.c +++ b/test/threadstest.c @@ -7,8 +7,13 @@ * https://www.openssl.org/source/license.html */ -/* test_multi below tests the thread safety of a deprecated function */ -#define OPENSSL_SUPPRESS_DEPRECATED +/* + * The test_multi_downgrade_shared_pkey function tests the thread safety of a + * deprecated function. + */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define OPENSSL_SUPPRESS_DEPRECATED +#endif #if defined(_WIN32) # include @@ -18,7 +23,9 @@ #include #include #include -#include +#include +#include "internal/tsan_assist.h" +#include "internal/nelem.h" #include "testutil.h" #include "threadstest.h" @@ -32,7 +39,22 @@ static int do_fips = 0; static char *privkey; static char *config_file = NULL; static int multidefault_run = 0; + static const char *default_provider[] = { "default", NULL }; +static const char *fips_provider[] = { "fips", NULL }; +static const char *fips_and_default_providers[] = { "default", "fips", NULL }; + +/* Grab a globally unique integer value */ +static int get_new_uid(void) +{ + /* + * Start with a nice large number to avoid potential conflicts when + * we generate a new OID. + */ + static TSAN_QUALIFIER int current_uid = 1 << (sizeof(int) * 8 - 2); + + return tsan_counter(¤t_uid); +} static int test_lock(void) { @@ -432,21 +454,6 @@ static void thread_shared_evp_pkey(void) multi_success = 0; } -static void thread_downgrade_shared_evp_pkey(void) -{ -#ifndef OPENSSL_NO_DEPRECATED_3_0 - /* - * This test is only relevant for deprecated functions that perform - * downgrading - */ - if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL) - multi_success = 0; -#else - /* Shouldn't ever get here */ - multi_success = 0; -#endif -} - static void thread_provider_load_unload(void) { OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default"); @@ -458,107 +465,99 @@ static void thread_provider_load_unload(void) OSSL_PROVIDER_unload(deflt); } -/* - * Do work in multiple worker threads at the same time. - * Test 0: General worker, using the default provider - * Test 1: General worker, using the fips provider - * Test 2: Simple fetch worker - * Test 3: Worker downgrading a shared EVP_PKEY - * Test 4: Worker using a shared EVP_PKEY - * Test 5: Worker loading and unloading a provider - */ -static int test_multi(int idx) +static int test_multi_general_worker_default_provider(void) { - thread_t thread1, thread2; - int testresult = 0; - OSSL_PROVIDER *prov = NULL, *prov2 = NULL; - void (*worker)(void) = NULL; - void (*worker2)(void) = NULL; - EVP_MD *sha256 = NULL; + return thread_run_test(&thread_general_worker, 2, &thread_general_worker, + 1, default_provider); +} - if (idx == 1 && !do_fips) +static int test_multi_general_worker_fips_provider(void) +{ + if (!do_fips) return TEST_skip("FIPS not supported"); + return thread_run_test(&thread_general_worker, 2, &thread_general_worker, + 1, fips_provider); +} -#ifdef OPENSSL_NO_DEPRECATED_3_0 - if (idx == 3) - return TEST_skip("Skipping tests for deprected functions"); -#endif +static int test_multi_fetch_worker(void) +{ + return thread_run_test(&thread_multi_simple_fetch, + 2, &thread_multi_simple_fetch, 1, default_provider); +} - multi_success = 1; - if (!TEST_true(test_get_libctx(&multi_libctx, NULL, config_file, - NULL, NULL))) - return 0; +static int test_multi_shared_pkey_common(void (*worker)(void)) +{ + int testresult = 0; - prov = OSSL_PROVIDER_load(multi_libctx, (idx == 1) ? "fips" : "default"); - if (!TEST_ptr(prov)) + multi_intialise(); + if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers + : default_provider) + || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)) + || !start_threads(1, &thread_shared_evp_pkey) + || !start_threads(1, worker)) goto err; - switch (idx) { - case 0: - case 1: - worker = thread_general_worker; - break; - case 2: - worker = thread_multi_simple_fetch; - break; - case 3: - worker2 = thread_downgrade_shared_evp_pkey; - /* fall through */ - case 4: - /* - * If available we have both the default and fips providers for this - * test - */ - if (do_fips - && !TEST_ptr(prov2 = OSSL_PROVIDER_load(multi_libctx, "fips"))) - goto err; - if (!TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx))) - goto err; - worker = thread_shared_evp_pkey; - break; - case 5: - /* - * We ensure we get an md from the default provider, and then unload the - * provider. This ensures the provider remains around but in a - * deactivated state. - */ - sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); - OSSL_PROVIDER_unload(prov); - prov = NULL; - worker = thread_provider_load_unload; - break; - default: - TEST_error("Invalid test index"); - goto err; - } - if (worker2 == NULL) - worker2 = worker; + thread_shared_evp_pkey(); - if (!TEST_true(run_thread(&thread1, worker)) - || !TEST_true(run_thread(&thread2, worker2))) + if (!teardown_threads() + || !TEST_true(multi_success)) goto err; - - worker(); - testresult = 1; + err: + EVP_PKEY_free(shared_evp_pkey); + thead_teardown_libctx(); + return testresult; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +static void thread_downgrade_shared_evp_pkey(void) +{ /* - * Don't combine these into one if statement; must wait for both threads. + * This test is only relevant for deprecated functions that perform + * downgrading */ - if (!TEST_true(wait_for_thread(thread1))) - testresult = 0; - if (!TEST_true(wait_for_thread(thread2))) - testresult = 0; - if (!TEST_true(multi_success)) - testresult = 0; + if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL) + multi_success = 0; +} + +static int test_multi_downgrade_shared_pkey(void) +{ + return test_multi_shared_pkey_common(&thread_downgrade_shared_evp_pkey); +} +#endif + +static int test_multi_shared_pkey(void) +{ + return test_multi_shared_pkey_common(&thread_shared_evp_pkey); +} + +static int test_multi_load_unload_provider(void) +{ + EVP_MD *sha256 = NULL; + OSSL_PROVIDER *prov = NULL; + int testresult = 0; + multi_intialise(); + if (!thread_setup_libctx(1, NULL) + || !TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, "default")) + || !TEST_ptr(sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL)) + || !TEST_true(OSSL_PROVIDER_unload(prov))) + goto err; + prov = NULL; + + if (!start_threads(2, &thread_provider_load_unload)) + goto err; + + thread_provider_load_unload(); + + if (!teardown_threads() + || !TEST_true(multi_success)) + goto err; + testresult = 1; err: - EVP_MD_free(sha256); OSSL_PROVIDER_unload(prov); - OSSL_PROVIDER_unload(prov2); - OSSL_LIB_CTX_free(multi_libctx); - EVP_PKEY_free(shared_evp_pkey); - shared_evp_pkey = NULL; - multi_libctx = NULL; + EVP_MD_free(sha256); + thead_teardown_libctx(); return testresult; } @@ -580,10 +579,6 @@ static void test_multi_load_worker(void) static int test_multi_default(void) { - thread_t thread1, thread2; - int testresult = 0; - OSSL_PROVIDER *prov = NULL; - /* Avoid running this test twice */ if (multidefault_run) { TEST_skip("multi default test already run"); @@ -591,34 +586,13 @@ static int test_multi_default(void) } multidefault_run = 1; - multi_success = 1; - multi_libctx = NULL; - prov = OSSL_PROVIDER_load(multi_libctx, "default"); - if (!TEST_ptr(prov)) - goto err; - - if (!TEST_true(run_thread(&thread1, thread_multi_simple_fetch)) - || !TEST_true(run_thread(&thread2, thread_multi_simple_fetch))) - goto err; - - thread_multi_simple_fetch(); - - if (!TEST_true(wait_for_thread(thread1)) - || !TEST_true(wait_for_thread(thread2)) - || !TEST_true(multi_success)) - goto err; - - testresult = 1; - - err: - OSSL_PROVIDER_unload(prov); - return testresult; + return thread_run_test(&thread_multi_simple_fetch, + 2, &thread_multi_simple_fetch, 0, default_provider); } static int test_multi_load(void) { - thread_t threads[MULTI_LOAD_THREADS]; - int i, res = 1; + int res = 1; OSSL_PROVIDER *prov; /* The multidefault test must run prior to this test */ @@ -640,14 +614,29 @@ static int test_multi_load(void) } OSSL_PROVIDER_unload(prov); - multi_success = 1; - for (i = 0; i < MULTI_LOAD_THREADS; i++) - (void)TEST_true(run_thread(&threads[i], test_multi_load_worker)); + return thread_run_test(NULL, MULTI_LOAD_THREADS, &test_multi_load_worker, + 0, NULL) && res; +} - for (i = 0; i < MULTI_LOAD_THREADS; i++) - (void)TEST_true(wait_for_thread(threads[i])); +static void test_obj_create_one(void) +{ + char tids[12], oid[40], sn[30], ln[30]; + int id = get_new_uid(); + + BIO_snprintf(tids, sizeof(tids), "%d", id); + BIO_snprintf(oid, sizeof(oid), "1.3.6.1.4.1.16604.%s", tids); + BIO_snprintf(sn, sizeof(sn), "short-name-%s", tids); + BIO_snprintf(ln, sizeof(ln), "long-name-%s", tids); + if (!TEST_true(id = OBJ_create(oid, sn, ln)) + || !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa))) + multi_success = 0; +} - return res && multi_success; +static int test_obj_add(void) +{ + return thread_run_test(&test_obj_create_one, + MAXIMUM_THREADS, &test_obj_create_one, + 1, default_provider); } static void test_lib_ctx_load_config_worker(void) @@ -717,7 +706,15 @@ int setup_tests(void) ADD_TEST(test_thread_local); ADD_TEST(test_atomic); ADD_TEST(test_multi_load); - ADD_ALL_TESTS(test_multi, 6); + ADD_TEST(test_multi_general_worker_default_provider); + ADD_TEST(test_multi_general_worker_fips_provider); + ADD_TEST(test_multi_fetch_worker); + ADD_TEST(test_multi_shared_pkey); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + ADD_TEST(test_multi_downgrade_shared_pkey); +#endif + ADD_TEST(test_multi_load_unload_provider); + ADD_TEST(test_obj_add); ADD_TEST(test_lib_ctx_load_config); return 1; } -- cgit v1.2.3