dl_open segment fault in ubuntu18.10 glibc2.28

Bug #1821677 reported by hongtao.liu
16
This bug affects 2 people
Affects Status Importance Assigned to Milestone
glibc (Ubuntu)
Fix Released
High
Adam Conrad
Bionic
Fix Released
Undecided
Unassigned
Cosmic
Won't Fix
Undecided
Unassigned
Disco
Fix Released
High
Adam Conrad

Bug Description

[Impact]

* Dlopen() may crash.

[Test Case]

$ sudo apt install make gcc
$ wget https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1821677/+attachment/5252188/+files/dl-big-note.tar.xz
$ tar -xf dl-big-note.tar.xz
$ cd dl-big-note/
$ make
$ ./dl-big-note dl-big-note-lib.so

 all ok

[Where problems could occur]

* The fix is correcting a patch that was not updated to the new upstream code that was backported. There is little change in the code, but in case of an error it can crash again, let dlopen load an invalid ELF file due to the false positive verification or reject a valid ELF file due to erroneoudly failing verification (least likely).

[Other Info]

I've tested the fix with an amd64-only build and I'm building the packages here for all arches:
https://launchpad.net/~ci-train-ppa-service/+archive/ubuntu/4242/+packages

[Original Bug Text]
With following testcase:

~/work/glibc$ cat foo.c

#include <dlfcn.h>
#include <stdio.h>

int main(int argc, char **argv) {
  if (argc < 1) return 1;
  printf("Trying to open %s\n", argv[1]);
  void *liball = dlopen(argv[1], RTLD_NOW);
  if(liball == NULL) {
    printf("\nERROR: %s", dlerror());
    return -1;
  }
  if(dlclose(liball)==0) {printf("\n all ok\n");}
  return 0;
}

compile with
~/work/glibc$ gcc -O0 -g foo.c -ldl

then get segment fault:

~/work/glibc$ ./a.out intel64_lin/libsvml.so
Trying to open intel64_lin/libsvml.so
Segmentation fault (core dumped)

coredump as:

(gdb) bt
#0 __GI___libc_free (mem=0x7ffff7d49010) at malloc.c:3085
#1 0x00007ffff7fdb6b6 in open_verify (
    name=0x555555559670 "/home/lilicui/intel64_lin/libsvml.so",
    fbp=fbp@entry=0x7fffffffd530, loader=<optimized out>,
    mode=mode@entry=-1879048190,
    found_other_class=found_other_class@entry=0x7fffffffd51f, free_name=true,
    whatcode=0, fd=3) at dl-load.c:1977
#2 0x00007ffff7fdc926 in _dl_map_object (loader=loader@entry=0x7ffff7ffe190,
    name=name@entry=0x7fffffffe1b7 "/home/lilicui/intel64_lin/libsvml.so",
    type=type@entry=2, trace_mode=trace_mode@entry=0,
    mode=mode@entry=-1879048190, nsid=<optimized out>) at dl-load.c:2401
#3 0x00007ffff7fe79c4 in dl_open_worker (a=a@entry=0x7fffffffdaa0)
    at dl-open.c:228
#4 0x00007ffff7f1b48f in __GI__dl_catch_exception (exception=<optimized out>,
    operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:196
#5 0x00007ffff7fe72c6 in _dl_open (
    file=0x7fffffffe1b7 "/home/lilicui/intel64_lin/libsvml.so",
    mode=-2147483646, caller_dlopen=0x5555555551cb <main+86>,
    nsid=<optimized out>, argc=2, argv=0x7fffffffde08, env=0x7fffffffde20)
    at dl-open.c:599
#6 0x00007ffff7faa256 in dlopen_doit (a=a@entry=0x7fffffffdcc0) at dlopen.c:66
#7 0x00007ffff7f1b48f in __GI__dl_catch_exception (
    exception=exception@entry=0x7fffffffdc60, operate=<optimized out>,
--Type <RET> for more, q to quit, c to continue without paging--
    args=<optimized out>) at dl-error-skeleton.c:196
#8 0x00007ffff7f1b51f in __GI__dl_catch_error (
    objname=0x7ffff7fae0f0 <last_result+16>,
    errstring=0x7ffff7fae0f8 <last_result+24>,
    mallocedp=0x7ffff7fae0e8 <last_result+8>, operate=<optimized out>,
    args=<optimized out>) at dl-error-skeleton.c:215
