#787227 ld-linux.so fails to expand relative RPATH when /proc is not mounted

Package:
libc6
Source:
glibc
Description:
GNU C Library: Shared libraries
Submitter:
Joey Hess
Date:
2021-12-10 22:54:04 UTC
Severity:
wishlist
#787227#5
Date:
2015-05-30 01:56:55 UTC
From:
To:
root@honeybee:/# ghc
/usr/lib/ghc/bin/ghc: error while loading shared libraries: libHShaskeline-0.7.1.2-ghc7.8.4.so: cannot open shared object file: No such file or directory

root@honeybee:/# ls -l /usr/lib/ghc/haskeline-0.7.1.2/libHShaskeline-0.7.1.2-ghc7.8.4.so
-rw-r--r-- 1 root root 2105712 May 25 20:47 /usr/lib/ghc/haskeline-0.7.1.2/libHShaskeline-0.7.1.2-ghc7.8.4.so

The problem isn't unique to this one .so file:

root@honeybee:/# hsc2hs
/usr/lib/ghc/bin/hsc2hs: error while loading shared libraries: libHSprocess-1.2.0.0-ghc7.8.4.so: cannot open shared object file: No such file or directory
root@honeybee:/# ldd /usr/lib/ghc/bin/hsc2hs | grep libHSprocess
	libHSprocess-1.2.0.0-ghc7.8.4.so => /usr/lib/ghc/bin/../process-1.2.0.0/libHSprocess-1.2.0.0-ghc7.8.4.so (0xb6d9d000)
root@honeybee:/# ls -l /usr/lib/ghc/process-1.2.0.0/libHSprocess-1.2.0.0-ghc7.8.4.so
-rw-r--r-- 1 root root 156452 May 25 20:47 /usr/lib/ghc/process-1.2.0.0/libHSprocess-1.2.0.0-ghc7.8.4.so

(Strange that ldd is able to resolve the paths to the libraries
when ld-linux.so cannot..)

LD_DEBUG=all hsc2hs sheds some light on the problem.
Comparing with the output on amd64 and armhf, it seems that the linker
is seeing a RUNPATH that has "tls/v7l/neon/vfp" in it, instead of
a RUNPATH that gives the directories where the haskell libraries are.

So, maybe something in the armel toolchain is overwriting the RUNPATH?

Horrible workaround: Make a ./tls/v7l/neon/vfp/ directory, and copy all the
libraries from ghc into it. :/

root@honeybee:/tmp# cp $(dpkg -L ghc |grep \.so) ./tls/v7l/neon/vfp/
root@honeybee:/tmp# ghc -V
The Glorious Glasgow Haskell Compilation System, version 7.8.4



armhf LD_DEBUG=all excerpt:

      4088:      search path=/usr/lib/ghc/bin/../process-1.2.0.0:/usr/lib/ghc/bin/../directory-1.2.1.0:/usr/lib/ghc/bin/../unix-2.7.0.1:/usr/lib/ghc/bin/../time-1.4.2:/usr/lib/ghc/bin/../old-locale-1.0.0.6:/usr/lib/ghc/bin/../filepath-1.3.0.2:/usr/lib/ghc/bin/../containers-0.5.5.1:/usr/lib/ghc/bin/../bytestring-0.10.4.0:/usr/lib/ghc/bin/../deepseq-1.3.0.2:/usr/lib/ghc/bin/../array-0.5.0.0:/usr/lib/ghc/bin/../base-4.7.0.2:/usr/lib/ghc/bin/../integer-gmp-0.5.1.0:/usr/lib/ghc/bin/../ghc-prim-0.3.1.0:/usr/lib/ghc/bin/../rts-1.0               (RUNPATH from file /usr/lib/ghc/bin/hsc2hs)

