From 2de7e1d69851a363cadd9d6bdd95302b89a4383b Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 19 Nov 2024 11:58:30 -0500 Subject: [PATCH] Fix SSL_write_[ex|ex2] on blocking quic streams When writing to a blocking quic stream, we sometimes get duplicate transmitted data. This occurs when a call to quic_write_blocking has to wait for space to become available in the ring buffer. When we do a wait, the call sets *written to the value returned in args.total_written as filled out by the calls to block_until_pred->quic_write_again. However, the value there is based on the amount we requested, which is only the remaining data that we didn't append in xso_sstream_write. So if we call quic_write_blocking with a buffer of length X, and initially append Y bytes, and write the remainig X-Y bytes via a block_until_pred call, then *written will return with the value X-Y, even though we wrote the full X bytes to the ring buffer. Fix it by recording the initial amount appended into *written, and then add the args.total_written value if we have to wait on more space Fixes openssl/project#924 Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/26023) --- ssl/quic/quic_impl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index c603ee9b1fd..01ba89e64e7 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -2317,9 +2317,13 @@ static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len, quic_post_write(xso, actual_written > 0, actual_written == len, flags, 1); + /* + * Record however much data we wrote + */ + *written = actual_written; + if (actual_written == len) { /* Managed to append everything on the first try. */ - *written = actual_written; return 1; } @@ -2343,7 +2347,14 @@ static int quic_write_blocking(QCTX *ctx, const void *buf, size_t len, return QUIC_RAISE_NON_NORMAL_ERROR(ctx, args.err, NULL); } - *written = args.total_written; + /* + * When waiting on extra buffer space to be available, args.total_written + * holds the amount of remaining data we requested to write, which will be + * something less than the len parameter passed in, however much we wrote + * here, add it to the value that we wrote when we initially called + * xso_sstream_append + */ + *written += args.total_written; return 1; } -- 2.47.2