summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschwarze <>2022-12-06 16:10:55 +0000
committerschwarze <>2022-12-06 16:10:55 +0000
commit73e2daf0f78d5a05d5bb4c92a2a82363f1e98378 (patch)
tree89ecfb89e18d9c317fbd43bd3eb6033a080d6855
parentb04f31a4fdc276077884e3e71688f595a3026b51 (diff)
downloadopenbsd-73e2daf0f78d5a05d5bb4c92a2a82363f1e98378.tar.gz
openbsd-73e2daf0f78d5a05d5bb4c92a2a82363f1e98378.tar.bz2
openbsd-73e2daf0f78d5a05d5bb4c92a2a82363f1e98378.zip
Improve the poorly designed BIO_set_next(3) API to always preserve all
invariants of the prev_bio and next_bio fields of all BIO objects in all involved chains, no matter which arguments this function is called with. Both real-world uses of this function (in libssl and freerdp) have been audited to make sure this makes nothing worse. We believe libssl behaves correctly before and after the patch (mostly because the second argument is NULL there), and we believe the code in freerdp behaves incorrectly before and after the patch, leaving a prev_bio pointer in place that is becoming bogus, only in a different object before and after the patch. But after the patch, that bogus pointer is due to a separate bug in BIO_push(3), which we are planning to fix afterwards. Joint work with and OK tb@.
-rw-r--r--src/lib/libcrypto/bio/bio_lib.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/lib/libcrypto/bio/bio_lib.c b/src/lib/libcrypto/bio/bio_lib.c
index c09ad8fe8e..2ffa0a765c 100644
--- a/src/lib/libcrypto/bio/bio_lib.c
+++ b/src/lib/libcrypto/bio/bio_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bio_lib.c,v 1.39 2022/12/02 19:44:04 tb Exp $ */ 1/* $OpenBSD: bio_lib.c,v 1.40 2022/12/06 16:10:55 schwarze Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -727,10 +727,25 @@ BIO_next(BIO *b)
727 return b->next_bio; 727 return b->next_bio;
728} 728}
729 729
730/*
731 * Two chains "bio -> oldtail" and "oldhead -> next" become
732 * three chains "oldtail", "bio -> next", and "oldhead".
733 */
730void 734void
731BIO_set_next(BIO *b, BIO *next) 735BIO_set_next(BIO *bio, BIO *next)
732{ 736{
733 b->next_bio = next; 737 /* Cut off the tail of the chain containing bio after bio. */
738 if (bio->next_bio != NULL)
739 bio->next_bio->prev_bio = NULL;
740
741 /* Cut off the head of the chain containing next before next. */
742 if (next != NULL && next->prev_bio != NULL)
743 next->prev_bio->next_bio = NULL;
744
745 /* Append the chain starting at next to the chain ending at bio. */
746 bio->next_bio = next;
747 if (next != NULL)
748 next->prev_bio = bio;
734} 749}
735 750
736void 751void