Commit f3dbf6aa79 for openssl.org
commit f3dbf6aa79c37f6fd280b1a96c081e3194c3f454
Author: Matt Caswell <matt@openssl.foundation>
Date: Thu Mar 19 10:38:22 2026 +0000
Fix a Use-After-Free bug in the DTLS code
The newly added #30225 introduced a UAF bug in the master branch found
by the dtlsserver fuzzer. If a CCS arrives early and there is trailing
data left in the current record at the point that we change epoch then
the buffer holding the trailing data is freed as part of setting up the
new record layer, but we still have dangling references into that buffer
causing the UAF.
Fixes #30487
Reviewed-by: Frederik Wedel-Heinen <fwh.openssl@gmail.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Fri Apr 3 15:06:50 2026
(Merged from https://github.com/openssl/openssl/pull/30503)
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 9db6caae2b..c960aa5893 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -1259,6 +1259,31 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
uint32_t max_early_data;
COMP_METHOD *compm = (comp == NULL) ? NULL : comp->method;
+ if (direction == OSSL_RECORD_DIRECTION_READ) {
+ if (SSL_CONNECTION_IS_DTLS(s)) {
+ if (s->rlayer.curr_rec < s->rlayer.num_recs) {
+ /*
+ * We are trying to move to the next epoch, but we've still got
+ * trailing record data to process. This should not happen in
+ * normal circumstances. The CCS must have arrived early, but
+ * this remaining record data is unexpected.
+ */
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+ }
+ } else {
+ if (!ossl_assert(s->rlayer.curr_rec == s->rlayer.num_recs)) {
+ /*
+ * How can this happen? We're trying to change to the next
+ * record layer - but that should only happen on a record
+ * boundary. We should never be able to get here.
+ */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
+ }
+
meth = ssl_select_next_record_layer(s, direction, level);
if (direction == OSSL_RECORD_DIRECTION_READ) {