News for hackers. Stuff that matters.
Re:Never run ldd on unknown executables by userbinator on Sunday July 23, 2023 @07:12PM (#36840938)
One particular case when a program won't be handled by ld-linux.so is when it has a different loader than the system's default specified in it's .interp ELF section. That's the whole idea in executing arbitrary code with ldd -- load the executable via a different loader that does not handle LD_TRACE_LOADED_OBJECTS environment variable but instead executes the program.

The way dynamic linking is done on UNIX-like systems has always seemed odd and a bit of an afterthought to me, and that explains why --- the actual loader in the OS kernel itself knows nearly nothing about dynamic linking. Instead it "redirects" execution to a loader (which is itself not that different from any other static binary) to do that.

Re:Never run ldd on unknown executables by throwawaylinux on Sunday July 23, 2023 @08:42PM (#36841633)
Well dynamic linking and most things in unix is an afterthought by definition because the first unix system did not have them.

That doesn't seem to be what you mean though in context, but I'm not sure what you do mean. You don't like it or don't think it was designed well because dynamic linking is done in userspace?

Re:Never run ldd on unknown executables by userbinator on Sunday July 23, 2023 @09:48PM (#36842106)
The fact that an executable needs to explicitly specify the "interpreter", instead of that being something under control of the OS loader, doesn't seem like a good way of doing it; and then the implementation of ldd discussed here just takes it in an even weirder direction.
Re:Never run ldd on unknown executables by dap on Sunday July 23, 2023 @10:47PM (#36842558)
What distinction are you making? Do you think it should be part of the kernel? I ask because ld.so (the runtime linker/loader) is part of the OS on many systems.
Re:Never run ldd on unknown executables by userbinator on Sunday July 23, 2023 @11:59PM (#36842986)
I mean not explicitly hardcoding the path to the interpreter inside every binary. If the dynamic linker is part of the OS, then surely the OS should already know where it is?
Re:Never run ldd on unknown executables by throwawaylinux on Monday July 24, 2023 @02:22AM (#36843754)
How much do you actually know about this? Have you read the ELF spec or written anything with libelf, hacked on a loader, a linker? Considered the actual problems with having this hard coded vs alternatives?

I ask because ELF and unix dynamic linking is a pretty well thought out set of specifications and processes and it's a huge body of work. It can certainly be criticized, but calling it an afterthought because of .interp doesn't seem very charitable.

There actually

Re:Never run ldd on unknown executables by duped on Monday July 24, 2023 @06:43AM (#36845700)
> If the dynamic linker is part of the OS, then surely the OS should already know where it is?

It's both part of the OS and the language's compiler tool chain the program was written in. For the vast majority of Linux executables that's glibc and the ld-linux.so that glibc ships.

And you don't need to hard code the path inside your executable. Static PIE objects for example are dynamic elf objects without an interpreter header. The system loader is capable of launching them just fine.

Re:Never run ldd on unknown executables by dap on Monday July 24, 2023 @02:34PM (#36852412)
I’m still not sure what principle you’ve got that’s being violated here? Given that one has chosen to implement part of the runtime linker/loader in userland, what’s wrong with fitting that into a more generic facility (supporting interpreters at arbitrary paths) and putting this specific implementation into a committed path?
Re:Never run ldd on unknown executables by throwawaylinux on Sunday July 23, 2023 @11:29PM (#36842797)
> The fact that an executable needs to explicitly specify the "interpreter", instead of that being something under control of the OS loader, doesn't seem like a good way of doing it;

The OS loader does control the permissions of what can be read and executed. And the user can execute a file. Why would it be better if you had to execute the loader explicitly to run a program? The same security problem would apply if you convinced somebody else to execute your malicious code. Seems like pretty harmless syntactic convenience.

The issue of ldd executing the program I guess is a thing that could be tightened to avoid foot shooting. Lots of unix programs traditionally were happy to give you lots of rope though.

Re:Never run ldd on unknown executables by cryptonector on Sunday July 23, 2023 @11:18PM (#36842754)
It fits perfectly in the Unix philosophy.
Re:Never run ldd on unknown executables by immibis on Monday July 24, 2023 @02:21AM (#36843740)
Sucky working code is better than code that doesn't exist, yes.

But isn't it silly that every Linux system needs to place this exact file at this exact path or else no program for another system will possibly be able to run on it?

Re:Never run ldd on unknown executables by jclulow on Monday July 24, 2023 @06:16AM (#36845450)
The name of the file is just part of the committed interface that the binary consumes. You could just as well suggest it's silly that every Linux system needs to agree on the behaviour of each system call number, or no program for another system will possibly be able to run on it.
Re:Never run ldd on unknown executables by cryptonector on Monday July 24, 2023 @02:45PM (#36852561)
"But isn't it silly that every Linux system needs a kernel and an initrd image or else it won't boot?"
Re:Never run ldd on unknown executables by pjmlp on Monday July 24, 2023 @03:28AM (#36844184)
Translation, worse is better philosophy.
Re:Never run ldd on unknown executables by anthk on Monday July 24, 2023 @08:19AM (#36846739)
9front does it better. No dynamic linking. At all.
Re:Never run ldd on unknown executables by cryptonector on Monday July 24, 2023 @01:09PM (#36851164)
User-land code can always add dynamic linking.
Re:Never run ldd on unknown executables by cryptonector on Monday July 24, 2023 @01:10PM (#36851174)
Not really. Would you rather that the dynamic linker-loader be part of the kernel? Do you think that the kernel can somehow prohibit user-land dynamic linking?
Re:Never run ldd on unknown executables by pjmlp on Tuesday July 25, 2023 @02:09AM (#36858563)
I would rather have it as Windows and AIX do, or even mainframes, or by gone systems of similar age like Xerox PARC or ETHZ ones, yes they are in the kernel.

In any case, modern security considerations have already shown that dynamic loading of foreign code into process memory isn't that much of a good idea after all, unless there are hardware restrictions regarding performace and memory use.

Re:Never run ldd on unknown executables by cryptonector on Tuesday July 25, 2023 @04:14PM (#36868680)
Well, I don't want dynamic linking and loading of user code to be done in the kernel -- that only increases the attack surface on the kernel.

> In any case, modern security considerations have already shown that dynamic loading of foreign code into process memory isn't that much of a good idea after all, [...]

As with many things it all depends on best practices and how you use the technology. Dynamic linking can be a big performance win. It can also be a performance loss. Dynamic linking can also be a big win in terms of code size, which even today is a good thing to have because container images can get bloated and you can need to have lots and lots of them, and it all adds up. None of that means you should be willing to dlopen() untrusted code, say.

And again, you can always implement your own dynamic linking and loading regardless of what such facilities (if any) the host OS provides.

Re:Never run ldd on unknown executables by cryptonector on Sunday July 23, 2023 @11:17PM (#36842750)
> The way dynamic linking is done on UNIX-like systems has always seemed odd and a bit of an afterthought to me, and that explains why --- the actual loader in the OS kernel itself knows nearly nothing about dynamic linking. Instead it "redirects" execution to a loader (which is itself not that different from any other static binary) to do that.

This makes it much easier to evolve the system because kernel-land programming is harder than user-land programming. The trade-off is that the user-land run-time loader has its own bootstrapping complexity to deal with.

Re:Never run ldd on unknown executables by userbinator on Monday July 24, 2023 @12:02AM (#36843008)
On Windows, the loader for usermode runs in usermode too; but every executable, by design, doesn't get to choose what to use for its loader.
Re:Never run ldd on unknown executables by cryptonector on Monday July 24, 2023 @12:40AM (#36843170)
> but every executable, by design, doesn't get to choose what to use for its loader.

Sure it does: it can load whatever it wants however it wants once main() gets to run.

Re:Never run ldd on unknown executables by mananaysiempre on Monday July 24, 2023 @11:21AM (#36849453)
I don’t know, I don’t hate the ELF interpreter bit; I actually don’t see why we need to have an ELF parser in the kernel at all—or rather I do, but the answer is likely “setuid”, which, bleh.

The emulating static linking semantics badly bit, though, I do hate, because it just seems so unnecessary and self-inflicted. The entirety of the symbol versioning mess could be reduced to build-time symbol aliases if only we agreed to bind symbols to imported dynamic libraries at build time and not at runtime. (MacOS’s “two-level namespaces” are a hack that tries to retrofit the sane behaviour on top of that, but of course it can’t free you from the underlying mess completely.)

And if we are comparing Unix and its descendants with Windows, isn’t it the case that dynamic linking is, in fact, an afterthought? Windows has had dynamic linking since literally 1.0, because without that you simply can’t fit multiple graphical apps into memory on the kind of machine it was supposed to target. I’d say that early 16-bit Windows essentially is a fancy dynamic linker tied to an overlay manager, plus a cooperative actor/object-like thing, and only then some graphics and input routines on top of all that. At least as far as the application programmer’s mental model is concerned.

Whereas Unix got dynamic linking well into the workstation era, and I remember somebody saying it was an attempt to reduce the memory overhead of Xlib; the classic Unix answer to runtime extensibility would be to spawn a separate process.