diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 3179b0ea..209110b5 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -251,14 +251,14 @@ wolfProvider and the test is dead weight. | Job | Flags | What it catches | |-----|-------|-----------------| -| `sanitizers` (ASan + UBSan) | `-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all` | use-after-free, double-free, out-of-bounds read/write, signed overflow, misaligned access, NULL deref, etc. | +| `sanitizers` (ASan + UBSan) | `-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all` | use-after-free, double-free, out-of-bounds read/write, signed overflow, misaligned access, NULL deref, etc.; leaks in `make test` (LeakSanitizer). | | `tsan` (Thread Sanitizer) | `-fsanitize=thread` | data races + lock-ordering violations in the multi-threaded unit tests in `test/unit.c` (`pthread_create` fan-out). | ASan and TSan can't coexist in one binary, so they're separate jobs -with separate caches. Both use `LD_PRELOAD=libasan.so` / `libtsan.so` -for the unit-test run because wolfProvider is loaded via `dlopen()` -from OpenSSL and the runtime needs the sanitizer interceptors live -before any provider code runs. `ASAN_OPTIONS=detect_odr_violation=0` +with separate caches. The unit-test binaries link the sanitizer +runtime. The ASan job preloads `libasan.so` only for `scripts/env-setup` +and the cmd-tests, and runs `make test` with `detect_leaks=1`. +`ASAN_OPTIONS=detect_odr_violation=0` is set to suppress a known false positive from the provider's static ASN.1 table being linked into both `libwolfprov.so` and the test binary. diff --git a/.github/workflows/sanitizers.yml b/.github/workflows/sanitizers.yml index 335d9950..9fd5bf48 100644 --- a/.github/workflows/sanitizers.yml +++ b/.github/workflows/sanitizers.yml @@ -51,7 +51,8 @@ jobs: matrix: wolfssl_ref: ${{ fromJson(needs.discover_versions.outputs.wolfssl_latest_ref_array) }} env: - # detect_leaks=0: OpenSSL keeps provider-registry allocs alive. + # detect_leaks=0: the libasan preload would also leak-check shell + # tools; the unit-test step enables it for the test binaries only. # detect_odr_violation=0: libwolfprov is linked + dlopen'd in # test/unit.test -- false-positive ODR. ASAN_OPTIONS: detect_leaks=0:halt_on_error=1:abort_on_error=0:print_stacktrace=1:detect_odr_violation=0 @@ -111,7 +112,9 @@ jobs: run: | export LD_PRELOAD="$(gcc -print-file-name=libasan.so)" source scripts/env-setup - make test + # Preload is only for env-setup's openssl; test binaries link libasan. + unset LD_PRELOAD + ASAN_OPTIONS="${ASAN_OPTIONS}:detect_leaks=1" make test - name: Run cmd-tests under sanitizers shell: bash diff --git a/include/wolfprovider/internal.h b/include/wolfprovider/internal.h index 0b10515c..abf85160 100644 --- a/include/wolfprovider/internal.h +++ b/include/wolfprovider/internal.h @@ -153,7 +153,7 @@ enum { typedef struct WOLFPROV_CTX { /** Cached handle to a resource. */ const OSSL_CORE_HANDLE *handle; - /** Library context to use in all cases. */ + /** Library context to use in all cases. Owned; may be NULL. */ OSSL_LIB_CTX *libCtx; /** Random number generator. */ WC_RNG rng; diff --git a/src/wp_wolfprov.c b/src/wp_wolfprov.c index 69446838..91cd83e2 100644 --- a/src/wp_wolfprov.c +++ b/src/wp_wolfprov.c @@ -285,6 +285,7 @@ static WOLFPROV_CTX* wolfssl_prov_ctx_new(void) */ static void wolfssl_prov_ctx_free(WOLFPROV_CTX* ctx) { + OSSL_LIB_CTX_free(ctx->libCtx); #if defined(WP_HAVE_SEED_SRC) && defined(WP_HAVE_RANDOM) /* Release a reference only if this context took one; pairing a failed init * with a cleanup would tear down the shared subsystem other contexts use. */ @@ -310,7 +311,7 @@ static void wolfssl_prov_ctx_free(WOLFPROV_CTX* ctx) * Stores the library context object in the wolfSSL provider object. * * @param [in] ctx wolfSSL provider context object. - * @param [in] libCtx Library context object. + * @param [in] libCtx Library context object. Owned by ctx. */ static void wolfssl_prov_ctx_set0_lib_ctx(WOLFPROV_CTX* ctx, OSSL_LIB_CTX* libCtx)