Skip to content

3.0.0: Segfault when using FIPS module #13469

@davidmakepeace

Description

@davidmakepeace

I either get a segfault (Ubuntu 18.04.1 or 20.04.1) or a hang (OEL7) with the following code when using OpenSSL built from the current master (short hash: 5053394) and earlier. There is some evidence suggesting this bug may have existed four months ago.

This code creates a library context, loads the configuration (using FIPS module), performs a SHA-1 digest operation using the libctx in the main thread, creates a thread which performs an RSA key pair generation operation and exits the thread.

The segfault occurs during the thread cleanup (init_thread_destructor, etc.).

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/provider.h>
#include <string.h>

#define OSSLPATH "/path/to/openssl"

OSSL_LIB_CTX *libctx;

void do_digest();
void *gen_rsa_keypair(void *arg);

int
main(int argc, char **argv)
{
    pthread_t t;
    int ret;

    libctx = OSSL_LIB_CTX_new();
    if (libctx == NULL) {
        fputs("ERROR: OSSL_LIB_CTX_new()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    OSSL_PROVIDER_set_default_search_path(libctx, OSSLPATH "/lib/ossl-modules");
    if (!OSSL_LIB_CTX_load_config(libctx, OSSLPATH "/openssl.cnf")) {
        fputs("ERROR: OSSL_LIB_CTX_load_config()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    fprintf(stdout, "Version: %s\n", OpenSSL_version(OPENSSL_VERSION));

    do_digest();

    puts("starting thread");
    if ((ret = pthread_create(&t, NULL, gen_rsa_keypair, NULL)) != 0) {
        fprintf(stderr, "ERROR: pthread_create() ret=%d\n", ret);
        goto err;
    }

    puts("joining thread");
    if ((ret = pthread_join(t, NULL)) != 0) {
        fprintf(stderr, "ERROR: pthread_join() ret=%d\n", ret);
        goto err;
    }
    puts("done");

err:
    OSSL_LIB_CTX_free(libctx);
    libctx = NULL;
    OPENSSL_cleanup();
    return 0;
}

void
do_digest()
{
    EVP_MD_CTX *ctx;
    EVP_MD *md = NULL;
    unsigned char outbuf[128];
    unsigned int outlen = 0;

    ctx = EVP_MD_CTX_new();
    if (ctx == NULL) {
        fputs("ERROR: EVP_MD_CTX_new()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    md = EVP_MD_fetch(libctx, "SHA-1", NULL);
    if (md == NULL) {
        fputs("ERROR: EVP_MD_fetch()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    if (EVP_DigestInit_ex(ctx, md, NULL) <= 0) {
        fputs("ERROR: EVP_DigestInit_ex()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }
    EVP_MD_free(md);
    md = NULL;

    if (EVP_DigestUpdate(ctx, "Test String 001", 15) <= 0) {
        fputs("ERROR: EVP_DigestUpdate()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    if (EVP_DigestFinal_ex(ctx, outbuf, &outlen) <= 0) {
        fputs("ERROR: EVP_DigestFinal_ex()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

err:
    EVP_MD_free(md);
    EVP_MD_CTX_free(ctx);
}

void *
gen_rsa_keypair(void *arg)
{
    EVP_PKEY_CTX *ctx = NULL;
    EVP_PKEY *pkey = NULL;

    ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL);
    if (ctx == NULL) {
        fputs("ERROR: EVP_PKEY_CTX_new_from_name()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    if (EVP_PKEY_keygen_init(ctx) <= 0) {
        fputs("ERROR: EVP_PKEY_keygen_init()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0) {
        fputs("ERROR: EVP_PKEY_CTX_set_rsa_keygen_bits()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

    if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
        fputs("ERROR: EVP_PKEY_keygen()\n", stderr);
        ERR_print_errors_fp(stderr);
        goto err;
    }

err:
    EVP_PKEY_free(pkey);
    EVP_PKEY_CTX_free(ctx);
    return NULL;
}

The openssl.cnf file is:

openssl_conf = openssl_init

[fips_sect]
activate = 1
install-version = 1
conditional-errors = 1
security-checks = 1
module-mac = 84:AC:60:00:7F:C5:48:7A:96:ED:50:EE:CB:0C:1E:72:C7:17:4C:6A:24:B4:D5:30:D0:1A:8F:C9:04:5B:37:1C

[openssl_init]
providers = provider_sect
alg_section = algorithm_sect

[provider_sect]
default = default_sect
fips = fips_sect

[default_sect]
activate = 1

[algorithm_sect]
default_properties = fips=yes

The output is:

Version: OpenSSL 3.0.0-alpha9-dev 
starting thread
joining thread
Segmentation fault (core dumped)

GDB stack trace:

GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./ossltest...done.
(gdb) run
Starting program: /home/dpmakepe/src/c/jaffadebug/ossltest 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Version: OpenSSL 3.0.0-alpha9-dev 
starting thread
[New Thread 0x7ffff6b61700 (LWP 24077)]
joining thread

Thread 2 "ossltest" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6b61700 (LWP 24077)]
__GI___pthread_rwlock_rdlock (rwlock=0x0) at pthread_rwlock_rdlock.c:27
27	pthread_rwlock_rdlock.c: No such file or directory.
(gdb) bt
#0  __GI___pthread_rwlock_rdlock (rwlock=0x0) at pthread_rwlock_rdlock.c:27
#1  0x00007ffff6c18804 in CRYPTO_THREAD_read_lock (lock=0x0)
    at crypto/threads_pthread.c:76
#2  0x00007ffff6c0e33a in ossl_lib_ctx_get_data (ctx=0x555555767df0, index=8, 
    meth=0x7ffff6efa510 <thread_event_ossl_ctx_method>) at crypto/context.c:281
#3  0x00007ffff6c112ee in ossl_ctx_thread_stop (arg=0x555555767df0)
    at crypto/initthread.c:285
#4  0x00007ffff795aafc in init_thread_stop (arg=0x0, hands=0x7ffff002e6b0)
    at crypto/initthread.c:313
#5  0x00007ffff795a931 in init_thread_destructor (hands=0x7ffff002e6b0)
    at crypto/initthread.c:190
#6  0x00007ffff7503408 in __nptl_deallocate_tsd () at pthread_create.c:300
#7  0x00007ffff750481b in __nptl_deallocate_tsd ()
    at ../sysdeps/nptl/futex-internal.h:200
#8  start_thread (arg=0x7ffff6b61700) at pthread_create.c:473
#9  0x00007ffff722d71f in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions