elf: Check for corrupt symbol version info

The BFD linker with PR ld/23499 may generate shared libraries with
corrupt symbol version info which leads to linker error when the
corrupt shared library is used:

/usr/bin/ld: bin/libKF5Service.so.5.49.0: _edata: invalid version 21 (max 0)
/usr/bin/ld: bin/libKF5Service.so.5.49.0: error adding symbols: bad value

Add check for corrupt symbol version info to objdump:

00000000000af005 g    D  .data	0000000000000000  <corrupt>   _edata

and readelf:

   728: 00000000000af005     0 NOTYPE  GLOBAL DEFAULT   25 _edata@<corrupt> (5)

bfd/

	PR ld/23499
	* elf.c (_bfd_elf_get_symbol_version_string): Return
	_("<corrupt>") for corrupt symbol version info.

binutils/

	PR ld/23499
	* readelf.c (get_symbol_version_string): Return _("<corrupt>")
	for corrupt symbol version info.
This commit is contained in:
H.J. Lu 2018-08-25 06:17:52 -07:00
parent bbf6c6b8ca
commit 7a815dd566
4 changed files with 22 additions and 1 deletions

View File

@ -1,3 +1,9 @@
2018-08-25 H.J. Lu <hongjiu.lu@intel.com>
PR ld/23499
* elf.c (_bfd_elf_get_symbol_version_string): Return
_("<corrupt>") for corrupt symbol version info.
2018-08-24 H.J. Lu <hongjiu.lu@intel.com> 2018-08-24 H.J. Lu <hongjiu.lu@intel.com>
* elfxx-x86.c (_bfd_x86_elf_parse_gnu_properties): Handle * elfxx-x86.c (_bfd_x86_elf_parse_gnu_properties): Handle

View File

@ -1877,7 +1877,7 @@ _bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
{ {
Elf_Internal_Verneed *t; Elf_Internal_Verneed *t;
version_string = ""; version_string = _("<corrupt>");
for (t = elf_tdata (abfd)->verref; for (t = elf_tdata (abfd)->verref;
t != NULL; t != NULL;
t = t->vn_nextref) t = t->vn_nextref)

View File

@ -1,3 +1,9 @@
2018-08-25 H.J. Lu <hongjiu.lu@intel.com>
PR ld/23499
* readelf.c (get_symbol_version_string): Return _("<corrupt>")
for corrupt symbol version info.
2018-08-24 H.J. Lu <hongjiu.lu@intel.com> 2018-08-24 H.J. Lu <hongjiu.lu@intel.com>
* readelf.c (decode_x86_compat_isa): New function. * readelf.c (decode_x86_compat_isa): New function.

View File

@ -11300,6 +11300,7 @@ get_symbol_version_string (Filedata * filedata,
unsigned char data[2]; unsigned char data[2];
unsigned short vers_data; unsigned short vers_data;
unsigned long offset; unsigned long offset;
unsigned short max_vd_ndx;
if (!is_dynsym if (!is_dynsym
|| version_info[DT_VERSIONTAGIDX (DT_VERSYM)] == 0) || version_info[DT_VERSIONTAGIDX (DT_VERSYM)] == 0)
@ -11317,6 +11318,8 @@ get_symbol_version_string (Filedata * filedata,
if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data == 0) if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data == 0)
return NULL; return NULL;
max_vd_ndx = 0;
/* Usually we'd only see verdef for defined symbols, and verneed for /* Usually we'd only see verdef for defined symbols, and verneed for
undefined symbols. However, symbols defined by the linker in undefined symbols. However, symbols defined by the linker in
.dynbss for variables copied from a shared library in order to .dynbss for variables copied from a shared library in order to
@ -11359,6 +11362,9 @@ get_symbol_version_string (Filedata * filedata,
ivd.vd_flags = BYTE_GET (evd.vd_flags); ivd.vd_flags = BYTE_GET (evd.vd_flags);
} }
if ((ivd.vd_ndx & VERSYM_VERSION) > max_vd_ndx)
max_vd_ndx = ivd.vd_ndx & VERSYM_VERSION;
off += ivd.vd_next; off += ivd.vd_next;
} }
while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) && ivd.vd_next != 0); while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) && ivd.vd_next != 0);
@ -11450,6 +11456,9 @@ get_symbol_version_string (Filedata * filedata,
return (ivna.vna_name < strtab_size return (ivna.vna_name < strtab_size
? strtab + ivna.vna_name : _("<corrupt>")); ? strtab + ivna.vna_name : _("<corrupt>"));
} }
else if ((max_vd_ndx || (vers_data & VERSYM_VERSION) != 1)
&& (vers_data & VERSYM_VERSION) > max_vd_ndx)
return _("<corrupt>");
} }
return NULL; return NULL;
} }