[07/10] libsframe: guard against buffer over-read in sframe_fde_tbl_init
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
Commit Message
In SFrame V3, the FDE attribute data is stored near the SFrame FREs. In
sframe_fde_tbl_init(), for SFrame V3 format,
fdep->sfdi_func_start_fre_off was used to index into fre_buf without
verifying if sfdi_func_start_fre_off + sizeof(sframe_func_desc_attr_v3)
<= fre_buf_len. If left unchecked, this may cause buffer over-reads in case
of invalid SFrame data.
Pass FRE buffer len to sframe_fde_tbl_init(), and validate
sfdi_func_start_fre_off against that guard before reading FDE attribute
data.
---
libsframe/sframe.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
Comments
On 8/28/2026 12:41 AM, Indu Bhagat wrote:
> In SFrame V3, the FDE attribute data is stored near the SFrame FREs. In
> sframe_fde_tbl_init(), for SFrame V3 format,
> fdep->sfdi_func_start_fre_off was used to index into fre_buf without
> verifying if sfdi_func_start_fre_off + sizeof(sframe_func_desc_attr_v3)
> <= fre_buf_len. If left unchecked, this may cause buffer over-reads in case
> of invalid SFrame data.
>
> Pass FRE buffer len to sframe_fde_tbl_init(), and validate
> sfdi_func_start_fre_off against that guard before reading FDE attribute
> data.
> ---
> libsframe/sframe.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
> diff --git a/libsframe/sframe.c b/libsframe/sframe.c
> @@ -140,8 +140,8 @@ sframe_fde_tbl_alloc (sf_fde_tbl **fde_tbl, unsigned int num_fdes)
>
> static int
> sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
> - const char *fre_buf, size_t *fidx_size,
> - unsigned int num_fdes, uint8_t ver)
> + const char *fre_buf, size_t fre_buf_len,
> + size_t *fidx_size, unsigned int num_fdes, uint8_t ver)
> {
> if (ver == SFRAME_VERSION_3 && SFRAME_VERSION == SFRAME_VERSION_3)
> {
> @@ -155,6 +155,10 @@ sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
> fde_tbl->entry[i].func_start_fre_off = fdep->sfdi_func_start_fre_off;
> /* V3 organizes the following data closer to the SFrame FREs for the
> function. Access them via the sfde_func_start_fre_off. */
> + if (fdep->sfdi_func_start_fre_off > fre_buf_len
> + || (sizeof (sframe_func_desc_attr_v3)
> + > (fre_buf_len - fdep->sfdi_func_start_fre_off)))
> + return SFRAME_ERR;
> const sframe_func_desc_attr_v3 *fattr
> = (sframe_func_desc_attr_v3 *)(fre_buf
> + fdep->sfdi_func_start_fre_off);
> @@ -1535,7 +1539,7 @@ sframe_decode (const char *sf_buf, size_t sf_size, int *errp)
>
> /* SFrame FDEs are at an offset of sfh_fdeoff from SFrame header end. */
> if (sframe_fde_tbl_init (dctx->sfd_funcdesc, frame_buf + dhp->sfh_fdeoff,
> - frame_buf + dhp->sfh_freoff,
> + frame_buf + dhp->sfh_freoff, dhp->sfh_fre_len,
> &fidx_size, dhp->sfh_num_fdes, sfp->sfp_version))
> {
> sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL);
Regards,
Jens
@@ -140,8 +140,8 @@ sframe_fde_tbl_alloc (sf_fde_tbl **fde_tbl, unsigned int num_fdes)
static int
sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
- const char *fre_buf, size_t *fidx_size,
- unsigned int num_fdes, uint8_t ver)
+ const char *fre_buf, size_t fre_buf_len,
+ size_t *fidx_size, unsigned int num_fdes, uint8_t ver)
{
if (ver == SFRAME_VERSION_3 && SFRAME_VERSION == SFRAME_VERSION_3)
{
@@ -155,6 +155,10 @@ sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
fde_tbl->entry[i].func_start_fre_off = fdep->sfdi_func_start_fre_off;
/* V3 organizes the following data closer to the SFrame FREs for the
function. Access them via the sfde_func_start_fre_off. */
+ if (fdep->sfdi_func_start_fre_off > fre_buf_len
+ || (sizeof (sframe_func_desc_attr_v3)
+ > (fre_buf_len - fdep->sfdi_func_start_fre_off)))
+ return SFRAME_ERR;
const sframe_func_desc_attr_v3 *fattr
= (sframe_func_desc_attr_v3 *)(fre_buf
+ fdep->sfdi_func_start_fre_off);
@@ -1535,7 +1539,7 @@ sframe_decode (const char *sf_buf, size_t sf_size, int *errp)
/* SFrame FDEs are at an offset of sfh_fdeoff from SFrame header end. */
if (sframe_fde_tbl_init (dctx->sfd_funcdesc, frame_buf + dhp->sfh_fdeoff,
- frame_buf + dhp->sfh_freoff,
+ frame_buf + dhp->sfh_freoff, dhp->sfh_fre_len,
&fidx_size, dhp->sfh_num_fdes, sfp->sfp_version))
{
sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL);