Your response makes sense. I am a bit puzzled by the BIO reference
counting. For example
BIO_new() (or BIO_new_socket() which calls BIO_new()) produces a
BIO with a reference count of 1.
BIO_free() drops 1 reference and if the reference count is 0, frees
BIO_push() connects the BIO to the BIO chain. No references are
directly changed. However, the BIO_CTRL_PUSH command is sent to the
BIO. For the SSL BIO, this results in a call to SSL_set_bio() and
adding 1 to the next_bio reference (socket BIO).
BIO_pop() calls BIO_CTRL_POP and disconnects the BIO from the BIO
chain. For the SSL BIO, the BIO_CTRL_POP subtracts one from the
next_bio reference (undoing BIO_push()).
The problem case is calling BIO_free_all() on the BIO chain.
BIO_free_all() does not use BIO_pop(). It simply detaches each BIO from
the chain, and calls BIO_free() for it. If the next_bio reference count
is > 1 (which it will be for the SSL BIO next_bio), it stops unlinking
and freeing BIOs. This seems asymmetrical with respect to the BIO
reference counting, and leaks the next_bio (socket BIO in this case).
What am I missing here?
On 9/29/2022 11:50 PM, Tomas Mraz wrote:
The SSL BIO should have the rbio from the SSL object as the next BIO.
If you create the SSL BIO and then BIO_push() the TCP socket BIO into
the SSL BIO, it will work correctly.
Otherwise, you can just fix the next BIO of the SSL BIO by using
The SSL BIO should always have a next BIO if properly initialized.
Tomas Mraz, OpenSSL
On Thu, 2022-09-29 at 13:02 -0700, Jay Foster wrote:
I have an application that constructs a chain of BIOs. Sometimes
chain also includes an SSL BIO. Years ago, I ran into a problem that
caused BIO_flush() to segfault on the SSL BIO. This turned out to
happen because the SSL BIO is added using SSL_set_bio() instead of
BIO_push(). SSL_set_bio() results in the SSL BIO always having a
bio_next value, so BIO_flush then crashes dereferencing this NULL
pointer when it calls BIO_copy_next_retry() on the SSL BIO (see
BIO_CTRL_FLUSH in ssl/bio_ssl.c).
This was reported as ticket 2615 years ago.
My question is, how could calling BIO_flush() on a BIO chain with an
BIO ever work? Is there a way to add the SSL BIO using BIO_push()
instead of SSL_set_bio()?