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 /src | |
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.
Diffstat (limited to 'src')
-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 | ||