From: Alan Modra <amodra@gmail.com>
To: Chenghua Xu <paul.hua.gm@gmail.com>,
"Maciej W. Rozycki" <macro@orcam.me.uk>
Cc: binutils@sourceware.org
Subject: PR28306, segfault in _bfd_mips_elf_reloc_unshuffle
Date: Wed, 8 Sep 2021 20:30:22 +0930 [thread overview]
Message-ID: <YTiXxtuLP+Cwcbkw@squeak.grove.modra.org> (raw)
Protect the _bfd_mips_elf_reloc_unshuffle call in mips16_gprel_reloc
by checking the reloc offset. The other changes catch potential
buffer overflows when processing relocations near the end of a
section.
OK to apply?
PR 28306
* elf64-mips.c (mips16_gprel_reloc): Sanity check reloc offset.
(mips_elf64_gprel32_reloc): Use bfd_reloc_offset_in_range.
* elfxx-mips.c (_bfd_mips_elf_gprel16_with_gp): Likewise.
(_bfd_mips_elf_hi16_reloc, _bfd_mips_elf_lo16_reloc): Likewise.
(_bfd_mips_elf_generic_reloc): Likewise. Comment.
* elf32-mips.c (gprel32_with_gp): Use bfd_reloc_offset_in_range.
* elfn32-mips.c (gprel32_with_gp): Likewise.
(elf_mips_howto_table_rela <R_MIPS_NONE>): Correct size.
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index f8467de478b..100e6e57143 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -1858,7 +1858,8 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
/* Set val to the offset into the section or symbol. */
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index 9ad884fafb6..764c686c0e8 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -3581,7 +3581,8 @@ mips_elf64_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
/* Set val to the offset into the section or symbol. */
@@ -3662,6 +3663,10 @@ mips16_gprel_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
if (ret != bfd_reloc_ok)
return ret;
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
+ return bfd_reloc_outofrange;
+
location = (bfd_byte *) data + reloc_entry->address;
_bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false,
location);
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index dc607e776d1..2ab0bae976a 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -877,7 +877,7 @@ static reloc_howto_type elf_mips_howto_table_rela[] =
/* No relocation. */
HOWTO (R_MIPS_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
@@ -3412,7 +3412,8 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry,
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
if (reloc_entry->howto->src_mask == 0)
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index e4827fd17de..aef5ede3ef0 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -2416,7 +2416,8 @@ _bfd_mips_elf_gprel16_with_gp (bfd *abfd, asymbol *symbol,
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
/* Set val to the offset into the section or symbol. */
@@ -2475,14 +2476,15 @@ static struct mips_hi16 *mips_hi16_list;
simplies the relocation handling in gcc. */
bfd_reloc_status_type
-_bfd_mips_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+_bfd_mips_elf_hi16_reloc (bfd *abfd, arelent *reloc_entry,
asymbol *symbol ATTRIBUTE_UNUSED, void *data,
asection *input_section, bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
struct mips_hi16 *n;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
n = bfd_malloc (sizeof *n);
@@ -2534,7 +2536,8 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
bfd_vma vallo;
bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
_bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false,
@@ -2586,7 +2589,7 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
bfd_perform_relocation and bfd_install_relocation. */
bfd_reloc_status_type
-_bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
+_bfd_mips_elf_generic_reloc (bfd *abfd, arelent *reloc_entry,
asymbol *symbol, void *data ATTRIBUTE_UNUSED,
asection *input_section, bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
@@ -2595,9 +2598,19 @@ _bfd_mips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc_entry,
bfd_reloc_status_type status;
bool relocatable;
+ /* ld -r or gas. */
relocatable = (output_bfd != NULL);
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+ /* We only use bfd_reloc_offset_in_range for final linking because
+ mips object files may use relocations that seem to access beyond
+ section limits. gas/testsuite/gas/mips/dla-reloc.s is an example
+ that puts R_MIPS_SUB, a 64-bit relocation, on the last
+ instruction in the section. If final linking that object file
+ the R_MIPS_SUB won't be processed here since it applies to the
+ addend for the next reloc rather than the section contents. */
+ if (!relocatable
+ && !bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, reloc_entry->address))
return bfd_reloc_outofrange;
/* Build up the field adjustment in VAL. */
--
Alan Modra
Australia Development Lab, IBM
next reply other threads:[~2021-09-08 11:00 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-08 11:00 Alan Modra [this message]
2021-09-09 9:51 ` Maciej W. Rozycki
2021-09-09 14:14 ` Alan Modra
2021-09-10 8:27 ` Alan Modra
2021-09-10 9:50 ` Maciej W. Rozycki
2021-09-10 11:01 ` Alan Modra
2022-12-09 11:08 Alan Modra
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=YTiXxtuLP+Cwcbkw@squeak.grove.modra.org \
--to=amodra@gmail.com \
--cc=binutils@sourceware.org \
--cc=macro@orcam.me.uk \
--cc=paul.hua.gm@gmail.com \
/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).