diff options
author | tb <> | 2023-03-31 06:07:44 +0000 |
---|---|---|
committer | tb <> | 2023-03-31 06:07:44 +0000 |
commit | 25a20dbee47e2778717afc53f5d438b40d543256 (patch) | |
tree | a362baf173cc7fea2ae5dd049cc308a5d976eed7 | |
parent | 96e4788cde61058167082e95712348212c565bf9 (diff) | |
download | openbsd-25a20dbee47e2778717afc53f5d438b40d543256.tar.gz openbsd-25a20dbee47e2778717afc53f5d438b40d543256.tar.bz2 openbsd-25a20dbee47e2778717afc53f5d438b40d543256.zip |
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.
-rw-r--r-- | src/regress/lib/libcrypto/bio/bio_asn1.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/bio/bio_asn1.c b/src/regress/lib/libcrypto/bio/bio_asn1.c index 9ee2bb5341..ac7f48ced8 100644 --- a/src/regress/lib/libcrypto/bio/bio_asn1.c +++ b/src/regress/lib/libcrypto/bio/bio_asn1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bio_asn1.c,v 1.1 2023/03/26 19:14:11 tb Exp $ */ | 1 | /* $OpenBSD: bio_asn1.c,v 1.2 2023/03/31 06:07:44 tb Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2023 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2023 Theo Buehler <tb@openbsd.org> |
@@ -21,9 +21,65 @@ | |||
21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
22 | 22 | ||
23 | #include <openssl/asn1.h> | 23 | #include <openssl/asn1.h> |
24 | #include <openssl/asn1t.h> | ||
24 | #include <openssl/bio.h> | 25 | #include <openssl/bio.h> |
25 | #include <openssl/pkcs7.h> | 26 | #include <openssl/evp.h> |
26 | #include <openssl/objects.h> | 27 | #include <openssl/objects.h> |
28 | #include <openssl/pkcs7.h> | ||
29 | |||
30 | /* | ||
31 | * Minimal reproducer for the BIO_new_NDEF() write after free fixed in | ||
32 | * bio_ndef.c r1.13. | ||
33 | */ | ||
34 | |||
35 | static int | ||
36 | waf_cb(int op, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) | ||
37 | { | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static const ASN1_AUX WAF_aux = { | ||
42 | .asn1_cb = waf_cb, | ||
43 | }; | ||
44 | |||
45 | static const ASN1_ITEM WAF_it = { | ||
46 | .funcs = &WAF_aux, | ||
47 | }; | ||
48 | |||
49 | static int | ||
50 | test_bio_new_ndef_waf(void) | ||
51 | { | ||
52 | BIO *out = NULL; | ||
53 | int failed = 1; | ||
54 | |||
55 | if ((out = BIO_new(BIO_s_mem())) == NULL) | ||
56 | goto err; | ||
57 | |||
58 | /* | ||
59 | * BIO_new_NDEF() pushes out onto asn_bio. The waf_cb() call fails. | ||
60 | * Prior to bio_ndef.c r1.13, asn_bio was freed and out->prev_bio | ||
61 | * still pointed to it. | ||
62 | */ | ||
63 | |||
64 | if (BIO_new_NDEF(out, NULL, &WAF_it) != NULL) { | ||
65 | fprintf(stderr, "%s: BIO_new_NDEF succeeded\n", __func__); | ||
66 | goto err; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * If out->prev_bio != NULL, this writes to out->prev_bio->next_bio. | ||
71 | * After bio_ndef.c r1.13, out is an isolated BIO, so this is a noop. | ||
72 | */ | ||
73 | |||
74 | BIO_pop(out); | ||
75 | |||
76 | failed = 0; | ||
77 | |||
78 | err: | ||
79 | BIO_free(out); | ||
80 | |||
81 | return failed; | ||
82 | } | ||
27 | 83 | ||
28 | /* | 84 | /* |
29 | * test_prefix_leak() leaks before asn/bio_asn1.c r1.19. | 85 | * test_prefix_leak() leaks before asn/bio_asn1.c r1.19. |
@@ -167,6 +223,7 @@ main(void) | |||
167 | { | 223 | { |
168 | int failed = 0; | 224 | int failed = 0; |
169 | 225 | ||
226 | failed |= test_bio_new_ndef_waf(); | ||
170 | failed |= test_prefix_leak(); | 227 | failed |= test_prefix_leak(); |
171 | failed |= test_infinite_loop(); | 228 | failed |= test_infinite_loop(); |
172 | 229 | ||