[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.