ldd reports incorrectly "not a dynamic executable" when the executable's loader is not present

Bug #1616609 reported by Ubfan
26
This bug affects 6 people
Affects Status Importance Assigned to Milestone
glibc (Ubuntu)
Confirmed
Undecided
Unassigned

Bug Description

system:Ubuntu 16.04.1 LTS
Linux leno 4.4.0-34-generic #53-Ubuntu SMP Wed Jul 27 16:06:39 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
package in use: libc-bin 2.23-0ubuntu3

The ldd script comes with wired in paths for the 64 bit and 32 bit loaders, but other architectures
are ignored. On a 64 bit Ubuntu installation, the 32 bit loader is not present by default, so
32 bit i386 dynamic executables are claimed to be "not a dynamic executable". This is simply wrong.
On a 64 bit Intel sytem, ldd is frequently used to identify missing necessary 32 bit libraries for
32 bit executables, so their packages may be installed.
It fails to do this unless ld-linux-x32.so.2 is present from the libc6-x32 package.

A minimum fix would be to change the present message to:
 "not a dynamic executable or possibly a missing loader, like ld-linux-x32.so.2 from the libc6-x32 package."

A better fix would be to use a program which can handle any architecture ELF file to report the needed libraries. Default Ubuntu installations do contain programs like file, readelf, and objdump which can successfully read these ELF files without loaders being present. The current ldd script even has a function, noelf, which might be better named "noloader" in which a fallback report may be issued to identify needed libraries. Using readelf in the "noloader" function, even different architectures may be correctly identified and their dependencies output. Below is a sample diff/patch for ldd which produces useful output for dynamic ELF files
regardless of architecture:

====snip====
97c97
< nonelf ()
---
> noloader ()
99,100c99,105
< # Maybe extra code for non-ELF binaries.
< return 1;
---
> # Extra code for non-native architecture ELF binaries.
> [ "$verbose" == "yes" ] && echo "No loader present for file $1, trying other options."
> readelf -h $1 1>/dev/null 2>&1
> ret=$?
> if [ $ret -eq 0 ]; then
> readelf -h $1 | egrep "Class|Type|Machine" && readelf -d $1 | grep NEEDED
> ret=$?
> fi
> return $ret
173,174c178,179
< # This can be a non-ELF binary or no binary at all.
< nonelf "$file" || {
---
> # This can be an ELF with no loader present, a non-ELF binary or no binary at all.
> noloader "$file" || {
====snip===

Comparison of original ldd with updated lddtest on three EFL files of different
architecture and a text file. The host machine does have the i386 loader
installed, but nothing for ARM.

The files:
$ file x y z txt
x: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.14, not stripped
y: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.0.0, not stripped
z: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=41cf4d8c7bbc4d37af0b7a55a7b0c48f8adfb2f5, not stripped
txt: ASCII text

The original ldd output:
$ ldd x y z txt
x:
    not a dynamic executable
y:
    linux-gate.so.1 => (0xf777d000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf76fe000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7548000)
    /lib/ld-linux.so.2 (0x56633000)
z:
    linux-vdso.so.1 => (0x00007fffc9dac000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4f63531000)
    /lib64/ld-linux-x86-64.so.2 (0x0000557d89ab7000)
txt:
    not a dynamic executable

The patched ldd output (with the 386 loader present):
$ ./lddtest x y z txt
x:
  Class: ELF32
  Type: EXEC (Executable file)
  Machine: ARM
 0x00000001 (NEEDED) Shared library: [libdl.so.2]
 0x00000001 (NEEDED) Shared library: [libc.so.6]
y:
    linux-gate.so.1 => (0xf774c000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xf76cd000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7517000)
    /lib/ld-linux.so.2 (0x56644000)
z:
    linux-vdso.so.1 => (0x00007ffe4388a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9550131000)
    /lib64/ld-linux-x86-64.so.2 (0x000056018c00d000)
txt:
    not a dynamic executable

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

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

Changed in glibc (Ubuntu):
status: New → Confirmed
Revision history for this message
Igor Z (igorz) wrote :
Ubfan (ubfan1)
description: updated
Revision history for this message
Ubfan (ubfan1) wrote :

Altered the patch in the description to explicitly save error status to handle recent bash changes.

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.