diff options
author | John Thacker <johnthacker@gmail.com> | 2023-05-28 07:14:52 -0400 |
---|---|---|
committer | John Thacker <johnthacker@gmail.com> | 2023-05-28 07:14:52 -0400 |
commit | b673bc022aa28c2c381cb96cae09357bd27eb0df (patch) | |
tree | 8d67516a07d1ad4c33f842b2d38455ca4a65ceec /epan | |
parent | 91cbf179bf890413bb6ff3152c163cd6a3fa0d37 (diff) |
kafka: Don't use after free
Neither tvb_new_child_real_data() nor tvb_composite_append() copy
the real data buffer that they're given. So we can't free a
decompressed buffer after making it a tvb.
We can realloc if the output size is smaller.
Fix #19105
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-kafka.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/epan/dissectors/packet-kafka.c b/epan/dissectors/packet-kafka.c index 20eb978f70..455f344433 100644 --- a/epan/dissectors/packet-kafka.c +++ b/epan/dissectors/packet-kafka.c @@ -1673,7 +1673,6 @@ decompress_lz4(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tv dst_size = (size_t)lz4_info.contentSize; } - decompressed_buffer = wmem_alloc(pinfo->pool, dst_size); size_t out_size; int count = 0; @@ -1683,12 +1682,16 @@ decompress_lz4(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tv goto end; } + decompressed_buffer = wmem_alloc(pinfo->pool, dst_size); out_size = dst_size; rc = LZ4F_decompress(lz4_ctxt, decompressed_buffer, &out_size, &data[src_offset], &src_size, NULL); if (LZ4F_isError(rc)) { goto end; } + if (out_size != dst_size) { + decompressed_buffer = (guint8 *)wmem_realloc(pinfo->pool, decompressed_buffer, out_size); + } if (out_size == 0) { goto end; } @@ -1730,7 +1733,7 @@ static gboolean decompress_snappy(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tvbuff_t **decompressed_tvb, int *decompressed_offset) { guint8 *data = (guint8*)tvb_memdup(pinfo->pool, tvb, offset, length); - size_t uncompressed_size; + size_t uncompressed_size, out_size; snappy_status rc = SNAPPY_OK; tvbuff_t *composite_tvb = NULL; gboolean ret = FALSE; @@ -1767,18 +1770,21 @@ decompress_snappy(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, goto end; } guint8 *decompressed_buffer = (guint8*)wmem_alloc(pinfo->pool, uncompressed_size); - rc = snappy_uncompress(&data[pos], chunk_size, decompressed_buffer, &uncompressed_size); + out_size = uncompressed_size; + rc = snappy_uncompress(&data[pos], chunk_size, decompressed_buffer, &out_size); if (rc != SNAPPY_OK) { goto end; } + if (out_size != uncompressed_size) { + decompressed_buffer = (guint8 *)wmem_realloc(pinfo->pool, decompressed_buffer, out_size); + } if (!composite_tvb) { composite_tvb = tvb_new_composite(); } tvb_composite_append(composite_tvb, - tvb_new_child_real_data(tvb, decompressed_buffer, (guint)uncompressed_size, (gint)uncompressed_size)); + tvb_new_child_real_data(tvb, decompressed_buffer, (guint)out_size, (gint)out_size)); pos += chunk_size; - wmem_free(pinfo->pool, decompressed_buffer); count++; DISSECTOR_ASSERT_HINT(count < MAX_LOOP_ITERATIONS, "MAX_LOOP_ITERATIONS exceeded"); } @@ -1793,12 +1799,16 @@ decompress_snappy(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, guint8 *decompressed_buffer = (guint8*)wmem_alloc(pinfo->pool, uncompressed_size); - rc = snappy_uncompress(data, length, decompressed_buffer, &uncompressed_size); + out_size = uncompressed_size; + rc = snappy_uncompress(data, length, decompressed_buffer, &out_size); if (rc != SNAPPY_OK) { goto end; } + if (out_size != uncompressed_size) { + decompressed_buffer = (guint8 *)wmem_realloc(pinfo->pool, decompressed_buffer, out_size); + } - *decompressed_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, (guint)uncompressed_size, (gint)uncompressed_size); + *decompressed_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, (guint)out_size, (gint)out_size); *decompressed_offset = 0; } |