Torvalds: [hot take that almost no one else agrees with]
Torvalds: [hot take that almost no one else agrees with]
Considering the popularity of vendoring and/or static linking dependencies, I'm not sure where you're getting the "almost no one else agrees with" from.
glibc's hostility towards static linking is arguably a substantial part of why musl has attracted so much interest. Static linking support is explicitly stated as one of musl's core tenets [0].
One can also argue the popularity of containers has in part been due to glibc's dynamic linking requirements, and containers have become the bloated "modern" version of static linked binaries, bundling all the dependencies without eliding all the dynamic linking overhead.
Torvalds is definitely not alone in this particular opinion.
Shared libraries (at least with ELF) requires fixups, which involve COW and a considerable number of per-process pages. Compiling with -fPIC reserves one register, which isn't a problem unless you're on a register-starved CPU, which is all of them.
You can avoid load-time fixups via prelinking.
Really? None of the 64 bit ISAs seem particularly starved, especially not aarch64.
https://en.wikichip.org/wiki/arm_holdings/microarchitectures...
https://en.wikipedia.org/wiki/Scratchpad_memory
https://millcomputing.com/
How to Use 1000 Registers
https://caltechconf.library.caltech.edu/200/
1000 registers would be 10 bits. So they tried register windows.These are all good ideas but they get to compete. So far, I'm a huge AArch64 fan but I now see the purpose of RISC-V. I watched Chris Lattner's ASPLOS talk and it finally clicked.
https://www.youtube.com/watch?v=4HgShra-KnYMuch more on the x86 than on sane architectures, of course.
Vendoring is hugely popular for projects in year zero, because it makes it easier to ship. Until they learn that packaging specific versions of all your dependencies with your project implies taking on responsibility for backporting all security updates to that version of every dependency when upstream is only actively maintaining the latest version. Or you have a project riddled with known published security vulnerabilities, which is what most of those turn into.
Static vs dynamic is just do you want the code owners to be responsible or some centralized ops group to be responsible. Usually ops doesn’t have the insight to do a good job with deps, so it’s better to have dev do it, e.g. statically linked go binaries, statically linked C/c++, frozen package versions in Python, I think mvn has a similar capability, also version pinned base container images etc etc. hence the fact all the packaging systems add new versions and only rarely remove things as that breaks it all worse than a security hole.
As a dev person with a lot of ops experience I like static because I don’t want some janky dependency change to come into the execution path when I am not aware of making a change. On the other hand, people usually just freeze everything and then don’t worry about it, which is wrong. But your security team needs to review source and source deps not just deployed versions. So if code is still owned, the bad deps can be found and fixed either way.
I don’t see that dynamic linking makes a lot of difference here.
So you have two alternatives. One is that you make your software compatible with both version 1.3 and version 1.4, so it can be used on both Redhat and Debian with dynamic linking. This is a bit of work up front which is why everybody grumbles and looks for an alternative.
The other is that you vendor in version 1.3 so that you're using version 1.3 even on Debian. But now that library is your responsibility to patch instead of the distribution's. So instead of doing that work up front, you either maintain the library yourself on an ongoing basis (which may be more work than supporting two only slightly different library versions up front), or you neglect to do it and have a security vulnerability.
And vendoring in is pretty much equivalent to what happens with static linking.
My parent had suggested that dynamic linking is some great solution, and I don't see it's that great.
Why would that be true in general? It would only be the case if the upstream version contains some feature you need that isn't present in the version packaged by the distribution, and then you would only need to do it until the next version of the distribution packages the newer library version.
> and if the distribution provides security updates past the upstream date, this means that I need to use that exact distribution to benefit.
Or support the multiple versions of the library, which for non-ridiculous libraries is often no more than refraining from using the features not present in the older versions.
> Why would that be true in general?
Because I want to write software that works on various Unices, not just one Linux distribution. So it seems safer to rely on software that my users (the people who install the software I wrote) will be able to install from source, if necessary.
If I were to require whatever version Debian had at the moment, then I'd leave Fedora, Arch, OpenBSD, FreeBSD, Illumos aficionados in the lurch.
Detect a new version? Update your local copy, run your CI, if it passes, you can automatically merge. Or you could ask for someone of your team to review the changes, knowing your tests passed. And if it doesn't, you can warn your team, who can then either fix the build manually (hopefully a small incremental change) or open a bug report to the library.
The point is to do that continuously, so that the deltas are smaller and easier to handle. I do that with some pretty critical libraries at work and it's mostly fine, takes a few minutes usually to approve changes every week. Doing an upgrade after 6 months+? That'd require a long rollout.
You use a library, you've already taken on responsibility for it. You're application has bugs due to bugs in a library, you're users aren't going to accept "we reported it to the library and they said it wasn't important" as the resolution.
But having to fix it yourself when the library maintainers fail once is a far cry from having to backport every security update in every library yourself even if the library maintainers are properly doing it for a newer version than you're using.
The problem is that doing the backporting is typically more work than updating your software to use the newer version of the library, but not maintaining the library version you use at all is invisible in the way that security vulnerabilities are until somebody exploits them.
I personally don't like to vendor as it bloats the revision control system, but as far as dealing with bugs in the dependencies it doesn't really make a difference.
In the first case, using a version lock with dynamic linking, the maintainer of the library package is the one paying attention to and shipping patches for the library. And if the version of the library you're using stops being supported, your software breaks and you have to fix it immediately.
That's the thing vendoring "makes easier" -- you're not dependent on the third party to maintain that library version. Except that now it's on you to do it, and the breakage that would have told you that the version you're still using may no longer be secure is now absent. So the developer has to pay more attention. Which they regularly do not.
Anothre reason is that glibc is equally bad for dynamic linking. Often a binary compiled on recent glibc doesn't work with older glibc. It is certainly possible but quite challenging to compile portable executables on Linux.
These people are propagandizing the bogus security argument that static linking is bad practice.
Take the red pill: statically linked executables are actually good practice.
Aren't most of the people working on distros doing it for free.
Optimizing for the unlikely scenario is not a worthy tradeoff. Focusing on shared libraries can indirectly lead to less security overall, because people run outdated software, because of dependency hell leading people to defer upgrades.
Here, I fixed it for you!