Discussion:
[ARM] Avoid dereferencing null pointers
Christophe Lyon
2018-10-23 14:21:41 UTC
Permalink
Hi,

While building an ARM FDPIC toolchain with a compiler generating Thumb
code, I face a couple of null pointer dereferences in cmse_scan().

When browsing ld-uClibc.so.1, all the external symbols have no info in
sym_hashes (sym_hashes[X] == NULL), and when handling libgcc_s.so.1
for the 2nd time in the same command, sym_hashes == NULL.

I don't know why this doesn't happen with a compiler generating Arm
code (ie. why the symbol tables are handled differently), but the
attached small patch prevents the linker from crashing.

OK?

Thanks,

Christophe
Alan Modra
2018-10-23 22:16:21 UTC
Permalink
Post by Christophe Lyon
Hi,
While building an ARM FDPIC toolchain with a compiler generating Thumb
code, I face a couple of null pointer dereferences in cmse_scan().
When browsing ld-uClibc.so.1, all the external symbols have no info in
sym_hashes (sym_hashes[X] == NULL), and when handling libgcc_s.so.1
for the 2nd time in the same command, sym_hashes == NULL.
I don't know why this doesn't happen with a compiler generating Arm
code (ie. why the symbol tables are handled differently), but the
attached small patch prevents the linker from crashing.
OK?
No, this is just papering over the real problem. You need to find out
why the sym hashes are not being set up (or are being overwritten).
--
Alan Modra
Australia Development Lab, IBM
Thomas Preudhomme
2018-10-24 09:37:59 UTC
Permalink
Hi Christophe,

I'm a bit surprised cmse_scan is run at all in your case. Where you
targeting an M profile core?

Regarding sym_hashes[X] being null, under what conditions can a global
symbol have a null hash?

Best regards,

Thomas
Post by Alan Modra
Post by Christophe Lyon
Hi,
While building an ARM FDPIC toolchain with a compiler generating Thumb
code, I face a couple of null pointer dereferences in cmse_scan().
When browsing ld-uClibc.so.1, all the external symbols have no info in
sym_hashes (sym_hashes[X] == NULL), and when handling libgcc_s.so.1
for the 2nd time in the same command, sym_hashes == NULL.
I don't know why this doesn't happen with a compiler generating Arm
code (ie. why the symbol tables are handled differently), but the
attached small patch prevents the linker from crashing.
OK?
No, this is just papering over the real problem. You need to find out
why the sym hashes are not being set up (or are being overwritten).
--
Alan Modra
Australia Development Lab, IBM
Alan Modra
2018-10-24 11:36:24 UTC
Permalink
Post by Thomas Preudhomme
Hi Christophe,
I'm a bit surprised cmse_scan is run at all in your case. Where you
targeting an M profile core?
Regarding sym_hashes[X] being null, under what conditions can a global
symbol have a null hash?
I sent a little more info to Christophe privately, after I thought a
little more about the problem. Guess I should have sent it to the
list.

You can have sym_hashes[n] being 0 when you have an as-needed library
that wasn't needed (it's loaded but then unloaded).

Note this elflink.c code:
if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
{
unsigned int i;

/* Restore the symbol table. */
old_ent = (char *) old_tab + tabsize;
memset (elf_sym_hashes (abfd), 0,
extsymcount * sizeof (struct elf_link_hash_entry *));

The memset zaps all the sym_hashes, because after restoring the symbol
table to as it was before loading the as-needed library, the symbol
pointers are no longer valid.

The patch I suggest instead of the one Christophe posted is:

diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 2c321bbcb6..5adec5e473 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -6449,7 +6449,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
asection *section;
Elf_Internal_Sym *local_syms = NULL;

- if (!is_arm_elf (input_bfd))
+ if (!is_arm_elf (input_bfd)
+ || (elf_dyn_lib_class (input_bfd) & DYN_AS_NEEDED) != 0)
continue;

num_a8_relocs = 0;
--
Alan Modra
Australia Development Lab, IBM
Christophe Lyon
2018-10-24 12:49:40 UTC
Permalink
Post by Alan Modra
Post by Thomas Preudhomme
Hi Christophe,
I'm a bit surprised cmse_scan is run at all in your case. Where you
targeting an M profile core?
Regarding sym_hashes[X] being null, under what conditions can a global
symbol have a null hash?
I sent a little more info to Christophe privately, after I thought a
little more about the problem. Guess I should have sent it to the
list.
You can have sym_hashes[n] being 0 when you have an as-needed library
that wasn't needed (it's loaded but then unloaded).
if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
{
unsigned int i;
/* Restore the symbol table. */
old_ent = (char *) old_tab + tabsize;
memset (elf_sym_hashes (abfd), 0,
extsymcount * sizeof (struct elf_link_hash_entry *));
The memset zaps all the sym_hashes, because after restoring the symbol
table to as it was before loading the as-needed library, the symbol
pointers are no longer valid.
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 2c321bbcb6..5adec5e473 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -6449,7 +6449,8 @@ elf32_arm_size_stubs (bfd *output_bfd,
asection *section;
Elf_Internal_Sym *local_syms = NULL;
- if (!is_arm_elf (input_bfd))
+ if (!is_arm_elf (input_bfd)
+ || (elf_dyn_lib_class (input_bfd) & DYN_AS_NEEDED) != 0)
continue;
num_a8_relocs = 0;
Thank you very much Alan for your time, explanations, and patch: I can
confirm it works for me. Can you commit it?
Post by Alan Modra
--
Alan Modra
Australia Development Lab, IBM
Loading...