[PATCH 09/10] libsframe: validate bounds before reads during endian flipping
Indu Bhagat <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
Currently, in both flip_sframe_fdes_with_fres_v2 () and
flip_sframe_fdes_with_fres_v3 (), the pointer fp to a location in the
SFrame FRE subsection is calculated using the unvalidated offset
fre_offset read from the SFrame section:
fp = fres + fre_offset
If an invalid or malicious SFrame binary contains a large fre_offset
(sfh_freoff is already validated in sframe_header_sanity_check_p), fp
may point past the buf_end.
Validate fp pointers in flip_sframe_fdes_with_fres_v2 () and
flip_sframe_fdes_with_fres_v3 () before calling the code to flip FREs.
While at it, also address similar issue with fdes location access.
This addresses some of the issues raised in PR libsframe/34273.
---
libsframe/sframe.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index 5ddd3962212..d3af9717fe2 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -794,7 +794,7 @@ flip_sframe_fdes_with_fres_v2 (char *frame_buf, size_t buf_size,
size_t fsz = sizeof (sframe_func_desc_entry_v2);
for (i = 0; i < num_fdes; fdes += fsz, i++)
{
- if (fdes >= buf_end)
+ if (fdes >= buf_end || (size_t)(buf_end - fdes) < fsz)
goto bad;
/* Handle FDE. */
@@ -817,6 +817,8 @@ flip_sframe_fdes_with_fres_v2 (char *frame_buf, size_t buf_size,
fp = fres + fre_offset;
for (; j < prev_frep_index + num_fres; j++)
{
+ if (fp < fres || fp >= buf_end)
+ goto bad;
if (flip_fre (fp, buf_end - fp, fre_type, &esz))
goto bad;
fre_bytes_flipped += esz;
@@ -890,7 +892,7 @@ flip_sframe_fdes_with_fres_v3 (char *frame_buf, size_t buf_size,
size_t fsz = sizeof (sframe_func_desc_idx_v3);
for (i = 0; i < num_fdes; fdes += fsz, i++)
{
- if (fdes >= buf_end)
+ if (fdes >= buf_end || (size_t)(buf_end - fdes) < fsz)
goto bad;
/* Handle FDE. */
@@ -909,6 +911,10 @@ flip_sframe_fdes_with_fres_v3 (char *frame_buf, size_t buf_size,
/* Handle FDE attr (only in V3). */
fp = fres + fre_offset;
+ if (fp < fres || fp >= buf_end
+ || (size_t)(buf_end - fp) < sizeof (sframe_func_desc_attr_v3))
+ goto bad;
+
if (to_foreign && sframe_decode_fde_attr_v3 (fp, buf_end - fp,
&num_fres, &fre_type))
goto bad;
@@ -926,6 +932,8 @@ flip_sframe_fdes_with_fres_v3 (char *frame_buf, size_t buf_size,
fp += sizeof (sframe_func_desc_attr_v3);
for (; j < prev_frep_index + num_fres; j++)
{
+ if (fp < fres || fp >= buf_end)
+ goto bad;
if (flip_fre (fp, buf_end - fp, fre_type, &esz))
goto bad;
fre_bytes_flipped += esz;
--
2.43.0