BIO_new_from_core_bio: Fix heap-use-after-free after attach

The providers have to call up_ref to keep the cbio pointer, just like
the internal bio_prov.c does.

OSSL_STORE_attach passes a cbio pointer to the provider and then calls
ossl_core_bio_free(cbio). If up_ref is not called, the cbio gets
freed way too early.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15163)
This commit is contained in:
Petr Gotthard 2021-05-05 18:32:55 +02:00 committed by Pauli
parent 454d69271c
commit 11efa7d45b
2 changed files with 29 additions and 0 deletions

View File

@ -17,6 +17,8 @@ typedef struct {
OSSL_FUNC_BIO_gets_fn *c_bio_gets;
OSSL_FUNC_BIO_puts_fn *c_bio_puts;
OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl;
OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref;
OSSL_FUNC_BIO_free_fn *c_bio_free;
} BIO_CORE_GLOBALS;
static void bio_core_globals_free(void *vbcg)
@ -97,7 +99,10 @@ static int bio_core_new(BIO *bio)
static int bio_core_free(BIO *bio)
{
BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx);
BIO_set_init(bio, 0);
bcgbl->c_bio_free(BIO_get_data(bio));
return 1;
}
@ -134,6 +139,10 @@ BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio)
if ((outbio = BIO_new_ex(libctx, BIO_s_core())) == NULL)
return NULL;
if (!bcgbl->c_bio_up_ref(corebio)) {
BIO_free(outbio);
return NULL;
}
BIO_set_data(outbio, corebio);
return outbio;
}
@ -164,6 +173,14 @@ int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns)
if (bcgbl->c_bio_ctrl == NULL)
bcgbl->c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns);
break;
case OSSL_FUNC_BIO_UP_REF:
if (bcgbl->c_bio_up_ref == NULL)
bcgbl->c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns);
break;
case OSSL_FUNC_BIO_FREE:
if (bcgbl->c_bio_free == NULL)
bcgbl->c_bio_free = OSSL_FUNC_BIO_free(fns);
break;
}
}

View File

@ -43,12 +43,24 @@ static long tst_bio_core_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr)
return BIO_ctrl(bio->bio, cmd, num, ptr);
}
static int tst_bio_core_up_ref(OSSL_CORE_BIO *bio)
{
return BIO_up_ref(bio->bio);
}
static int tst_bio_core_free(OSSL_CORE_BIO *bio)
{
return BIO_free(bio->bio);
}
static const OSSL_DISPATCH biocbs[] = {
{ OSSL_FUNC_BIO_READ_EX, (void (*)(void))tst_bio_core_read_ex },
{ OSSL_FUNC_BIO_WRITE_EX, (void (*)(void))tst_bio_core_write_ex },
{ OSSL_FUNC_BIO_GETS, (void (*)(void))tst_bio_core_gets },
{ OSSL_FUNC_BIO_PUTS, (void (*)(void))tst_bio_core_puts },
{ OSSL_FUNC_BIO_CTRL, (void (*)(void))tst_bio_core_ctrl },
{ OSSL_FUNC_BIO_UP_REF, (void (*)(void))tst_bio_core_up_ref },
{ OSSL_FUNC_BIO_FREE, (void (*)(void))tst_bio_core_free },
{ 0, NULL }
};