TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

“Static Linking Considered Harmful” Considered Harmful

155 pointsby yagizdegirmenciover 3 years ago

26 comments

themulticasterover 3 years ago
&gt; Second, ldd, the dynamic linker, can be manipulated into executing arbitrary code.<p>ldd is <i>not</i> the dynamic linker, it&#x27;s only a tool to debug the process of dynamic linking. The dynamic linker is ld-linux.so (exact name depends on glibc version, architecture, etc.)<p>Also, I think the linked article [1] about the security of ldd is somewhat useless. The ldd(1) manpage [2] is very explicit about the security of ldd and tells you not to run ldd on untrusted executables:<p>&gt; [...] Thus, you should <i>never</i> employ ldd on an untrusted executable, since this may result in the execution of arbitrary code.<p>It&#x27;s a little amusing how the linked blog post explains how to create a malicious executable that runs arbitrary code when inspected with ldd, noting that &quot;I researched this subject thoroughly and found that it&#x27;s almost completely undocumented. I have no idea how this could have gone unnoticed for such a long time.&quot; and concluding with &quot;Never run ldd on unknown executables!&quot; - all while the manpage literally mentions that precise known limitation in the third paragraph!<p>To be fair, you could argue that this limitation is not widely known and people should be made aware of the risks of ldd, but on the other hand you can hardly criticize ldd when its manpage is that explicit about the issue.<p>[1] <a href="https:&#x2F;&#x2F;catonmat.net&#x2F;ldd-arbitrary-code-execution" rel="nofollow">https:&#x2F;&#x2F;catonmat.net&#x2F;ldd-arbitrary-code-execution</a><p>[2] <a href="https:&#x2F;&#x2F;www.man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;ldd.1.html" rel="nofollow">https:&#x2F;&#x2F;www.man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;ldd.1.html</a>
评论 #28738249 未加载
评论 #28738190 未加载
评论 #28740630 未加载
risover 3 years ago
I eagerly await some concrete implementations of these new ideas.<p>In the meantime I&#x27;m waiting for the first <i>big</i> vulnerability in a widely used golang or rust library to see if downstream projects pinning it <i>also</i> release CVEs as they should (which would probably DDoS the CVE system from the resulting avalanche) <i>or</i> they quietly bump it and move on (in which case their users won&#x27;t get the nudge to upgrade). This is where someone says &quot;well you should just always be running the latest version of everything&quot;, which is of course infeasible on a real life system with thousands of installed packages.<p>And it&#x27;s not that I don&#x27;t completely sympathize or understand the advantages of static linking from a developer&#x27;s point of view - you don&#x27;t have to sell it to me there.
评论 #28737016 未加载
评论 #28736591 未加载
评论 #28737874 未加载
评论 #28737554 未加载
评论 #28736573 未加载
评论 #28736652 未加载
评论 #28737671 未加载
评论 #28738708 未加载
dhsysusbsjsiover 3 years ago
Personal end user perspective: troubleshooting dylib errors is the most common cause of wanting to throw the computer out the window and quit programming.
评论 #28737342 未加载
评论 #28738819 未加载
cesarbover 3 years ago
The first section, on security fixes (&quot;[...] you only need to update a shared library to apply security fixes to all executables that rely on that library&quot;), starts talking about security fixes but then suddenly switches to talking about ABI and API breaks. But that sleight-of-hand hides the fact that many (perhaps even most) security fixes do <i>not</i> break the ABI or API; they are completely contained to the implementation (one obvious exception would be if the security issue was caused by bad API design, but even then often there are ways to fix it without breaking the ABI).
评论 #28737484 未加载
评论 #28737534 未加载
ChrisSDover 3 years ago
&gt; However, there is one big elephant in the room: right now, there are a lot of platforms that do not fully support static linking because you have to dynamically link libc or other system interfaces. The only one I know of that supports static linking is Linux.<p>&gt; The ironic thing is that operating systems only supported a stable syscall ABI, rather than requiring programs to dynamically link system libraries, they would have less problems with ABI breaks.<p>&gt; With a statically-linked binary, you can copy it to another machine with a Linux that supports all of the needed syscalls, and it will just run.<p>I think this is a misunderstanding. With Linux there is a stable interface at the kernel boundary. Other OSes have their stable interfaces in user space. The difference is mostly irrelevant in this context. In one case you dynamically call into the kernel, in another case you dynamically link a user space library. Either way the code you&#x27;re calling isn&#x27;t static but the interface is.
评论 #28737295 未加载
评论 #28736609 未加载
评论 #28737223 未加载
评论 #28736472 未加载
davidwfover 3 years ago
This is very situational, but I have recently been part of a project that does a lot of C server-side development and we have found that static linking our non-glibc dependencies has really improved our developer experience. Using ceedling&#x27;s dependency plugin[1] and producing a single &quot;statically&quot; linked library has made our C development much closer to using a language with a more modern package manager. Don&#x27;t get me wrong, if I was trying to distribute binaries to machines I didn&#x27;t control I&#x27;d definitely be willing to invest in the Linux packaging &quot;fun&quot;, but for a server-side application it&#x27;s been a good choice for our team overall.<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;ThrowTheSwitch&#x2F;Ceedling&#x2F;tree&#x2F;master&#x2F;plugins&#x2F;dependencies" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ThrowTheSwitch&#x2F;Ceedling&#x2F;tree&#x2F;master&#x2F;plugi...</a>
评论 #28737248 未加载
PaulDavisThe1stover 3 years ago
&gt; I don’t think Ulrich Drepper could have foreseen all of the problems with DLL Hell (though there were signs on Windows),<p>Drepper&#x27;s article is from 2006. &quot;DLL Hell&quot; was beyond fully understood at that point, certainly by Drepper and large numbers of other well informed programmers.
评论 #28737371 未加载
评论 #28740968 未加载
tinus_hnover 3 years ago
Considered harmful essays considered harmful:<p><a href="https:&#x2F;&#x2F;meyerweb.com&#x2F;eric&#x2F;comment&#x2F;chech.html" rel="nofollow">https:&#x2F;&#x2F;meyerweb.com&#x2F;eric&#x2F;comment&#x2F;chech.html</a>
评论 #28737279 未加载
评论 #28737243 未加载
flohofwoeover 3 years ago
Unfortunately not even Linux allows full static linking (as far as I&#x27;m aware at least) as soon as libraries like OpenGL are involved.<p>Dynamic linking with core system libraries which are guaranteed to exist(!) is fine though, for everything else dynamic linking mostly has downsides.<p>Also: it&#x27;s <i>only</i> Linux where this is an issue, because it&#x27;s nearly impossible to build small self-contained executables which run on another Linux machine, thanks to glibc&#x27;s versioning mess (at least there&#x27;s MUSL as an alternative to create portable command line tools).
评论 #28736614 未加载
评论 #28736751 未加载
评论 #28736585 未加载
评论 #28736666 未加载
rwmjover 3 years ago
I read this interesting article recently about all the security problems that static linking, bundling and pinning cause for Linux distributions:<p><a href="https:&#x2F;&#x2F;blogs.gentoo.org&#x2F;mgorny&#x2F;2021&#x2F;02&#x2F;19&#x2F;the-modern-packagers-security-nightmare&#x2F;" rel="nofollow">https:&#x2F;&#x2F;blogs.gentoo.org&#x2F;mgorny&#x2F;2021&#x2F;02&#x2F;19&#x2F;the-modern-packag...</a>
评论 #28737347 未加载
评论 #28737171 未加载
gnufxover 3 years ago
There are examples of the sort of reason I want dynamic linking under <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28734875" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28734875</a> and you also really want it for profiling&#x2F;tracing, and possibly debugging, e.g. in HPC with the MPI PMPI mechanism.<p>libabigail is one tool for checking that a library&#x27;s ELF versioning hasn&#x27;t lied about ABI compatibility when you&#x27;re building packages, for instance.<p>Unfortunately people typically don&#x27;t follow Drepper&#x27;s advice (as far I remember the article) on building shared libraries, particularly using symbol versioning a la glibc.
评论 #28737461 未加载
apiover 3 years ago
My personal view is that only standard core system libraries should be dynamically linked. Anything that is not totally ubiquitous should be static.<p>That seems to be the Go and Rust default approach, or close to it. Link libc and such, but build in more obscure things.<p>The idea of dynamically linking everything doesn’t scale. It asks too much of distribution maintainers and makes them the choke point for every little upgrade.
评论 #28737516 未加载
评论 #28737204 未加载
Jachover 3 years ago
I&#x27;d like to see solutions like SDL2&#x27;s become more widespread: <a href="https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;linux_gaming&#x2F;comments&#x2F;1upn39&#x2F;sdl2_adds_dynamic_api_magic_to_allow_updating_it&#x2F;" rel="nofollow">https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;linux_gaming&#x2F;comments&#x2F;1upn39&#x2F;sdl2_a...</a> At runtime, the first call into SDL sets up a jump table for all SDL functions afterwards. When SDL is statically linked, it uses those static functions by default, but it&#x27;s possible to specify an environmental variable pointing at an SDL dynamic lib, and the jump table will use those functions instead.
3npover 3 years ago
&quot;&quot;Static Linking Considered Harmful&quot; Considered Harmful&quot; Considered Harmful:<p>This is the blog version of Re: Re: Fwd: Re: in email and has to stop here.<p>See also <a href="https:&#x2F;&#x2F;meyerweb.com&#x2F;eric&#x2F;comment&#x2F;chech.html" rel="nofollow">https:&#x2F;&#x2F;meyerweb.com&#x2F;eric&#x2F;comment&#x2F;chech.html</a>
评论 #28737428 未加载
评论 #28737432 未加载
rasculover 3 years ago
According to Linus, &quot;Shared libraries are not a good thing in general&quot;.<p><a href="https:&#x2F;&#x2F;lore.kernel.org&#x2F;lkml&#x2F;CAHk-=whs8QZf3YnifdLv57+FhBi5_WeNTG1B-suOES=RcUSmQg@mail.gmail.com&#x2F;" rel="nofollow">https:&#x2F;&#x2F;lore.kernel.org&#x2F;lkml&#x2F;CAHk-=whs8QZf3YnifdLv57+FhBi5_W...</a>
评论 #28737399 未加载
0xbadcafebeeover 3 years ago
I wish I had three hours to waste on why almost all of these points are either innacurate or willfully misleading. But I don&#x27;t, so I&#x27;ll just point out the single biggest reason why static linking is harmful.<p>Encryption libraries.<p>If OpenSSL, or LibreSSL, or Go&#x27;s encryption modules, or <i>any gigantic encryption library</i> has a vulnerability, you basically have to recompile, distribute, and then have your users download, every single god damn networking program.<p>But it&#x27;s worse than that. Because everyone wants to ship a statically compiled Go app, nobody packages for the distros. So now every user needs to go track down where they downloaded each of their static Go apps, <i>safely</i> download the update, verify its checksum or signature via a 3rd party, and upgrade the app.<p>That is a logistical nightmare. Not only are apps going to remain vulnerable for way, way longer, more users will be compromised by phishing and other attacks because there&#x27;s no package manager to safely automate all these updates (distros sign and verify packages for you).<p>I&#x27;ve actually written a Shell quasi-package manager&#x2F;installer just for statically compiled apps (cliv) so in theory that problem could be somewhat solved... But nobody even knows about that program, so the manual update problem still stands.
评论 #28736824 未加载
评论 #28736774 未加载
评论 #28737215 未加载
评论 #28737681 未加载
lamontcgover 3 years ago
I sorta think that static linking needs to die, but dynamic linking also needs to be a lot better.<p>More of the choices that get made during autoconf needs to be made lazily at link time. That would make executables and dynamic libraries more like containers or lego blocks that could be rearranged without compilation. Which would fix a lot of issues that people hate about package managers and bloated distros along the way.
ghowardover 3 years ago
Author here. I don&#x27;t know why my own submission of this [1] didn&#x27;t catch and this one did. Oh well. XD<p>I&#x27;m open to answering questions, and I&#x27;ll be hanging in the thread.<p>[1]: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28728801" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28728801</a>
评论 #28739506 未加载
lggover 3 years ago
Every time I read one of these essays extolling the virtues of static linking it makes me pretty sad. Engineering is about trade offs, and sometimes it does make sense to statically link, but the fact that those trade offs are so lopsided on Linux has very little to do with dynamic linking vs static linking as generic concepts, and more to do with the fact that the design of ld.so is straight out of the 1990s and almost nothing has be done to either exploit the benefits dynamic linking brings, nor to mitigate the issues it causes.<p>On Darwin derived systems (macOS, iOS, tvOS, watchOS) we have invested heavily in dynamic linking over the last two decades. That includes features we use to improve binary compatibility (things like two level namespaces (aka Direct Binding in ELF) and umbrella frameworks), middleware distribution (through techniques like bundling resources with their dylibs into frameworks), and mitigate the security issues (through technologies like __DATA_CONST).<p>Meanwhile, we also substantially reduced the cost of dynamic linking through things like the dyld shared cache (which makes dynamic linking of most system frameworks almost free, and in practice it often reduces their startup cost to below the startup cost of statically linking them once you include the cost of rebasing for PIE), and mitigate much of the rest of the cost of dynamic linking through things like pre-calculated launch closures. It does not hurt that my team owns both the static and dynamic linkers. We have a tight design loop so that when we come up with ideas for how to change libraries to make the dynamic linker load them faster we have the ability to rapidly deploy those changes through the ecosystem.<p>As I explained in here[1] dynamic linking on macOS is way faster than on Linux because we do it completely differently, and because of that it is used way more pervasively on our systems (a typical command line binary loads 80-150 dylibs, a GUI app around 300-800 depending on which of our OS you are talking about). IOW, by mitigating the costs we drove up the adoption which amplifies the benefits.<p>And it is not like we have squeezed all the performance out of the dynamic linker that we can, not by a long shot. We have more ideas than we have time to pursue, as well as additional improvements to static linking. If you have any interest in either static or dynamic linking we&#x27;re looking for people to work on both[2].<p>[1]: <a href="https:&#x2F;&#x2F;www.realworldtech.com&#x2F;forum&#x2F;?threadid=197081&amp;curpostid=197486" rel="nofollow">https:&#x2F;&#x2F;www.realworldtech.com&#x2F;forum&#x2F;?threadid=197081&amp;curpost...</a><p>[2]: <a href="https:&#x2F;&#x2F;jobs.apple.com&#x2F;en-us&#x2F;details&#x2F;200235669&#x2F;systems-engineer-dyld" rel="nofollow">https:&#x2F;&#x2F;jobs.apple.com&#x2F;en-us&#x2F;details&#x2F;200235669&#x2F;systems-engin...</a><p>(edit: fixed link formatting)
评论 #28738031 未加载
arduinomancerover 3 years ago
It seems a pain point of static linking is that if a library changes you need to rebuild everyone<p>Maybe a stupid idea but has there ever been thought of distributing applications with source code included?<p>That way you could have a system that automatically rebuilds the application if a static library changes.<p>Meaning when a user sees “updating” it’s actually rebuilding the app underneath.
sharikousover 3 years ago
Correct me if I am wrong but OpenBSD introduced the constraint that syscalls must come from a specific section of memory, that assigned to their libc.<p>In a case like that static linking is not only unstable, as in Windows or macOS, but also impossible.<p>And since that has security benefits we will probably see it being migrated to other platforms in the near future.
Wowfunhappyover 3 years ago
Are there any Linux distros that actually distribute (most) software as (mostly) static binaries? Right now, the only way to do it seems to be compiling everything myself...
评论 #28736644 未加载
评论 #28736626 未加载
评论 #28736465 未加载
forrestthewoodsover 3 years ago
I care far more about about bundled vs unbundled than dynamic vs static.<p>I am passionately in-favor of bundled. Unbundled distribution is what has led to software being so outrageously impossible to execute that the only sane path to distribution is to create a bundled docker image. <a href="https:&#x2F;&#x2F;xkcd.com&#x2F;1987&#x2F;" rel="nofollow">https:&#x2F;&#x2F;xkcd.com&#x2F;1987&#x2F;</a>
mstover 3 years ago
&gt; Operating systems can statically map libraries.<p>I have &quot;fond&quot; memories of running perebaseall on cygwin that this sentence reminded me of.
osigurdsonover 3 years ago
I really dislike the tired re-use of the term &quot;considered harmful&quot;. A better title may be &quot;I don&#x27;t like dynamic linking - here&#x27;s why&quot;.
KronisLVover 3 years ago
Why are we still developing software like we used to 40 years ago?<p>Why not just import external dependencies into your project at a function&#x2F;class level rather than at a package one: if you only use FooPackage.BarClass and FooPackage.bazMethod(), you should be able to choose to make your project depend on just those two things, ideally in a completely transparent way by your IDE.<p>Then having to manage the full scope of packages and their versions becomes less relevant, because the IDE can check whether a new version has been released in the package manager of choice, check whether those two things have changed and if they have, then demand that the developer have a look at the code changes to refactor code if necessary, otherwise not requiring any action on their part. Furthermore, if you ever need to migrate to a different package or even rewrite the functionality itself, you could just look at the few signatures that you use, rather than having to remove the package entirely and see what breaks in your IDE. Why can&#x27;t we have itemized lists of everything that&#x27;s called and everything that we depend on, as opposed to the abstraction of entire packages?<p>Better yet, why even depend on binary blobs or hidden code (that&#x27;s ignored by your IDE) in the first place? Why not just download the source for every package that you use and upon updates be able to review the code changes to the package much like a regular Git diff?<p>Of course, this would probably require getting rid of reflection and other forms of dynamic code, which i fully support, since those have never been good for much in the first place and only destroy any hopes of determinism and full control flow analysis.<p>As for the possible counterargument of this being hard to do: it wouldn&#x27;t really be with more granular packages. Instead of trying to shove an ecosystem inside of a single package, why not split it into 10-20 bits of reusable code instead? Smaller packages, which would be easier to review and manage.<p>Context: i dislike how Spring and Spring Boot in Java force a huge ecosystem of fragile dependencies upon you, with their reflection which ensures that your apps will break at runtime, for example, when moving from Spring Boot 1.5 to 2.0. Furthermore, in the JS world, the node_modules folders are probably 10-1000x too large for what&#x27;s actually necessary to display a webpage with some interactive behaviour.<p>Disclaimer: i have no delusions about any of the above being technically feasible right now. Perhaps &quot;Why?&quot; would be a good question to ask. In my eyes, perhaps the industry is too set in its current ways and as long as we don&#x27;t have languages and entire ecosystems that approach established practices from a wildly different angle, no one can actually contest the decades of already built packages and tools.<p>On the bright side, WireGuard kind of displaced OpenVPN somewhat and there are numerous benefits to it being smaller, which is a good example of getting rid of bloated software. Furthermore, Nix may or may not do that to alternative approaches to package management, but its usage still remains really low.<p>In my eyes, the only long term solution is to be able to tell exactly what&#x27;s necessary for your code to build and work, and to test every dependency update that comes out against this automated process. Static dependencies but at the speed of updates of dynamic dependencies. Then you&#x27;d just have to wait for a day until the devs fix the newest regressions of a new dependency release before getting a new statically linked app, as opposed to using dynamic linking and finding that some dependency breaks your app as it happens in prod.
评论 #28737628 未加载
评论 #28737169 未加载
评论 #28737893 未加载
评论 #28736792 未加载