From 60421893a286bb9eb7fb7c2454b84af9778ffca4 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Wed, 30 Aug 2023 10:32:53 +0100 Subject: QUIC: Harden ring buffer against internal misuse Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21895) --- include/internal/ring_buf.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/include/internal/ring_buf.h b/include/internal/ring_buf.h index 1d70439278..85a8d309ba 100644 --- a/include/internal/ring_buf.h +++ b/include/internal/ring_buf.h @@ -12,6 +12,7 @@ # pragma once # include /* For 'ossl_inline' */ +# include "internal/safe_math.h" /* * ================================================================== @@ -39,6 +40,10 @@ struct ring_buf { uint64_t ctail_offset; }; +OSSL_SAFE_MATH_UNSIGNED(u64, uint64_t) + +#define MAX_OFFSET (((uint64_t)1) << 62) /* QUIC-imposed limit */ + static ossl_inline int ring_buf_init(struct ring_buf *r) { r->start = NULL; @@ -74,11 +79,15 @@ static ossl_inline int ring_buf_write_at(struct ring_buf *r, { size_t avail, idx, l; unsigned char *start = r->start; - int i; + int i, err = 0; avail = ring_buf_avail(r); if (logical_offset < r->ctail_offset - || logical_offset + buf_len > r->head_offset + avail) + || safe_add_u64(logical_offset, buf_len, &err) + > safe_add_u64(r->head_offset, avail, &err) + || safe_add_u64(r->head_offset, buf_len, &err) + > MAX_OFFSET + || err) return 0; for (i = 0; buf_len > 0 && i < 2; ++i) { @@ -113,6 +122,9 @@ static ossl_inline size_t ring_buf_push(struct ring_buf *r, if (buf_len > avail) buf_len = avail; + if (buf_len > MAX_OFFSET - r->head_offset) + buf_len = (size_t)(MAX_OFFSET - r->head_offset); + if (buf_len == 0) break; @@ -190,7 +202,7 @@ static ossl_inline void ring_buf_cpop_range(struct ring_buf *r, { assert(end >= start); - if (start > r->ctail_offset) + if (start > r->ctail_offset || end >= MAX_OFFSET) return; if (cleanse && r->alloc > 0 && end > r->ctail_offset) { -- cgit v1.2.3