#9 0x00007ffff7faaa25 in _dlerror_run (
    operate=operate@entry=0x7ffff7faa200 <dlopen_doit>,
    args=args@entry=0x7fffffffdcc0) at dlerror.c:163
#10 0x00007ffff7faa2e6 in __dlopen (file=<optimized out>, mode=<optimized out>)
    at dlopen.c:87
#11 0x00005555555551cb in main (argc=2, argv=0x7fffffffde08) at foo.c:7

intel64_lin/libsvml.so is icc19.0(aleady released) runtime library, refer to attachment.

Ubuntu version:

~/work/glibc$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.10
Release: 18.10
Codename: cosmic

Glibc version:

~/work/glibc$ ldd --version
ldd (Ubuntu GLIBC 2.28-0ubuntu1) 2.28
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

It works fine with Glibc_2.28 upstream, and Glibc_2.28 on Fedora 29, but failed with Glibc 2.28 in Ubuntu 18.10

I found ubuntu18.10 was backporting its own patches, would that affect such testcase?

hongtao.liu (liuhongt)
information type: Public → Public Security
information type: Public Security → Public
Revision history for this message
Sunil Pandey (skpgkp1) wrote :
Download full text (7.5 KiB)

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 att...

Read more...

Matthias Klose (doko)
Changed in glibc (Ubuntu):
importance: Undecided → High
tags: added: rls-dd-incoming
tags: added: rls-cc-incoming
Revision history for this message
Sunil Pandey (skpgkp1) wrote :

Attached is small test case to reproduce this issue.

$ tar -Jxvf dl-big-note.tar.xz
dl-big-note/
dl-big-note/dl-big-note-lib.S
dl-big-note/dl-big-note.c
dl-big-note/Makefile
$ cd dl-big-note/
$ make runtest
gcc -c -o dl-big-note-lib.o dl-big-note-lib.S
gcc -shared -o dl-big-note-lib.so dl-big-note-lib.o
gcc -o dl-big-note dl-big-note.c -ldl
./dl-big-note
make: *** [Makefile:10: runtest] Segmentation fault (core dumped)

tags: removed: rls-cc-incoming rls-dd-incoming
tags: added: id-5ca6214756f1b84f8df62a00
Adam Conrad (adconrad)
Changed in glibc (Ubuntu Disco):
assignee: nobody → Adam Conrad (adconrad)
status: New → Fix Committed
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package glibc - 2.29-0ubuntu2

