From 13ffeb0184f17f2b3142c755bf190dadd2658d14 Mon Sep 17 00:00:00 2001 From: tb Date: Fri, 31 Mar 2023 06:07:44 +0000 Subject: [PATCH] Add a regress for the recent BIO_new_NDEF() write after free This is a simple reproducer for a write after free that avoids all the mess with CMS, PKCS7 and SMIME. This now mostly allows ASAN to check that the memory handling in this marvellous function is correct. --- regress/lib/libcrypto/bio/bio_asn1.c | 61 +++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/regress/lib/libcrypto/bio/bio_asn1.c b/regress/lib/libcrypto/bio/bio_asn1.c index 9ee2bb53412..ac7f48ced89 100644 --- a/regress/lib/libcrypto/bio/bio_asn1.c +++ b/regress/lib/libcrypto/bio/bio_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_asn1.c,v 1.1 2023/03/26 19:14:11 tb Exp $ */ +/* $OpenBSD: bio_asn1.c,v 1.2 2023/03/31 06:07:44 tb Exp $ */ /* * Copyright (c) 2023 Theo Buehler @@ -21,9 +21,65 @@ #include #include +#include #include -#include +#include #include +#include + +/* + * Minimal reproducer for the BIO_new_NDEF() write after free fixed in + * bio_ndef.c r1.13. + */ + +static int +waf_cb(int op, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) +{ + return 0; +} + +static const ASN1_AUX WAF_aux = { + .asn1_cb = waf_cb, +}; + +static const ASN1_ITEM WAF_it = { + .funcs = &WAF_aux, +}; + +static int +test_bio_new_ndef_waf(void) +{ + BIO *out = NULL; + int failed = 1; + + if ((out = BIO_new(BIO_s_mem())) == NULL) + goto err; + + /* + * BIO_new_NDEF() pushes out onto asn_bio. The waf_cb() call fails. + * Prior to bio_ndef.c r1.13, asn_bio was freed and out->prev_bio + * still pointed to it. + */ + + if (BIO_new_NDEF(out, NULL, &WAF_it) != NULL) { + fprintf(stderr, "%s: BIO_new_NDEF succeeded\n", __func__); + goto err; + } + + /* + * If out->prev_bio != NULL, this writes to out->prev_bio->next_bio. + * After bio_ndef.c r1.13, out is an isolated BIO, so this is a noop. + */ + + BIO_pop(out); + + failed = 0; + + err: + BIO_free(out); + + return failed; +} /* * test_prefix_leak() leaks before asn/bio_asn1.c r1.19. @@ -167,6 +223,7 @@ main(void) { int failed = 0; + failed |= test_bio_new_ndef_waf(); failed |= test_prefix_leak(); failed |= test_infinite_loop(); -- 2.20.1