From 721db032d6a35ff05975538b8d1c01a901f3ea52 Mon Sep 17 00:00:00 2001 From: Mikhail Novosyolov Date: Mon, 6 Apr 2020 05:18:58 +0300 Subject: [PATCH] patch: fix loading patchelf'ed libraries (RB#10231) --- glibc-ldconfig-patchelf-truncated.patch | 85 +++++++++++++++++++++++++ glibc.spec | 7 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 glibc-ldconfig-patchelf-truncated.patch diff --git a/glibc-ldconfig-patchelf-truncated.patch b/glibc-ldconfig-patchelf-truncated.patch new file mode 100644 index 0000000..4c21284 --- /dev/null +++ b/glibc-ldconfig-patchelf-truncated.patch @@ -0,0 +1,85 @@ +[PATCH] ldconfig: file truncated while reading soname after patchelf [BZ #23964] + +The way loadaddr is computed from the first LOAD segment in process_elf_file +assumes .dynstr is also contained in that segment. That is not necessarily +true, especially for libraries that have been touched by patchelf. + +With this patch, the address read from the dynamic segment is checked against +all applicable segments instead of only the first one. + + [BZ #23964] + * elf/readelflib.c: Fix resolving of loadaddr for .dynstr vaddr. +--- + elf/readelflib.c | 33 ++++++++++++++++----------------- + 1 file changed, 16 insertions(+), 17 deletions(-) + +diff --git a/elf/readelflib.c b/elf/readelflib.c +index 5a1e2dc2df..bc1195c175 100644 +--- a/elf/readelflib.c ++++ b/elf/readelflib.c +@@ -98,11 +98,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + + switch (segment->p_type) + { +- case PT_LOAD: +- if (loadaddr == (ElfW(Addr)) -1) +- loadaddr = segment->p_vaddr - segment->p_offset; +- break; +- + case PT_DYNAMIC: + if (dynamic_addr) + error (0, 0, _("more than one dynamic segment\n")); +@@ -176,11 +171,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + } + + } +- if (loadaddr == (ElfW(Addr)) -1) +- { +- /* Very strange. */ +- loadaddr = 0; +- } + + /* Now we can read the dynamic sections. */ + if (dynamic_size == 0) +@@ -190,22 +180,31 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + check_ptr (dynamic_segment); + + /* Find the string table. */ +- dynamic_strings = NULL; + for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; + ++dyn_entry) + { + check_ptr (dyn_entry); + if (dyn_entry->d_tag == DT_STRTAB) +- { +- dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); +- check_ptr (dynamic_strings); +- break; +- } ++ break; + } + +- if (dynamic_strings == NULL) ++ for (i = 0, segment = elf_pheader;i < elf_header->e_phnum; i++, segment++) ++ { ++ ElfW(Addr) vaddr = dyn_entry->d_un.d_ptr; ++ if (segment->p_type == PT_LOAD && ++ vaddr >= segment->p_vaddr && ++ vaddr < segment->p_vaddr + segment->p_filesz) ++ { ++ loadaddr = segment->p_vaddr - segment->p_offset; ++ break; ++ } ++ } ++ if (loadaddr == (ElfW(Addr)) -1) + return 1; + ++ dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); ++ check_ptr (dynamic_strings); ++ + /* Now read the DT_NEEDED and DT_SONAME entries. */ + for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; + ++dyn_entry) +-- +2.19.2 + diff --git a/glibc.spec b/glibc.spec index d2a5cae..356283c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -57,7 +57,7 @@ Summary: The GNU libc libraries Name: glibc Epoch: 6 Version: 2.24 -Release: 9 +Release: 11 License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ Group: System/Libraries Url: http://www.eglibc.org/ @@ -217,6 +217,10 @@ Patch205: glibc-2.24-CVE-2017-16997.patch Patch206: glibc-2.24-CVE-2017-15670.patch Patch208: glibc-2.24-CVE-2017-15804.patch +# https://sourceware.org/bugzilla/show_bug.cgi?id=23964 +# https://bugzilla.rosalinux.ru/show_bug.cgi?id=10231#c5 +Patch210: glibc-ldconfig-patchelf-truncated.patch + BuildRequires: autoconf2.5 BuildRequires: gettext BuildRequires: kernel-headers @@ -906,6 +910,7 @@ cp -a crypt_blowfish-%{crypt_bf_ver}/*.[chS] crypt/ %patch205 -p1 %patch206 -p1 %patch208 -p1 +%patch210 -p1 %if %{with selinux} # XXX kludge to build nscd with selinux support as it added -nostdinc