---------------
glibc (2.29-0ubuntu2) disco; urgency=medium

  * debian/patches/git-updates.diff: Update from upstream stable branch,
    including "S390: Mark vx and vxe as important hwcap" (LP: #1821200)
  * debian/testsuite-xfail-debian.mk: XFAIL new tst-nss-test3 for disco.
  * debian/debhelper.in/libc.postinst: Only restart services once each.
  * debian/patches/arm/unsubmitted-ldso-abi-check.diff: Fix rtld segv in
    dl_open() introduced via merge with upstream at 2.28 (LP: #1821677)
  * debian/testsuite-xfail-debian.mk: XFAIL new tst-support_descriptors.

 -- Adam Conrad <email address hidden> Sun, 07 Apr 2019 14:12:24 -0600

Changed in glibc (Ubuntu Disco):
status: Fix Committed → Fix Released
Revision history for this message
Sunil Pandey (skpgkp1) wrote :

Is it fixed in 18.04 update release OR any plan to fix it?

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in glibc (Ubuntu Cosmic):
status: New → Confirmed
Revision history for this message
Andrew Snyder (arsnyder16) wrote :

I am experiencing this same issue on LIBC 2.27-3ubuntu1.3 and it appears to be the same dll. I did not see it with GLIBC 2.27-3ubuntu1.2

$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 18.04.5 LTS
Release: 18.04
Codename: bionic

$ ldd --version
ldd (Ubuntu GLIBC 2.27-3ubuntu1.3) 2.27

Thread 1 "node" received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x7fffff730010) at malloc.c:3113
3113 malloc.c: No such file or directory.
#0 __GI___libc_free (mem=0x7fffff730010) at malloc.c:3113
#1 0x00007fffff40608f in open_verify (name=name@entry=0x7ffffffea460 "libsvml.so", fbp=fbp@entry=0x7ffffffea6b0, loader=loader@entry=0x271f570, whatcode=whatcode@entry=4, mode=mode@entry=-2147483648, found_other_class=found_other_class@entry=0x7ffffffea69f, free_name=false, fd=20) at dl-load.c:1971
#2 0x00007fffff4063d8 in open_path (name=name@entry=0x7ffff713af72 "libsvml.so", namelen=namelen@entry=11, mode=mode@entry=-2147483648, sps=0x271f918, realname=0x7ffffffea6a0, fbp=0x7ffffffea6b0, loader=0x271f570, whatcode=4, found_other_class=0x7ffffffea69f) at dl-load.c:2052
#3 0x00007fffff4093bd in _dl_map_object (loader=0x271f570, name=0x7ffff713af72 "libsvml.so", type=2, trace_mode=0, mode=<optimized out>, nsid=<optimized out>) at dl-load.c:2301
#4 0x00007fffff40e4e2 in openaux (a=a@entry=0x7ffffffeb270) at dl-deps.c:63
#5 0x00007ffffe1d71ef in __GI__dl_catch_exception (exception=0x7ffffffeb250, operate=0x7fffff40e4b0 <openaux>, args=0x7ffffffeb270) at dl-error-skeleton.c:196
#6 0x00007fffff40e85b in _dl_map_object_deps (map=map@entry=0x2723d60, preloads=preloads@entry=0x0, npreloads=npreloads@entry=0, trace_mode=trace_mode@entry=0, open_mode=open_mode@entry=-2147483648) at dl-deps.c:249
#7 0x00007fffff415109 in dl_open_worker (a=a@entry=0x7ffffffeb4c0) at dl-open.c:278
#8 0x00007ffffe1d71ef in __GI__dl_catch_exception (exception=0x7ffffffeb4a0, operate=0x7fffff414f80 <dl_open_worker>, args=0x7ffffffeb4c0) at dl-error-skeleton.c:196
#9 0x00007fffff41498a in _dl_open (file=0x27163f8 "core.node", mode=-2147483647, caller_dlopen=0x8fc024 <node::DLOpen(v8::FunctionCallbackInfo<v8::Value> const&)+324>, nsid=<optimized out>, argc=2, argv=<optimized out>, env=0x7ffffffedc90) at dl-open.c:605
#10 0x00007fffff1f0f96 in dlopen_doit (a=a@entry=0x7ffffffeb6f0) at dlopen.c:66
#11 0x00007ffffe1d71ef in __GI__dl_catch_exception (exception=exception@entry=0x7ffffffeb690, operate=0x7fffff1f0f40 <dlopen_doit>, args=0x7ffffffeb6f0) at dl-error-skeleton.c:196
#12 0x00007ffffe1d727f in __GI__dl_catch_error (objname=0x27179a0, errstring=0x27179a8, mallocedp=0x2717998, operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:215
#13 0x00007fffff1f1745 in _dlerror_run (operate=operate@entry=0x7fffff1f0f40 <dlopen_doit>, args=args@entry=0x7ffffffeb6f0) at dlerror.c:162
#14 0x00007fffff1f1051 in __dlopen (file=<optimized out>, mode=<optimized out>) at dlopen.c:87

Balint Reczey (rbalint)
Changed in glibc (Ubuntu Bionic):
status: New → Confirmed
tags: added: regression-update rls-bb-incoming
Changed in glibc (Ubuntu Cosmic):
status: Confirmed → Fix Released
Revision history for this message
Balint Reczey (rbalint) wrote :

@arsnyder16 Thank you for the report about the regression. I'll queue up the fix for the next update.

Revision history for this message
Andrew Snyder (arsnyder16) wrote :

Great! Thanks! Any tentative release date for the next version?

Revision history for this message
Balint Reczey (rbalint) wrote :

Cosmic did not receive the fix, but I've prepared the fix and will upload it in the next days. The release will still take more than a week due to the aging requirement and due to waiting for the test results.

description: updated
Changed in glibc (Ubuntu Cosmic):
status: Fix Released → Won't Fix
Balint Reczey (rbalint)
description: updated
Revision history for this message
Brian Murray (brian-murray) wrote : Please test proposed package

Hello hongtao.liu, or anyone else affected,

Accepted glibc into bionic-proposed. The package will build now and be available at https://launchpad.net/ubuntu/+source/glibc/2.27-3ubuntu1.4 in a few hours, and then in the -proposed repository.

Please help us by testing this new package. See https://wiki.ubuntu.com/Testing/EnableProposed for documentation on how to enable and use -proposed. Your feedback will aid us getting this update out to other Ubuntu users.

If this package fixes the bug for you, please add a comment to this bug, mentioning the version of the package you tested, what testing has been performed on the package and change the tag from verification-needed-bionic to verification-done-bionic. If it does not fix the bug for you, please add a comment stating that, and change the tag to verification-failed-bionic. In either case, without details of your testing we will not be able to proceed.

Further information regarding the verification process can be found at https://wiki.ubuntu.com/QATeam/PerformingSRUVerification . Thank you in advance for helping!

N.B. The updated package will be released to -updates after the bug(s) fixed by this package have been verified and the package has been in -proposed for a minimum of 7 days.

Changed in glibc (Ubuntu Bionic):
status: Confirmed → Fix Committed
tags: added: verification-needed verification-needed-bionic
Revision history for this message
Balint Reczey (rbalint) wrote :

ubuntu@bb:~/test$ dpkg -l libc6 | cat
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-===============-============-=================================
ii libc6:amd64 2.27-3ubuntu1.4 amd64 GNU C Library: Shared libraries
ubuntu@bb:~/test$ wget -q https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1821677/+attachment/5252188/+files/dl-big-note.tar.xz
ubuntu@bb:~/test$ tar -xf dl-big-note.tar.xz
ubuntu@bb:~/test$ cd dl-big-note/
ubuntu@bb:~/test/dl-big-note$ make
gcc -c -o dl-big-note-lib.o dl-big-note-lib.S
gcc -shared -o dl-big-note-lib.so dl-big-note-lib.o
gcc -o dl-big-note dl-big-note.c -ldl
ubuntu@bb:~/test/dl-big-note$ ./dl-big-note dl-big-note-lib.so

 all ok

tags: added: verification-done verification-done-bionic
removed: verification-needed verification-needed-bionic
Revision history for this message
Ubuntu SRU Bot (ubuntu-sru-bot) wrote : Autopkgtest regression report (glibc/2.27-3ubuntu1.4)

All autopkgtests for the newly accepted glibc (2.27-3ubuntu1.4) for bionic have finished running.
The following regressions have been reported in tests triggered by the package:

firefox/83.0+build2-0ubuntu0.18.04.2 (armhf)
linux-hwe-5.4/5.4.0-58.64~18.04.1 (armhf)
samtools/1.7-1 (s390x, arm64, armhf, amd64, i386)
linux-hwe-5.0/5.0.0-63.69 (armhf)
pacemaker/1.1.18-0ubuntu1.3 (armhf)
snapcraft/2.43.1+18.04.1 (arm64, armhf, amd64, i386)
openjdk-8/8u275-b01-0ubuntu1~18.04 (armhf)
php-imagick/3.4.3~rc2-2ubuntu4.1 (armhf, i386)
ruby2.5/2.5.1-1ubuntu1.7 (s390x, arm64, ppc64el, armhf, amd64, i386)

Please visit the excuses page listed below and investigate the failures, proceeding afterwards as per the StableReleaseUpdates policy regarding autopkgtest regressions [1].

https://people.canonical.com/~ubuntu-archive/proposed-migration/bionic/update_excuses.html#glibc

[1] https://wiki.ubuntu.com/StableReleaseUpdates#Autopkgtest_Regressions

Thank you!

Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package glibc - 2.27-3ubuntu1.4

---------------
glibc (2.27-3ubuntu1.4) bionic; urgency=medium

  [ Balint Reczey ]
  * tests: XFAIL new tst-support_descriptors on armel, too.
    The armhf build builds for armel, too, thus this fixes the armhf autopkgtest.
    (LP: #1895920)

  [ Adam Conrad ]
  * debian/patches/arm/unsubmitted-ldso-abi-check.diff: Fix rtld segv in dl_open()
    introduced via merge with upstream at 2.28 and when backporting upstream's
    2.27/master changes. (LP: #1821677)

 -- Balint Reczey <email address hidden> Mon, 07 Dec 2020 17:38:09 +0100

Changed in glibc (Ubuntu Bionic):
status: Fix Committed → Fix Released
Revision history for this message
Łukasz Zemczak (sil2100) wrote : Update Released

The verification of the Stable Release Update for glibc has completed successfully and the package is now being released to -updates. Subsequently, the Ubuntu Stable Release Updates Team is being unsubscribed and will not receive messages about this bug report. In the event that you encounter a regression using the package from -updates please report a new bug using ubuntu-bug and tag the bug report regression-update so we can easily find any regressions.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.