Re: [PATCH] libsframe: validate FDE/FRE subsection bounds in sframe_decode
Indu Bhagat <[email protected]> Wed, 22 Jul 2026 14:35:02 -0700
| Newsgroups | gmane.comp.gnu.binutils |
|---|---|
| Message-ID | <[email protected]> |
On 2026-06-21 14:12, Naveed Khan wrote: > sframe_decode only calls sframe_header_sanity_check_p, which verifies > that sfh_fdeoff <= sfh_freoff but never checks the header-supplied > offsets, lengths and counts against the size of the SFrame buffer. On > the native-endian decode path -- the foreign-endian path is bounds > checked inside flip_sframe -- a crafted SFrame section therefore drives > two out-of-bounds heap reads: > > - sframe_fde_tbl_init reads sfh_num_fdes function descriptor entries > starting at frame_buf + sfh_fdeoff, and > > - memcpy (dctx->sfd_fres, frame_buf + sfh_freoff, sfh_fre_len) copies > sfh_fre_len bytes starting at frame_buf + sfh_freoff. > > Both read past the end of the buffer. The defect is reachable from > objdump --sframe and readelf on an object file carrying a crafted > .sframe section; for example a 28-byte section whose header claims > sfh_fre_len = 0x10000 makes objdump --sframe read 64KB past the > section contents. > > Validate in sframe_decode that the FDE and FRE sub-sections described > by the header are fully contained in the buffer before they are read. > The checks use subtraction and division so the arithmetic cannot > overflow. > > Signed-off-by: Naveed Khan <[email protected]> > --- > diff --git a/libsframe/sframe.c b/libsframe/sframe.c > index cd6bb302..24d07ae3 100644 > --- a/libsframe/sframe.c > +++ b/libsframe/sframe.c > @@ -1480,6 +1480,25 @@ sframe_decode (const char *sf_buf, size_t sf_size, int *errp) > goto decode_fail_free; > } > hdrsz = sframe_get_hdr_size (dhp); > + > + /* Validate that the FDE and FRE sub-sections described by the SFrame > + header lie entirely within the SFrame buffer. The earlier call to > + sframe_header_sanity_check_p has checked that sfh_fdeoff <= sfh_freoff. > + The FDE sub-section holds sfh_num_fdes entries and precedes the FRE > + sub-section, which is sfh_fre_len bytes long. The arithmetic below uses > + subtraction and division so that it cannot itself overflow. */ > + size_t fde_size = sizeof (sframe_func_desc_entry_v2); > + if (sfp->sfp_version == SFRAME_VERSION_3) > + fde_size = sizeof (sframe_func_desc_idx_v3); > + if (hdrsz > sf_size > + || dhp->sfh_freoff > sf_size - hdrsz > + || dhp->sfh_fre_len > sf_size - hdrsz - dhp->sfh_freoff > + || dhp->sfh_num_fdes > (dhp->sfh_freoff - dhp->sfh_fdeoff) / fde_size) > + { > + sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); > + goto decode_fail_free; > + } > + > frame_buf += hdrsz; > > /* Handle the SFrame Function Descriptor Entry section. */ Thanks Naveed. Looks like this may need to be pushed on your behalf. Please confirm. Indu