armel LF_DEBUG=all complete output for resolving the libHSprocess lib:

      3791:	file=libHSprocess-1.2.0.0-ghc7.8.4.so [0];  needed by /usr/lib/ghc/bin/hsc2hs [0]
      3791:	find library=libHSprocess-1.2.0.0-ghc7.8.4.so [0]; searching
      3791:	 search path=tls/v7l/neon/vfp:tls/v7l/neon:tls/v7l/vfp:tls/v7l:tls/neon/vfp:tls/neon:tls/vfp:tls:v7l/neon/vfp:v7l/neon:v7l/vfp:v7l:neon/vfp:neon:vfp:		(RUNPATH from file /usr/lib/ghc/bin/hsc2hs)
      3791:	  trying file=tls/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=tls/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	 search cache=/etc/ld.so.cache
      3791:	 search path=/lib/arm-linux-gnueabi/tls/v7l/neon/vfp:/lib/arm-linux-gnueabi/tls/v7l/neon:/lib/arm-linux-gnueabi/tls/v7l/vfp:/lib/arm-linux-gnueabi/tls/v7l:/lib/arm-linux-gnueabi/tls/neon/vfp:/lib/arm-linux-gnueabi/tls/neon:/lib/arm-linux-gnueabi/tls/vfp:/lib/arm-linux-gnueabi/tls:/lib/arm-linux-gnueabi/v7l/neon/vfp:/lib/arm-linux-gnueabi/v7l/neon:/lib/arm-linux-gnueabi/v7l/vfp:/lib/arm-linux-gnueabi/v7l:/lib/arm-linux-gnueabi/neon/vfp:/lib/arm-linux-gnueabi/neon:/lib/arm-linux-gnueabi/vfp:/lib/arm-linux-gnueabi:/usr/lib/arm-linux-gnueabi/tls/v7l/neon/vfp:/usr/lib/arm-linux-gnueabi/tls/v7l/neon:/usr/lib/arm-linux-gnueabi/tls/v7l/vfp:/usr/lib/arm-linux-gnueabi/tls/v7l:/usr/lib/arm-linux-gnueabi/tls/neon/vfp:/usr/lib/arm-linux-gnueabi/tls/neon:/usr/lib/arm-linux-gnueabi/tls/vfp:/usr/lib/arm-linux-gnueabi/tls:/usr/lib/arm-linux-gnueabi/v7l/neon/vfp:/usr/lib/arm-linux-gnueabi/v7l/neon:/usr/lib/arm-linux-gnueabi/v7l/vfp:/usr/lib/arm-linux-gnueabi/v7l:/usr/lib/arm-linux-gnueabi/neon/vfp:/usr/lib/arm-linux-gnueabi/neon:/usr/lib/arm-linux-gnueabi/vfp:/usr/lib/arm-linux-gnueabi:/lib/tls/v7l/neon/vfp:/lib/tls/v7l/neon:/lib/tls/v7l/vfp:/lib/tls/v7l:/lib/tls/neon/vfp:/lib/tls/neon:/lib/tls/vfp:/lib/tls:/lib/v7l/neon/vfp:/lib/v7l/neon:/lib/v7l/vfp:/lib/v7l:/lib/neon/vfp:/lib/neon:/lib/vfp:/lib:/usr/lib/tls/v7l/neon/vfp:/usr/lib/tls/v7l/neon:/usr/lib/tls/v7l/vfp:/usr/lib/tls/v7l:/usr/lib/tls/neon/vfp:/usr/lib/tls/neon:/usr/lib/tls/vfp:/usr/lib/tls:/usr/lib/v7l/neon/vfp:/usr/lib/v7l/neon:/usr/lib/v7l/vfp:/usr/lib/v7l:/usr/lib/neon/vfp:/usr/lib/neon:/usr/lib/vfp:/usr/lib	(system search path)
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/tls/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/arm-linux-gnueabi/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/tls/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/arm-linux-gnueabi/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/tls/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/lib/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/tls/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/v7l/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/v7l/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/v7l/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/v7l/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/neon/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/neon/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/vfp/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:	  trying file=/usr/lib/libHSprocess-1.2.0.0-ghc7.8.4.so
      3791:
/usr/lib/ghc/bin/hsc2hs: error while loading shared libraries: libHSprocess-1.2.0.0-ghc7.8.4.so: cannot open shared object file: No such file or directory

#787227#10
Date:
2015-05-30 02:05:06 UTC
From:
To:
Note that this bug is likely a security hole; /usr/bin/ghc loading .so
files relative to the CWD could be exploted.

When ghc's postinst runs ghc-pkg, it seems that dpkg does something that
prevents those relative paths being used (possibly just a chdir, didn't
check). So, it's at least not trivially exploitable by getting root to
install ghc when root is in /tmp.

#787227#15
Date:
2015-05-30 02:14:01 UTC
From:
To:
FWIW, I have seen this on 2 machins:

* Bannana pi, running bannanian with a Debian armel chroot
* Cubietruck, running an image from https://romanrm.net/a10/debian with
  a Debian armel chroot

In both cases, the kernel and boot system are armhf. I don't know if
this nonstandard configuration has something to do with it.

#787227#20
Date:
2015-05-30 08:34:14 UTC
From:
To:
Hi Joey,

Are you sure that /proc is mounted in that chroot? Maybe this is a
duplicate of #773768?

Since this keeps coming up, I suggest:

severity -1 wishlist
reassign -1 libc6
retitle -1 bad error message from ld-linux when /proc is unavailable
affects -1 + ghc

Helmut

#787227#25
Date:
2015-05-30 14:00:11 UTC
From:
To:
Helmut Grohne wrote:

Totally is a dup of that, thanks!

In light of the possible exploitability of this misconfiguration as a
security hole, it seems that ghc should be fixed to not look for
libraries in relative paths in this case, as well as printing a more
useful error message..

#787227#30
Date:
2015-05-30 14:04:29 UTC
From:
To:
Hi,

Am Samstag, den 30.05.2015, 10:00 -0400 schrieb Joey Hess:

I don’t think ghc even has the chance to do something else here, this is
the linker failing, isn’t it?

Greetings,
Joachim

#787227#35
Date:
2015-05-30 15:54:26 UTC
From:
To:
Joachim Breitner wrote:

Sorry, I meant the linker should be fixed, not ghc.

#787227#40
Date:
2015-05-30 16:56:03 UTC
From:
To:
When /proc is not mounted, a relative RPATH causes ld-linux.so to fall
back to using the working directory as the base directory for RPATH
resolution instead of using the (unknown) location of the executed
binary. This issue is hard to diagnose, because the error message does
not make it clear that fallback code is in use due to readlink
/proc/self/exe failing. Furthermore, it may pose a security risk by
loading libraries from unintended locations.

Let's codify that in the bts.

Steps to reproduce (for glibc maintainers):

Create an unstable chroot. Install ghc. Do not mount /proc in that
chroot. Execute /usr/bin/ghc. You shall see that it fails loading
libraries.

I assume that any binary with a relative RPATH is affected.

Helmut

#787227#57
Date:
2021-12-10 22:49:24 UTC
From:
To:
control: retitle -1 ld-linux.so fails to expand relative RPATH when /proc is not mounted
control: tag -1 - security

Hi,

The fact that it replaces $ORIGIN by the current directory when /proc is
not mounted is one part of the issue. It has already been tracked and
fixed in #884615.

This is the second part of the issue. The dynamic loader has no way to
find the location of the binary without a mounted /proc, that's why it
fails to find the GHC libraries.


Retitling / tagging the bug accordingly.

Regards,
Aurelien