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)
This commit is contained in:
Hugo Landau 2023-08-30 10:32:53 +01:00
parent ecb6cdf02a
commit 60421893a2

View File

@ -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) {