summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-08-30 10:32:53 +0100
committerHugo Landau <hlandau@openssl.org>2023-08-31 16:34:51 +0100
commit60421893a286bb9eb7fb7c2454b84af9778ffca4 (patch)
tree5f3f4edff9e431b7cb60044c25a478dc99db6cb7 /include
parentecb6cdf02a302af18fe4bc20097a9ea3177f897c (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.h18
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) {