From: Indu Bhagat <indu.bhagat@oracle.com>
To: binutils@sourceware.org
Cc: Indu Bhagat <indu.bhagat@oracle.com>
Subject: [PATCH, PR 29856] libsframe: avoid generating misaligned loads
Date: Wed, 14 Dec 2022 15:43:10 -0800 [thread overview]
Message-ID: <20221214234310.1247719-1-indu.bhagat@oracle.com> (raw)
Hello,
This patch fixes the PR 29856 "libsframe asan: load misaligned at
sframe.c:516". More details below in the commit log.
Testing Notes:
- Regression tested gas testsuite with -fsanitize=alignment for
--target=aarch64-elf showed the issues fixed and no new regressions.
- binutils try bit showed no new regressions
- various native and cross builds (on host aarch64-linux and host
x86_64-linux) showed no new regressions.
Thanks
------------------------
There are two places where unaligned loads were seen on aarch64:
- #1. access to the SFrame FRE stack offsets in the in-memory
representation/abstraction provided by libsframe.
- #2. access to the SFrame FRE start address in the on-disk representation
of the frame row entry.
For #1, we can fix this by reordering the struct members of
sframe_frame_row_entry in libsframe/sframe-api.h.
For #2, we need to default to using memcpy instead, and copy out the bytes
to a location for output.
SFrame format is an unaligned on-disk format. As such, there are other blobs
of memory in the on-disk SFrame FRE that are on not on their natural
boundaries. But that does not pose further problems yet, because the users
are provided access to the on-disk SFrame FRE data via libsframe's
sframe_frame_row_entry, the latter has its' struct members aligned on their
respective natural boundaries (and initialized using memcpy).
PR 29856 libsframe asan: load misaligned at sframe.c:516
ChangeLog:
PR libsframe/29856
* bfd/elf64-x86-64.c: Adjust as the struct members have been
reordered.
* libsframe/sframe.c (sframe_decode_fre_start_address): Use
memcpy to perform 16-bit/32-bit reads.
* libsframe/testsuite/libsframe.encode/encode-1.c: Adjust as the
struct members have been reordered.
include/ChangeLog:
PR libsframe/29856
* sframe-api.h: Reorder fre_offsets for natural alignment.
---
bfd/elf64-x86-64.c | 24 +++++++++----------
include/sframe-api.h | 8 +++++--
libsframe/sframe.c | 18 ++++++++++++--
.../testsuite/libsframe.encode/encode-1.c | 16 ++++++-------
4 files changed, 42 insertions(+), 24 deletions(-)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index afc8c76c52b..8cf733d89e0 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -822,48 +822,48 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] =
static const sframe_frame_row_entry elf_x86_64_sframe_null_fre =
{
0,
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* .sframe FRE covering the .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre1 =
{
0, /* SFrame FRE start address. */
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* .sframe FRE covering the .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre2 =
{
6, /* SFrame FRE start address. */
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* .sframe FRE covering the .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre1 =
{
0, /* SFrame FRE start address. */
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* .sframe FRE covering the .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre2 =
{
11, /* SFrame FRE start address. */
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* .sframe FRE covering the second .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
{
0, /* SFrame FRE start address. */
- SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B), /* FRE info. */
- {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */
+ {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
/* SFrame helper object for non-lazy PLT. Also used for IBT enabled PLT. */
diff --git a/include/sframe-api.h b/include/sframe-api.h
index 3338a2ebd5c..bd1833558a4 100644
--- a/include/sframe-api.h
+++ b/include/sframe-api.h
@@ -35,13 +35,17 @@ typedef struct sframe_encoder_ctx sframe_encoder_ctx;
/* User interfacing SFrame Row Entry.
An abstraction provided by libsframe so the consumer is decoupled from
- the binary format representation of the same. */
+ the binary format representation of the same.
+
+ The members are best ordered such that they are aligned at their natural
+ boundaries. This helps avoid usage of undesirable misaligned memory
+ accesses. See PR libsframe/29856. */
typedef struct sframe_frame_row_entry
{
uint32_t fre_start_addr;
- unsigned char fre_info;
unsigned char fre_offsets[MAX_OFFSET_BYTES];
+ unsigned char fre_info;
} sframe_frame_row_entry;
#define SFRAME_ERR ((int) -1)
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index ef821da3901..b8fde2f04f8 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -670,6 +670,11 @@ sframe_frame_row_entry_copy (sframe_frame_row_entry *dst, sframe_frame_row_entry
return 0;
}
+/* Decode the SFrame FRE start address offset value from FRE_BUF in on-disk
+ binary format, given the FRE_TYPE. Updates the FRE_START_ADDR.
+
+ Returns 0 on success, SFRAME_ERR otherwise. */
+
static int
sframe_decode_fre_start_address (const char *fre_buf,
uint32_t *fre_start_addr,
@@ -677,6 +682,9 @@ sframe_decode_fre_start_address (const char *fre_buf,
{
uint32_t saddr = 0;
int err = 0;
+ size_t addr_size = 0;
+
+ addr_size = sframe_fre_start_addr_size (fre_type);
if (fre_type == SFRAME_FRE_TYPE_ADDR1)
{
@@ -686,12 +694,18 @@ sframe_decode_fre_start_address (const char *fre_buf,
else if (fre_type == SFRAME_FRE_TYPE_ADDR2)
{
uint16_t *ust = (uint16_t *)fre_buf;
- saddr = (uint32_t)*ust;
+ /* SFrame is an unaligned on-disk format. Using memcpy helps avoid the
+ use of undesirable unaligned loads. See PR libsframe/29856. */
+ uint16_t tmp = 0;
+ memcpy (&tmp, ust, addr_size);
+ saddr = (uint32_t)tmp;
}
else if (fre_type == SFRAME_FRE_TYPE_ADDR4)
{
uint32_t *uit = (uint32_t *)fre_buf;
- saddr = (uint32_t)*uit;
+ int32_t tmp = 0;
+ memcpy (&tmp, uit, addr_size);
+ saddr = (uint32_t)tmp;
}
else
return sframe_set_errno (&err, SFRAME_ERR_INVAL);
diff --git a/libsframe/testsuite/libsframe.encode/encode-1.c b/libsframe/testsuite/libsframe.encode/encode-1.c
index 01481106a62..0f5225ff9ec 100644
--- a/libsframe/testsuite/libsframe.encode/encode-1.c
+++ b/libsframe/testsuite/libsframe.encode/encode-1.c
@@ -33,10 +33,10 @@ add_fde1 (sframe_encoder_ctx *encode, int idx)
int i, err;
/* A contiguous block containing 4 FREs. */
sframe_frame_row_entry fres[]
- = { {0x0, 0x3, {0x8, 0, 0}},
- {0x1, 0x5, {0x10, 0xf0, 0}},
- {0x4, 0x4, {0x10, 0xf0, 0}},
- {0x1a, 0x5, {0x8, 0xf0, 0}}
+ = { {0x0, {0x8, 0, 0}, 0x3},
+ {0x1, {0x10, 0xf0, 0}, 0x5},
+ {0x4, {0x10, 0xf0, 0}, 0x4},
+ {0x1a, {0x8, 0xf0, 0}, 0x5}
};
unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
@@ -58,10 +58,10 @@ add_fde2 (sframe_encoder_ctx *encode, int idx)
int i, err;
/* A contiguous block containing 4 FREs. */
sframe_frame_row_entry fres[]
- = { {0x0, 0x3, {0x8, 0, 0}},
- {0x1, 0x5, {0x10, 0xf0, 0}},
- {0x4, 0x4, {0x10, 0xf0, 0}},
- {0xf, 0x5, {0x8, 0xf0, 0}}
+ = { {0x0, {0x8, 0, 0}, 0x3},
+ {0x1, {0x10, 0xf0, 0}, 0x5},
+ {0x4, {0x10, 0xf0, 0}, 0x4},
+ {0xf, {0x8, 0xf0, 0}, 0x5}
};
unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
--
2.37.2
next reply other threads:[~2022-12-14 23:43 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-14 23:43 Indu Bhagat [this message]
2022-12-15 12:58 ` Nick Clifton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221214234310.1247719-1-indu.bhagat@oracle.com \
--to=indu.bhagat@oracle.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).