diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-08-30 10:32:53 +0100 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-08-31 16:34:51 +0100 |
commit | 60421893a286bb9eb7fb7c2454b84af9778ffca4 (patch) | |
tree | 5f3f4edff9e431b7cb60044c25a478dc99db6cb7 /include | |
parent | ecb6cdf02a302af18fe4bc20097a9ea3177f897c (diff) |
QUIC: Harden ring buffer against internal misuse
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21895)
Diffstat (limited to 'include')
-rw-r--r-- | include/internal/ring_buf.h | 18 |
1 files 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 <openssl/e_os2.h> /* 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) { |