I'd like to provide an ld.so command as part of glibc.
Today, ld.so can be used to activate preloading, for example.
Compared to LD_PRELOAD, the difference is that it's specific to one
process, and won't be inherited by subprocesses—something is that
exactly what is needed.
Anyway, do you see any problems with providing /usr/bin/ld.so for use
by skilled end users?
Right, thanks for providing a concrete example. A (somewhat) portable version would look like this:
ld.so --preload '/usr/$LIB/libeatmydata.so.1.3.0' /bin/sl
Florian Weimer wrote:
I'd like to provide an ld.so command as part of glibc.
Will this happen in glibc upstream or just in Debian?
Today, ld.so can be used to activate preloading, for example.
Compared to LD_PRELOAD, the difference is that it's specific to one
process, and won't be inherited by subprocesses—something is that
exactly what is needed.
That appears to be activated like this:
/lib64/ld-linux-x86-64.so.2 --preload /usr/lib/x86_64-linux-gnu/libeatmydata.so.1.3.0 /bin/ls
Anyway, do you see any problems with providing /usr/bin/ld.so for use
by skilled end users?
It means more folks get exposed to ld.so features, which might mean
more support and feature requests for glibc upstream,. For example the
set of features provided by environment variables is different to the
set of features provided by command-line options.
On Fri, Dec 03, 2021 at 01:57:08PM +0100, Florian Weimer wrote:
Right, thanks for providing a concrete example. A (somewhat) portable
version would look like this:
ld.so --preload '/usr/$LIB/libeatmydata.so.1.3.0' /bin/sl
You mean
ld.so --preload libeatmydata.so.1.3.0 /bin/ls
?
On Fri, Dec 03, 2021 at 01:57:08PM +0100, Florian Weimer wrote:
Right, thanks for providing a concrete example. A (somewhat) portable version would look like this:
ld.so --preload '/usr/$LIB/libeatmydata.so.1.3.0' /bin/sl
You mean
ld.so --preload libeatmydata.so.1.3.0 /bin/ls
Having ld.so as a real command makes the name architecture-agnostic.
This discourages from hard-coding non-portable paths such as /lib64/ld-linux-x86-64.so.2 or even (the non-ABI-compliant) /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 in scripts that require
specific functionality offered by such an explicit loader invocation.
The initial implementation will be just a symbolic link. This means
that multi-arch support will be missing: the amd64 loader will not be
able to redirect execution to the s390x loader.
In principle, it should
be possible to find PT_INTERP with a generic ELF parser and redirect to
that, but that's vaporware at present. I don't know yet if it will be possible to implement this without some knowledge of Debian's multi-arch support in the loader.
If someone wants to upstream the multi-arch patches, that would be
great. glibc now accepts submissions under DCO, so copyright assignment should no longer be an obstacle.
No objects to /usr/bin/ld.so then?
* How does ld.so --preload *work*?
* Does it modify /bin/ls, so that all users running /bin/ls get the
preloaded library?
* Does it modify something in the user's home directory?
* How do you undo the effects ld.so --preload?
Just a random thought: If you have configured a restricted shell (e.g.
rbash) that only lets you execute commands in PATH, will this make it possible to bypass the restriction with "ld.so /tmp/some-random-binary"?
This is not necessary an argument to not do this, I'm just wondering what
the implications could be.
Some stupid questions that I couldn't answer by reading the man page
or doing a quick google search....
* How does ld.so --preload *work*?
* Does it modify /bin/ls, so that all users running /bin/ls get the
preloaded library?
* Does it modify something in the user's home directory?
* How do you undo the effects ld.so --preload?
On Thu, 02 Dec 2021 at 19:51:16 +0100, Florian Weimer wrote:
Having ld.so as a real command makes the name architecture-agnostic.
This discourages from hard-coding non-portable paths such as
/lib64/ld-linux-x86-64.so.2 or even (the non-ABI-compliant)
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 in scripts that require
specific functionality offered by such an explicit loader invocation.
This works up to a point, but because there is only one /usr/bin/ld.so,
it can only work for one architecture per machine, so saying it's architecture-agnostic is still a bit of a stretch.
In principle, it should
be possible to find PT_INTERP with a generic ELF parser and redirect to
that, but that's vaporware at present. I don't know yet if it will be
possible to implement this without some knowledge of Debian's multi-arch
support in the loader.
I believe Debian uses the interoperable (ABI-compliant) ELF interpreter
as listed on https://sourceware.org/glibc/wiki/ABIList for all
architectures - it certainly does for all *common* architectures (for
example our x86_64 executables use /lib64/ld-linux-x86-64.so.2, which is
a special exception to the rule that we don't usually use lib64).
I had naively believed that all distros do the same, but unfortunately
my work on the Steam Runtime has taught me otherwise: for example, Arch
Linux has a non-standard ELF interpreter /usr/lib/ld-linux-x86-64.so for executables that are built from the glibc source package (but uses the interoperable ELF interpreter for everything else),
and Exherbo consistently puts their dynamic linkers in /usr/x86_64-pc-linux-gnu/lib.
Does glibc automatically set up the interoperable ELF interpreter, or is
it something that distros' glibc maintainers have to "just know" if they
are using a non-default ${libdir}?
If someone wants to upstream the multi-arch patches, that would be
great. glibc now accepts submissions under DCO, so copyright assignment
should no longer be an obstacle.
(Please note that I am not a glibc maintainer and cannot speak for them.)
I think multiarch is mostly build-time configuration rather than patches.
The main thing needing patching is that we want ${LIB} to expand to lib/x86_64-linux-gnu instead of just x86_64-linux-gnu, so that the "/usr/${LIB}/libfoo.so.0" idiom works, but glibc would normally only take
the last component of the ${libdir}:
https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/any/local-ld-multiarch.diff
The freedesktop.org SDK used for Flatpak also uses Debian-style multiarch (but is not otherwise Debian-derived), and addresses that differently, in a way that might be more upstream-suitable:
https://gitlab.com/freedesktop-sdk/freedesktop-sdk/-/blob/master/patches/glibc/fix-dl-dst-lib.patch
On Thu, 02 Dec 2021 at 19:51:16 +0100, Florian Weimer wrote:
If someone wants to upstream the multi-arch patches, that would be
great.
I think multiarch is mostly build-time configuration rather than patches.
We would have to take the table out of dpkg-architecture and put it into upstream glibc (or gcc or binutils), otherwise you can't build a
multi-arch glibc on a non-Debian system.
In addition to get the right value for $LIB, it's also desirable to get
the default search paths right.
And there's also /usr/libexec/getconf to worry about.
* Theodore Y. Ts'o:
* How does ld.so --preload *work*?
The dynamic loader has an array of preloaded sonames, and it processes
them before loading the dependencies of the main program. This way, definitions in the preloaded objects preempt definitions in the shared objects.
* Does it modify /bin/ls, so that all users running /bin/ls get the preloaded library?
No, it's purely a run-time change.
We can add a generic ELF parser to that ld.so and use PT_INTERP, as I mentioned below. I think this is the way to go. Some care will be
needed to avoid endless loops, but that should be it.
From what was said, I expect that /usr/bin/ld.so is an ELF executable.It will likely be part of libc-bin. Do you confirm?
Hi Florian,
On Fri, Dec 03, 2021 at 06:29:33PM +0100, Florian Weimer wrote:
We can add a generic ELF parser to that ld.so and use PT_INTERP, as I
mentioned below. I think this is the way to go. Some care will be
needed to avoid endless loops, but that should be it.
Can I ask you to go into a bit more technical detail as to how this is supposed to work?
From what was said, I expect that /usr/bin/ld.so is an ELF executable.
It will likely be part of libc-bin. Do you confirm?
Since libc-bin is Multi-Arch: foreign. The new ld.so really must have an architecture-independent API. If it does not, it must not go there.
As far as I understand things, the typical use will be "ld.so
--preload somelib someprogram". Now consider an i386 ld.so, an amd64
somelib and an amd64 someprogram. Will that work with the generic ELF
parser?
At present, it does not seem to work:
$ /lib/ld-linux.so.2 --preload /usr/lib/x86_64-linux-gnu/libeatmydata.so /bin/true
/bin/true: error while loading shared libraries: /bin/true: wrong ELF class: ELFCLASS64
$
If that is what you will get from /usr/bin/ld.so, then it must not be
part of libc-bin or Multi-Arch: foreign must be dropped. The latter
likely is a non-option due to the amount of resulting breakage.
I'd like to provide an ld.so command as part of glibc. Today, ld.so can
be used to activate preloading, for example. Compared to LD_PRELOAD,
the difference is that it's specific to one process, and won't be
inherited by subprocesses—something is that exactly what is needed.
There is also some useful diagnostic output in --help,
--list-diagnostics.
Having ld.so as a real command makes the name architecture-agnostic.
This discourages from hard-coding non-portable paths such as /lib64/ld-linux-x86-64.so.2 or even (the non-ABI-compliant) /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 in scripts that require
specific functionality offered by such an explicit loader invocation.
I thought that commands with file extensions might be Policy violation. Policy actually talks about file extensions for programs installed in /usr/bin—but only for scripts. So it's technically okay. And today, there's already an ld.so manual page, although it's in section 8 and 1.
(I think /usr/bin is still appropriate because running ld.so does not
require special privileges.)
The initial implementation will be just a symbolic link. This means
that multi-arch support will be missing: the amd64 loader will not be
able to redirect execution to the s390x loader. In principle, it should
be possible to find PT_INTERP with a generic ELF parser and redirect to
that, but that's vaporware at present. I don't know yet if it will be possible to implement this without some knowledge of Debian's multi-arch support in the loader. Upstream doesn't have those features (we only
support /usr/lib vs /usr/lib64 and some minor variants of that), so integration might be lacking.
If someone wants to upstream the multi-arch patches, that would be
great. glibc now accepts submissions under DCO, so copyright assignment should no longer be an obstacle.
Anyway, do you see any problems with providing /usr/bin/ld.so for use by skilled end users?
Hi,
On 2021-12-02 19:51, Florian Weimer wrote:
I'd like to provide an ld.so command as part of glibc. Today, ld.so can
be used to activate preloading, for example. Compared to LD_PRELOAD,
the difference is that it's specific to one process, and won't be
inherited by subprocesses—something is that exactly what is needed.
There is also some useful diagnostic output in --help,
--list-diagnostics.
This sounds a good idea, I guess for instance that in the future the ldd feature could be implemented as an option.
However before exposing directly to user, there might be some work need
to improve error reporting. For instance running the dynamic linker
against a static library like ldconfig just causes a segmentation fault
(at least in 2.34, I haven't tried in HEAD). I haven't tried either
binaries from other libc, but we should make sure that an error is
correctly reported if users try that. At least a binary from a different architecture correctly reports the error.
Having ld.so as a real command makes the name architecture-agnostic.
This discourages from hard-coding non-portable paths such as
/lib64/ld-linux-x86-64.so.2 or even (the non-ABI-compliant)
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 in scripts that require
specific functionality offered by such an explicit loader invocation.
Do you actually have example of usage of the non-ABI-compliant dynamic
loader in Debian? Independently of the current discussion, this should probably be fixed.
I thought that commands with file extensions might be Policy violation.
Policy actually talks about file extensions for programs installed in
/usr/bin—but only for scripts. So it's technically okay. And today,
there's already an ld.so manual page, although it's in section 8 and 1.
(I think /usr/bin is still appropriate because running ld.so does not
require special privileges.)
The initial implementation will be just a symbolic link. This means
that multi-arch support will be missing: the amd64 loader will not be
able to redirect execution to the s390x loader. In principle, it should
be possible to find PT_INTERP with a generic ELF parser and redirect to
that, but that's vaporware at present. I don't know yet if it will be
possible to implement this without some knowledge of Debian's multi-arch
support in the loader. Upstream doesn't have those features (we only
support /usr/lib vs /usr/lib64 and some minor variants of that), so
integration might be lacking.
A simple symlink would work as a start, however it means creating a
new non-multiarch package. If we want that feature to be available to
all system, we need a way to ensure this package is automatically
installed.
What is the plan about supporting /usr/lib vs /usr/lib64? If upstream go
the wrapper way, there might not be a lot of differences with what is
needed to support multiarch. From what I understand a wrapper would need
to have a basic understanding of the arguments passed to ld.so to find
the binary that needs to be loaded. Looking at PT_INTERP is one way to
go, however we should define what would be the behaviour for non GNU
libc dynamic loader.
If someone wants to upstream the multi-arch patches, that would be
great. glibc now accepts submissions under DCO, so copyright assignment
should no longer be an obstacle.
I don't think copyright assignment is really the issue there. We have
two patches left that haven't been merged upstream, one from Steve
Langasek and one from me. The problem is more that there is work to add proper upstream support for multiarch, I guess the idea would be to use
a configure option. On the Debian side multiarch support is basically
done by defining libdir, slibdir and rtlldir in the configparms file,
plus two patches:
- https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/any/local-ldconfig-multiarch.diff
This patch basically changes the way ldconfig gets its standard search
paths. I guess this is something that could be upstream, probably with
some changes but I haven't recently look at it in details.
- https://salsa.debian.org/glibc-team/glibc/-/blob/sid/debian/patches/any/local-ld-multiarch.diff
This patch does actually two things. The first part makes sure that
ld.so still looks in the non-multiarch paths. This doesn't look
upstreamable in the way its done. The second patch just change the way
the initial '/' is dropped from $(slibdir) so that it works for two
level paths. This part looks upstreamable.
It is as architecture-independent as ldconfig or getconf. Perhaps a bit
more so than getconf.
Even if /bin/true is an i386 program, assuming that libeatmydata1:i386
is installed. Whether ld.so is built for i386 or amd64 will not matter.
With the patch I've posted, you'll get the ELFCLASS64 error. But I have
some ideas how to fix that eventually. Is this sufficient for now?
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 296 |
Nodes: | 16 (2 / 14) |
Uptime: | 84:08:41 |
Calls: | 6,658 |
Calls today: | 4 |
Files: | 12,203 |
Messages: | 5,333,601 |
Posted today: | 1 |