diff options
| author | Neil Horman <[email protected]> | 2026-01-07 17:52:09 +0100 |
|---|---|---|
| committer | Tomas Mraz <[email protected]> | 2026-01-26 20:42:35 +0100 |
| commit | 68a7cd2e2816c3a02f4d45a2ce43fc04fac97096 (patch) | |
| tree | a60878f523663afcafff34b95395e4634f516069 | |
| parent | ossl_quic_get_cipher_by_char(): Add a NULL guard before dereferencing SSL_CIPHER (diff) | |
| download | openssl-68a7cd2e2816c3a02f4d45a2ce43fc04fac97096.tar.gz openssl-68a7cd2e2816c3a02f4d45a2ce43fc04fac97096.zip | |
Fix heap buffer overflow in BIO_f_linebuffer
When a FIO_f_linebuffer is part of a bio chain, and the next BIO
preforms short writes, the remainder of the unwritten buffer is copied
unconditionally to the internal buffer ctx->obuf, which may not be
sufficiently sized to handle the remaining data, resulting in a buffer
overflow.
Fix it by only copying data when ctx->obuf has space, flushing to the
next BIO to increase available storage if needed.
Fixes openssl/srt#48
Fixes CVE-2025-68160
Reviewed-by: Nikola Pajkovsky <[email protected]>
Reviewed-by: Eugene Syromiatnikov <[email protected]>
Reviewed-by: Saša Nedvědický <[email protected]>
Reviewed-by: Tomas Mraz <[email protected]>
MergeDate: Mon Jan 26 19:41:40 2026
(cherry picked from commit b21663c35a6f0ed4c8de06855bdc7a6a21f00c2f)
| -rw-r--r-- | crypto/bio/bf_lbuf.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c index eec6e12b049..63cf12b5d16 100644 --- a/crypto/bio/bf_lbuf.c +++ b/crypto/bio/bf_lbuf.c @@ -186,14 +186,34 @@ static int linebuffer_write(BIO *b, const char *in, int inl) } while (foundnl && inl > 0); /* * We've written as much as we can. The rest of the input buffer, if - * any, is text that doesn't and with a NL and therefore needs to be - * saved for the next trip. + * any, is text that doesn't end with a NL and therefore we need to try + * free up some space in our obuf so we can make forward progress. */ - if (inl > 0) { - memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl); - ctx->obuf_len += inl; - num += inl; + while (inl > 0) { + size_t avail = (size_t)ctx->obuf_size - (size_t)ctx->obuf_len; + size_t to_copy; + + if (avail == 0) { + /* Flush buffered data to make room */ + i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len); + if (i <= 0) { + BIO_copy_next_retry(b); + return num > 0 ? num : i; + } + if (i < ctx->obuf_len) + memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i); + ctx->obuf_len -= i; + continue; + } + + to_copy = inl > (int)avail ? avail : (size_t)inl; + memcpy(&(ctx->obuf[ctx->obuf_len]), in, to_copy); + ctx->obuf_len += (int)to_copy; + in += to_copy; + inl -= (int)to_copy; + num += (int)to_copy; } + return num; } |
