This regression caused by following patch. It is mostly arm code but also affecting x86. If I remove this patch segfault will go away. $ cat unsubmitted-ldso-abi-check.diff --- elf/dl-load.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1438,6 +1438,209 @@ _dl_debug_printf_c ("\t\t(%s)\n", what); } +#ifdef __arm__ +/* Read an unsigned leb128 value from P, store the value in VAL, return + P incremented past the value. We assume that a word is large enough to + hold any value so encoded; if it is smaller than a pointer on some target, + pointers should not be leb128 encoded on that target. */ +static unsigned char * +read_uleb128 (unsigned char *p, unsigned long *val) +{ + unsigned int shift = 0; + unsigned char byte; + unsigned long result; + + result = 0; + do + { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *val = result; + return p; +} + + +#define ATTR_TAG_FILE 1 +#define ABI_VFP_args 28 +#define VFP_ARGS_IN_VFP_REGS 1 + +/* Check consistency of ABI in the ARM attributes. Search through the + section headers looking for the ARM attributes section, then + check the VFP_ARGS attribute. */ +static int +check_arm_attributes_hfabi(int fd, ElfW(Ehdr) *ehdr, bool *is_hf) +{ + unsigned int i; + ElfW(Shdr) *shdrs; + int sh_size = ehdr->e_shentsize * ehdr->e_shnum; + + /* Load in the section headers so we can look for the attributes + * section */ + shdrs = alloca(sh_size); + __lseek (fd, ehdr->e_shoff, SEEK_SET); + if ((size_t) __libc_read (fd, (void *) shdrs, sh_size) != sh_size) + return -1; + + for (i = 0; i < ehdr->e_shnum; i++) + { + if (SHT_ARM_ATTRIBUTES == shdrs[i].sh_type) + { + /* We've found a likely section. Load the contents and + * check the tags */ + unsigned char *contents = alloca(shdrs[i].sh_size); + unsigned char *p = contents; + unsigned char * end; + + __lseek (fd, shdrs[i].sh_offset, SEEK_SET); + if ((size_t) __libc_read (fd, (void *) contents, shdrs[i].sh_size) != shdrs[i].sh_size) + return -1; + + /* Sanity-check the attribute section details. Make sure + * that it's the "aeabi" section, that's all we care + * about. */ + if (*p == 'A') + { + unsigned long len = shdrs[i].sh_size - 1; + unsigned long namelen; + p++; + + while (len > 0) + { + unsigned long section_len = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; + if (section_len > len) + { + _dl_debug_printf_c (" invalid section len %lu, max remaining %lu\n", section_len, len); + section_len = len; + } + + p += 4; + len -= section_len; + section_len -= 4; + + if (0 != strcmp((char *)p, "aeabi")) + { + _dl_debug_printf_c (" ignoring unknown attr section %s\n", p); + p += section_len; + continue; + } + namelen = strlen((char *)p) + 1; + p += namelen; + section_len -= namelen; + + /* We're in a valid section. Walk through this + * section looking for the tag we care about + * (ABI_VFP_args) */ + while (section_len > 0) + { + unsigned long val = 0; + unsigned long tag; + unsigned long size; + + end = p; + tag = (*p++); + + size = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; + if (size > section_len) + { + _dl_debug_printf_c (" invalid subsection length %lu, max allowed %lu\n", size, section_len); + size = section_len; + } + p += 4; + + section_len -= size; + end += size; + if (ATTR_TAG_FILE != tag) + { + /* ignore, we don't care */ + _dl_debug_printf_c (" ignoring unknown subsection with type %lu length %lu\n", tag, size); + p = end; + continue; + } + while (p < end) + { + p = read_uleb128 (p, &tag); + /* Handle the different types of tag. */ + if ( (tag == 4) || (tag == 5) || (tag == 67) ) + { + /* Special cases for string values */ + namelen = strlen((char *)p) + 1; + p += namelen; + } + else + { + p = read_uleb128 (p, &val); + } + if ( (tag == ABI_VFP_args) && (val == VFP_ARGS_IN_VFP_REGS) ) + { + *is_hf = 1; + return 0; + } + } + } + } + } + } + } + + return 0; +} + + +/* ARM-specific checks. If we're built using the HF ABI, then fail any + attempts to use the SF ABI (and vice versa). Then, check for + consistency of ABI in terms of passing VFP args. */ +static int +arm_specific_checks(int fd, const char *name, ElfW(Ehdr) *ehdr) +{ + static int all_hf = -1; /* unset */ + bool is_hf = false; + int ret; + + ret = check_arm_attributes_hfabi(fd, ehdr, &is_hf); + if (ret != 0) + return ret; + +#ifdef __ARM_PCS_VFP + if (!is_hf) + return EINVAL; +#else + if (is_hf) + return EINVAL; +#endif + + if (all_hf == -1) + { + if (is_hf) + all_hf = 1; + else + all_hf = 0; + } + else if (all_hf == 1 && !is_hf) + return EINVAL; + else if (all_hf == 0 && is_hf) + return EINVAL; + return 0; +} +#endif + + +/* Run any architecture-specific checks that might be needed for the + current architecture. */ +static int +arch_specific_checks(int fd, const char *name, ElfW(Ehdr) *ehdr) +{ +#ifdef __arm__ + return arm_specific_checks(fd, name, ehdr); +#endif + + return 0; +} + + /* Open a file and verify it is an ELF file for this architecture. We ignore only ELF files for other architectures. Non-ELF files and ELF files with different header information cause fatal errors since @@ -1676,6 +1879,7 @@ /* Check .note.ABI-tag if present. */ for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph) + { if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4) { ElfW(Addr) size = ph->p_filesz; @@ -1751,6 +1955,21 @@ } free (abi_note_malloced); } + if (-1 != fd) + { + int error = arch_specific_checks(fd, name, ehdr); + if (EINVAL == error) + { + goto close_and_out; + } + if (0 != error) + { + errstring = N_("Unable to run arch-specific checks\n"); + goto call_lose; + } + } + + } return fd; }