From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id ECFC91395E2 for ; Sat, 12 Nov 2016 07:15:44 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 5E89A21C0A0; Sat, 12 Nov 2016 07:15:44 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 36C4D21C0A0 for ; Sat, 12 Nov 2016 07:15:39 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 2FA56341663 for ; Sat, 12 Nov 2016 07:15:38 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 6C3F324BD for ; Sat, 12 Nov 2016 07:15:35 +0000 (UTC) From: "Mike Frysinger" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Frysinger" Message-ID: <1478934613.e20faa493f9dd326f7bc0fbf2c0abe1a4fdae0e4.vapier@gentoo> Subject: [gentoo-commits] proj/pax-utils:master commit in: / X-VCS-Repository: proj/pax-utils X-VCS-Files: paxldso.c X-VCS-Directories: / X-VCS-Committer: vapier X-VCS-Committer-Name: Mike Frysinger X-VCS-Revision: e20faa493f9dd326f7bc0fbf2c0abe1a4fdae0e4 X-VCS-Branch: master Date: Sat, 12 Nov 2016 07:15:35 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 73c948d4-2ee5-4e99-b1db-e30fb4afe6a5 X-Archives-Hash: 421046eae2fadf53c1d9e6b613cf7bd5 commit: e20faa493f9dd326f7bc0fbf2c0abe1a4fdae0e4 Author: Mike Frysinger gentoo org> AuthorDate: Wed Jul 27 04:47:39 2016 +0000 Commit: Mike Frysinger gentoo org> CommitDate: Sat Nov 12 07:10:13 2016 +0000 URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=e20faa49 paxldso: properly decode the flags bits in the cache This fixes handling of multiple ABIs for a single arch like x86/x86_64/x32 or mips o32/n32/n64. It also fixes decoding of arm float libs. paxldso.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 34 deletions(-) diff --git a/paxldso.c b/paxldso.c index 5ea0bfc..2227387 100644 --- a/paxldso.c +++ b/paxldso.c @@ -20,30 +20,121 @@ static size_t ldcache_size = 0; static char *ldso_cache_buf = NULL; static size_t ldso_cache_buf_size = 0; +#if defined(__GLIBC__) || defined(__UCLIBC__) + /* Defines can be seen in glibc's sysdeps/generic/ldconfig.h */ -#define LDSO_CACHE_MAGIC "ld.so-" -#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) -#define LDSO_CACHE_VER "1.7.0" -#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) -#define FLAG_ANY -1 -#define FLAG_TYPE_MASK 0x00ff -#define FLAG_LIBC4 0x0000 -#define FLAG_ELF 0x0001 -#define FLAG_ELF_LIBC5 0x0002 -#define FLAG_ELF_LIBC6 0x0003 -#define FLAG_REQUIRED_MASK 0xff00 -#define FLAG_SPARC_LIB64 0x0100 -#define FLAG_IA64_LIB64 0x0200 -#define FLAG_X8664_LIB64 0x0300 -#define FLAG_S390_LIB64 0x0400 -#define FLAG_POWERPC_LIB64 0x0500 -#define FLAG_MIPS64_LIBN32 0x0600 -#define FLAG_MIPS64_LIBN64 0x0700 -#define FLAG_X8664_LIBX32 0x0800 -#define FLAG_ARM_LIBHF 0x0900 -#define FLAG_AARCH64_LIB64 0x0a00 +#define LDSO_CACHE_MAGIC "ld.so-" +#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) +#define LDSO_CACHE_VER "1.7.0" +#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) +#define FLAG_ANY -1 +#define FLAG_TYPE_MASK 0x00ff +#define FLAG_LIBC4 0x0000 +#define FLAG_ELF 0x0001 +#define FLAG_ELF_LIBC5 0x0002 +#define FLAG_ELF_LIBC6 0x0003 +#define FLAG_REQUIRED_MASK 0xff00 +#define FLAG_SPARC_LIB64 0x0100 +#define FLAG_IA64_LIB64 0x0200 +#define FLAG_X8664_LIB64 0x0300 +#define FLAG_S390_LIB64 0x0400 +#define FLAG_POWERPC_LIB64 0x0500 +#define FLAG_MIPS64_LIBN32 0x0600 +#define FLAG_MIPS64_LIBN64 0x0700 +#define FLAG_X8664_LIBX32 0x0800 +#define FLAG_ARM_LIBHF 0x0900 +#define FLAG_AARCH64_LIB64 0x0a00 +#define FLAG_ARM_LIBSF 0x0b00 +#define FLAG_MIPS_LIB32_NAN2008 0x0c00 +#define FLAG_MIPS64_LIBN32_NAN2008 0x0d00 +#define FLAG_MIPS64_LIBN64_NAN2008 0x0e00 + +typedef struct { + int flags; + unsigned int sooffset; + unsigned int liboffset; +} libentry_t; + +static bool is_compatible(elfobj *elf, libentry_t *libent) +{ + int flags = libent->flags & FLAG_REQUIRED_MASK; + + /* We assume that ((flags & FLAG_TYPE_MASK) == FLAG_ELF_LIBC6) + * since anything older is very very old and no one cares. + * + * Otherwise we really only need to check here for cases where + * an arch has more than one ABI per bitsize (e.g. x86, x32, and + * x86_64). The default case should be fine otherwise. + */ + + if (elf->elf_class == ELFCLASS32) { + Elf32_Ehdr *ehdr = EHDR32(elf->ehdr); + + switch (EGET(ehdr->e_machine)) { + case EM_AARCH64: + break; + case EM_ARM: + if ((flags == FLAG_ARM_LIBHF && (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD)) || + (flags == FLAG_ARM_LIBSF && (ehdr->e_flags & EF_ARM_ABI_FLOAT_SOFT)) || + (flags == 0 && !(ehdr->e_flags & (EF_ARM_ABI_FLOAT_HARD | EF_ARM_ABI_FLOAT_SOFT)))) + return true; + break; + case EM_IA_64: + break; + case EM_MIPS: { + int ef_flags = (ehdr->e_flags & (EF_MIPS_ABI2 | EF_MIPS_NAN2008)); + if ((flags == 0 && ef_flags == 0) || + (flags == FLAG_MIPS64_LIBN32 && ef_flags == EF_MIPS_ABI2) || + (flags == FLAG_MIPS_LIB32_NAN2008 && ef_flags == EF_MIPS_NAN2008) || + (flags == FLAG_MIPS64_LIBN32_NAN2008 && ef_flags == (EF_MIPS_ABI2 | EF_MIPS_NAN2008))) + return true; + break; + } + case EM_X86_64: + if (flags == FLAG_X8664_LIBX32) + return true; + break; + default: + /* A sane enough default. */ + if (flags == 0) + return true; + break; + } + } else { + Elf64_Ehdr *ehdr = EHDR64(elf->ehdr); + + switch (EGET(ehdr->e_machine)) { + case EM_AARCH64: + if (flags == FLAG_AARCH64_LIB64) + return true; + break; + case EM_ARM: + break; + case EM_IA_64: + if (flags == FLAG_IA64_LIB64) + return true; + break; + case EM_MIPS: { + int ef_flags = (ehdr->e_flags & EF_MIPS_NAN2008); + if ((flags == FLAG_MIPS64_LIBN64 && ef_flags == 0) || + (flags == FLAG_MIPS64_LIBN64_NAN2008 && ef_flags == EF_MIPS_NAN2008)) + return true; + break; + } + case EM_X86_64: + if (flags == FLAG_X8664_LIB64) + return true; + break; + default: + /* A sane enough default. */ + if (flags != 0) + return true; + break; + } + } -#if defined(__GLIBC__) || defined(__UCLIBC__) + return false; +} char *ldso_cache_lookup_lib(elfobj *elf, const char *fname) { @@ -58,11 +149,6 @@ char *ldso_cache_lookup_lib(elfobj *elf, const char *fname) } header_t; header_t *header; - typedef struct { - int flags; - unsigned int sooffset; - unsigned int liboffset; - } libentry_t; libentry_t *libent; if (fname == NULL) @@ -110,13 +196,7 @@ char *ldso_cache_lookup_lib(elfobj *elf, const char *fname) const char *lib; size_t lib_len; - /* This should be more fine grained, but for now we assume that - * diff arches will not be cached together, and we ignore the - * the different multilib mips cases. - */ - if (elf->elf_class == ELFCLASS64 && !(libent[nlib].flags & FLAG_REQUIRED_MASK)) - continue; - if (elf->elf_class == ELFCLASS32 && (libent[nlib].flags & FLAG_REQUIRED_MASK)) + if (!is_compatible(elf, &libent[nlib])) continue; if (strcmp(fname, strs + libent[nlib].sooffset) != 0)