Hacker News new | past | comments | ask | show | jobs | submit login
Deciding to rewrite getaddrinfo in rust (dkhenry.com)
105 points by azth on Feb 23, 2016 | hide | past | web | favorite | 120 comments



How security sensitive is getaddrinfo? The recent vulnerability was actually in glibc's DNS client library, libresolv, not getaddrinfo itself (but it was triggered when using getaddrinfo). Therefore, I think that rewriting libresolv in Rust (and possibly the DNS NSS module) would be more fruitful than trying to rewrite getaddrinfo. It would also be easier - libresolv is in its own .so so you could swap the entire thing out, rather than having to patch glibc or use LD_PRELOAD hacks. (I actually started working on this a few days ago :-)


Is ldns vulnerable? Did OpenBSD drop BIND and libresolv in favor of ldns and nsd, unbound, drill? Might be an interim solution.


Yes, OpenBSD dropped BIND, as did FreeBSD.


Really hope you post this!


glibc in total is about 460.000 lines of C. If we're planning on reimplementing it as a whole that's going to be quite an undertaking. Musl is an alternative libc that's only about 60.000 lines of C. I don't know exactly why libc is that much larger, as musl also aims to be a complete and POSIX compatible libc.

Its getaddrinfo is considerably smaller at 90 lines, and there's no goto's, it looks comfortably readable at a glance. Maybe a nice blog post would be to compare both implementations to find out if there's a concrete difference in functionality and code quality.

edit: I should've looked at the 2nd Google result, it's a complete comparison of a bunch of libc's:

http://www.etalabs.net/compare_libcs.html


One of the things I'm noticing in looking through the musl code in comparison to FreeBSD's libc (yes, it's not glibc, but it's also a full-featured libc) is that musl makes a lot more assumptions about the base system and the results it gets back. Looking through getaddrinfo.c, musl doesn't handle systems that don't have ipv6 enabled, doesn't document the tricky corner cases of the RFCs that cover name resolution, doesn't check for order of precedence, doesn't handle site local address ranges, etc. Other sticky points offhand look like a much lower amount of i18n support in musl, the inclusion of floating point emulation in the bigger C libraries, and other bits and pieces that are useful when you find yourself on platforms that aren't as full featured as other architectures. Aditionally, individual files in musl do not carry licensing and other information, which again pushes up counts of code length.

This is just a 10000 foot view of the two, but hopefully is helpful in starting to explain why musl's small size may not be all that advantageous if you want the kind of coverage a libc like glibc or freebsd libc has.


Some of that will be glibc's coverage of a much wider range of architectures and host OSes than musl (a very back-of-the-envelope wc -l suggests that somewhere between 20 and 25% of glibc code is in sysdeps/ or ports/sysdeps/), but that's clearly not the only thing contributing to glibc being bigger.


There is also GNU specific functions and macros in glibc. Is musl implementing _GNU_SOURCE? I know that my own project use TEMP_FAILURE_RETRY macro quite heavily, among with asprintf.


I think Musl would probably be a better starting point for a libc rewrite. It would be cool if people were willing to take this on.


This comparison is mentioned here or there, but it is important to add that it's not that recent.

musl 1.1.5 was released on October 2014

glibc 2.19 was released on February 2014

Author of that page should probably add at the top of the page big header "2014". I can't find contact info to ask of him to do that though.


The author is Rich Felker (the musl developer).


Correct me if I'm wrong here but the CVE-2015-7547 vulnerability covered code that fell into "libresolv"--at least under Ubuntu. This is a smaller subset of glibc that would take far less effort than a re-implemtation of the glibc in its entirety.


I understand why people want to rewrite C libraries and such in Rust.

Software like glibc is battle-tested---it is _widely_ used on hundreds of thousands of systems around the world, and has been used (though not at today's massive scale) for decades. I understand that glibc is under active development and there is a lot of new code, but let's keep this in perspective:

Writing a new implementation of a system is a huge opportunity to introduce bugs. There is focus on these specific problems, but in the broader scheme of things, glibc is remarkably stable, performant, and feature-rich. A new implementation will have bugs, and those bugs might be less likely to be caught simply because the system will not be as widely used for quite a long time. Even formally proven systems don't address flaws in the actual program specification. (See "The Limits of Correctness" by Brian Cantwell Smith for a good discussion). Also relevant (which I'm reminded of in part because of his recent death): Peter Naur's Programming as Theory Building.

So even _new_ code to glibc has the benefit of a huge community of both developers are users to eyeball it and test it out in production on a huge number of systems.

So rewriting glibc may solve certain problems, but it's bound to create a whole lot more, considering the narrow range of issues that are being focused on. New Rust code will have undiscovered issues too, even if they're not memory or stack related. I feel that this effort might be better spent fixing and finding problems with glibc---and continuing the development of tools to find those problems, to benefit _all_ of our old C libraries and programs---than rewriting for the sake of rewriting.


> New Rust code will have undiscovered issues too, even if they're not memory or stack related.

Memory issues have a tendency to be the most severe types of issues from a security perspective. (Not always, but with a high frequency.) Other issues that may occur with a rewrite may be security problems as well, but the security track records of network-facing software written in old-timey C speak for themselves: memory safety issues make up a huge fraction of their vulnerabilities.

> I feel that this effort might be better spent fixing and finding problems with glibc---and continuing the development of tools to find those problems, to benefit _all_ of our old C libraries and programs---than rewriting for the sake of rewriting.

So we've been trying that for the past 35 years since C was released in 1978, and we've completely failed to move beyond making the same basic memory management errors again and again and again. I think that if we couldn't do it in 35 years, we aren't likely to be able to by just trying a little harder this one time.


One problem with rewriting libc in a safer language is that interfaces will still be memory unsafe. No matter how many times you rewrite 'gets' it will still be broken, str* will still be problematic, the heap can be still trivially corrupted by the application, etc.

As long as the public interfaces are still unsafe, it doesn't seem to me that there is significant latitude to qualitatively improve the security of a libc implementation.


> As long as the public interfaces are still unsafe, it doesn't seem to me that there is significant latitude to qualitatively improve the security of a libc implementation.

Of course there is. The glibc bug we're talking about would not have happened if libresolv were memory safe.


I was too negative in my last message.

To be more precise: I claim that, for a library for an unsafe interface, if the ratio of library interface area over the library implementation volume is high enough, it is not worth re-implementing in a safe language. I also claim that a libc implementation is generally well above this threshold.

I agree that this might not be the case for selected subsets of the library like libresolv.


We can resolve this empirically, by looking at the list of glibc CVEs: https://www.cvedetails.com/vulnerability-list/vendor_id-72/p...

The vast majority of the memory safety issues here are not at the public interface boundaries.


> Software like glibc is battle-tested

This seems a bit counter-intuitive given that serious problems are still being found years or even decades later. Perhaps battle-tested is insufficient.

And while new code is likely to have bugs, assuming it's already based on the original C code it would be less than if it was re-written from scratch based on a spec. New code can take advantage of the battle-tested nature of the original code even if it's in a different language.


Yes, there's this whole attitude of "black-boxiness" to these types of arguments that I find troubling; that it is simply the nature of the machine to be unpredictable, and that therefore the safest and best code is the code with the most mileage on it, and every time you poke it you compromise the integrity of the system as whole.

(It's a close cousin to the "don't rewrite it" argument we've all heard via Spolsky et. al., even though they've ended up rewriting their shit several times over).

There is a fundamental shift forward in the types of guarantees you can make with the premises of a language like Rust vs. that of C that I have simply never heard one of these demagogues address.


> This seems a bit counter-intuitive given that serious problems are still being found years or even decades later. Perhaps battle-tested is insufficient.

Bugs will always exist. But that statement will apply equally to any software, regardless of language.

> New code can take advantage of the battle-tested nature of the original code even if it's in a different language.

That's why I referenced the Peter Naur paper on Programming as Theory Building---in practice, that may very well not be the case.


> Bugs will always exist. But that statement will apply equally to any software, regardless of language.

I'd be curious to see some research suggesting that the prevalence and severity of those bugs is identical regardless of development tool/language/runtime, but I'd be surprised if that's demonstrable.

The question at hand is not "will safer languages eliminate all bugs?" It's "will safer languages reduce the prevalence and severity of important classes of bugs?" I'd wager it's probably yes, but even if you disagree, I don't think that it's reasonable to suggest that because there will always be bugs we should never improve.


> I'd be curious to see some research suggesting that the prevalence and severity of those bugs is identical regardless of development tool/language/runtime, but I'd be surprised if that's demonstrable.

I intended to convey that software written in any language will have bugs, not that all languages will produce the same types of bugs.


Yes, but all that gets you is that no language is a panacea; bugs always exist. It does not address the question of whether or not there will be a propensity for more bugs (or more severe bugs) when comparing two languages.


> It does not address the question of whether or not there will be a propensity for more bugs (or more severe bugs) when comparing two languages.

My argument is based on the act of rewriting it---regardless of language. Many languages provide excellent guarantees, but that does not protect against bugs in the implementation itself (logic).


Yes; and the rewrite can take into account the logic used in the old code (especially in the security-critical areas) as well as all the vulnerabilities that have happened before. You're not starting from a complete blank slate; you can pick up the lessons learned.

Despite being "battle tested", all of these C programs continue to have both memory and logic errors. I think a rewrite would have the same rate of new logic issues after the initial code review and testing. "bugs will always exist" -- sure, so if we have something that eliminates a class of bugs, why not use it? The other classes of bugs will be there (and probably in the same force) whether you rewrite or not.

A lot of these bugs get introduced due to cruft in old code as well. So there are a bunch of tradeoffs here.


> Many languages provide excellent guarantees, but that does not protect against bugs in the implementation itself (logic).

This is the black and white security fallacy. Memory safety problems are, statistically, a huge quantity of security bugs. By eliminating them you drastically reduce the number of bugs.


Battle tested in the past != fit for future wars. The nature of systems has evolved. Attackers are more sophisticated, have better tools and probably understand C code better than most who still write it. So our tools need to evolve too. Admittedly rewriting full libs into another language sounds scary, but hey - since when did fear of the future stop it from coming?


I'm unconvinced by the argument that C is unfit for future wars.


It's simple:

1. Memory safety issues are the cause of a very large number of security vulnerabilities (often most of them for projects written in C or C++, depending on the software).

2. Memory safety-related issues have a relatively high probability of being turned into remote code execution, which is one of the most if not the most severe outcomes.

3. C and C++ projects have been empirically observed to have orders of magnitude more memory safety problems than projects written in other languages do.

4. The additional classes of security vulnerabilities that managed languages tend to foster do not have the combined prevalence and severity of memory safety problems.

So, we would be better served in security by moving to memory-safe languages.


> C and C++ projects have been empirically observed to have orders of magnitude more memory safety problems than projects written in other languages do.

Note that this includes projects in languages that are themselves written in C or C++, which shows that there's some value in confining the unsafe code to a small and well-tested core library (in this case, the language runtime). Honestly, it seems like 50% of the value just comes from not using C strings, since pretty much every other language has its own string library that does not use null-termination.


Memory safe programs require

1) Runtime overhead for some form of GC (D, Lisp, etc)

2) Rephrasing a program to satisfy a memory constraint checker (Rust)

3) Disciplined memory usage (i.e. Nasa C coding guidelines)

We don't have enough experience with 2 to indicate whether it will create new classes of bugs. We also don't understand the knock-on effect of managing memory differently - will functionally identical programs require more or fewer resources, more or fewer programmers hours, etc.

Rust may very well be the future, but we don't know for sure yet.

One thing we do know: options 1 and 3 have been available for years, but not widely utilized. What lessons can we learn from this fact to apply to Rust?


> We don't have enough experience with 2 to indicate whether it will create new classes of bugs.

What classes of security bugs could possibly arise from Rust's ownership discipline?


Logic bugs. Failure to correctly adapt imperative algorithms while still satisfying the constraint checkers.

Not all security bugs are related to memory. Many are related to improperly written algorithms (most crypto attacks), or improperly designed requirements (TLSv1).

Even Heartbleed was primarily due to a logic bug (trusting tainted data) instead of an outright memory ownership bug.

Does Rust automatically zero out newly allocated memory? Honest question, I don't know the answer.


> Logic bugs. Failure to correctly adapt imperative algorithms while still satisfying the constraint checkers.

Oh, also: If you're implying that Rust's ownership discipline can create security bugs where there were none before, I consider that a real stretch. I'd need to see an actual bug, or at least a bug concept, that Rust's borrowing/ownership rules create before accepting this.


> Not all security bugs are related to memory. Many are related to improperly written algorithms (most crypto attacks), or improperly designed requirements (TLSv1).

Nobody is saying that Rust eliminates all security bugs. Just a huge number of the most common ones.

> Does Rust automatically zero out newly allocated memory? Honest question, I don't know the answer.

Yes.


> Not all security bugs are related to memory.

This is a problem that will be there equally in all languages

Perhaps less so in languages with a better type system, but that doesn't affect Rust since there aren't any _systems_ languages with a better type system.


You most definitely know a lot more about code than me. So I'm not challenging you at all. But my contention is that robustness is a function of resilience. C has a class of errors which are hard to spot for foot-soldiers, and sometimes even generals which can leave deadly chinks unspotted for long. If Rust attempts to do away with those specific type of errors altogether, what's wrong with that? Rewriting code. And if that seems like a challenge worth attempting for some people, I can't fault it. And in the process maybe we will discover more bugs, or maybe something better. Its evolution, no?


It's not a bad thing that Rust addresses these issues. That's good, and essential for newer languages---it wouldn't make sense to not try to solve these problems in a language that intends to be lower-level (like Rust), relatively speaking.

The paper on the Limits of Correctness that I mentioned above does a good job at arguing my point. Even if you rewrote glibc in a language like Coq and formally proved its correctness, that doesn't mean that it's "correct" in the sense that its logic mimics glibc---there could be logic errors.

So you might gain confidence (or guarantees) in rewriting glibc in Rust, but in rewriting it you potentially introduce a host of new issues.


  > Software like glibc is battle-tested
"The best time to plant a tree is 20 years ago; the second best time is now."


The comment about changing the const pointers is subtly wrong. There are pointers to const memory and there are const pointers to memory. My favourite little known C fact. See also http://stackoverflow.com/questions/1143262/


That's not really "little known". Almost every single piece of code that does string manipulation in C uses that fact:

  const char* s = ...;
  while (*s++) { ... }


I think you have proven my point. I'm talking about this:

  void something(const char* const s);
Maybe I'm extrapolating here, but it surprised me.


That is indeed what the post you're replying to meant. Note that the pointed-to value is a constant string, yet the pointer itself is being modified. That's a fairly common idiom in C string-handling code, only possible because it's a const char , not a const char const.


constant pointers are arguably little-known, though pointers to constants are well known.


Agree with the other comments that this is most decidedly not "little known". The author loses all credibility in all C topics for saying this is poor form.


Not sure who your issue is with, me or the author of the article?


Not you. You can relax. :-)


Is there a good reason why a binary compatible glibc couldn't be re-written in a better language? People are always going to be using C/C++ and there is little that can be done about that exposure, but at least the libraries they rely upon could be better engineered to have certain assurances about safety.


You'd lose most of the safety. E.g. a lot of the value of Rust comes from ownership tracking, but you can't track ownership across a C-ABI boundary because the information simply isn't there. And I'm not sure assurances in libraries used by unsafe languages are really that valuable - it'd be like locking your back door and leaving your front door open. Better to make a clean break.


Most of the bad stuff in glibc is due to bad API's, not to bad programming languages. (E.g., non-reentrant functions with global state, functions that deliberately crash on incorrect input, poor separation between standard library functions and non-standard but commonly accepted ones, poor separation between stuff that's needed for C and stuff that wraps kernel/syscall functionality, etc.)

Parts of it probably should be replaced with safer implementations, but as long as you're going for 100% compatibility you're still putting lipstick on a pig.


I don't think there's a reason why it couldn't happen at least in parts – it sounds like that's Mozilla's plan for migrating parts of Gecko – but I suspect you'd hit an 80/20 rule pretty hard where many programs could use your alternate libc but a fair amount of code would have different results due to arcane details for things like threading, signal handling, etc. and it would be quite time-consuming to hit complete compatibility.


I don't think it would be worthwhile to rewrite all of glibc, at least not initially. We should focus first on libraries that parse attacker-controlled input, such as glibc's DNS resolver, image libraries, font libraries, etc. Most of glibc does not parse attacker-controlled input and is probably already safe.


Microsoft re-wrote their C runtime library in C++, taking advantage of the language features for writing safer code.

https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great...


There could be bad habits built into glibc that everyone has just learned to live with, that Rust explicitly forbids, or makes difficult to reimplement, such that doing so would reintroduce all of the same problems as before.


Minimalism comes in many forms. Here, we see an example of a content-free article.

> fun aside, name and service are both const char* so I find it funny that they are set in the program, I do understand that from the callers perspective they don't change, but still bad form

… are you sure you know enough C to do this?


I know that it's used for more than just C programs, but it still seems a little perverse to rewrite the C standard library in something other than C. Imagine if someone had a preference for writing his Python libraries in Perl that emitted Python bytecode. Or if C++'s Boost was the output of a Haskell program.


I get what you mean, but I guess calling it the "C Standard Library" is really a historical holdover from times when the entire system was written only in C (with the exception of a smattering of assembly). In the current context it should probably be called the "System Standard Library" and when you consider it like that, a system standard library in another language isn't all that weird. They all compile down to machine code anyway, so the Python-Perl analogy doesn't quite match.


UNIX is the C runtime, kid of.

They just didn't want to force it into other OSes when ANSI C was defined and eventually POSIX took up that role.


Actually many people have a preference for writing their Python libraries in C :-) Python was explicitly designed under the assumption that much of the heavy lifting will happen in C. And C programmers write their parsers in Yacc, etc.

(This is not to say that rewriting libc is a good way for people knowing Rust to spend their time. It's a ton of effort with the result most likely to be unused and if it is used, then it provides a small benefit to C and C++ programs at the expense of a rather scarce resource - Rust developers - having been diverted from benefiting Rust programs. If I were a Rust enthusiast, I'd much rather write libraries in Rust designed to be used in Rust programs so that more such programs get written more quickly than use Rust to put lipstick on the pigs that are C and C++.)


It seemed perverse to me to write our desktops and servers in C given how it was "designed:"

http://pastebin.com/UAQaWuWG

Once one understands it, getting rid of as much of it as possible makes a lot more sense. The replacement should ideally stand alone eventually, have stronger memory/type/integration safety, not assume what calls it (eg C code) will do things right, and integrate with C easily. Not sure how much Rust fits that as I lack details.

Result would've eliminated all kinds of crashes and host compromises due to C-specific errors. It is ironic that one of the best ways for a C application to be safe while using 3rd party code is avoiding C in that 3rd party code. :)


On the other hand, how many languages use libraries that are written in C? Especially in the higher level scripting language ecosystems(JS, Python, Lua) a lot of libraries interface with C/C++ libraries. If instead they used Rust, would that not result in a gain for those languages(even if there was a small C wrapper around it)?


What about a C compiler written with C++?

If it helps any, `getaddrinfo` is actually part of POSIX and not an essential part of C.


Another potential source of inspiration is Musl: http://git.musl-libc.org/cgit/musl/tree/src/network/getaddri...


So many tentative posts here :)

I say, "Go for it!" Kozlowski's attitude is exactly what we need. That's not saying it will ship in Ubuntu 18.04... It will be carefully vetted just like any piece of software, but it's got to start somewhere and I like that he's sharing his thought process with the community.

As people have pointed out, it may not actually be the Rust part of it that's valuable, but the organization and code quality. Rah rah!


I'm not so sure about the attitude.

> After reading about the newest glibc vulnerability, I have decided to see how much effort there is in rewriting parts of glibc in a safe language.

If I were a C programmer, especially if I were a C programmer who worked on glibc, I might feel a little bit insulted that remark. Safety is a complicated concept, and calling Rust "safe" and C "unsafe" oversimplifies things, especially if your Rust code includes unsafe blocks. See also http://www.tedunangst.com/flak/post/heartbleed-in-rust.

I don't think we have anything to lose by being as diplomatic as possible with these sorts of things. We can acknowledge that Rust's safety is a work in progress, and that we're still learning about the drawbacks.


it might oversimplify it, but there is truth in there too


Has anyone successful linked to a Rust library from another language (ie Python). I know Rust offers FFI and will apparently make its data representations C like if annotated and I think has some ABI.

This is the second post I have seen in the last couple of days of "glibc is bad lets rewrite it in Rust". However the problem is not that glibc is just bad but rather everything links to it. If other languages can't talk to Rust easy this would be a nicer problem to focus on first (before rewriting glibc).

I guess this is sort of how its done: http://siciarz.net/24-days-of-rust-calling-rust-from-other-l...

Rust -> C <- Other language. You have to create the C header files (I'm surprised Rust compiler or something similar doesn't automate this).


I wrote a simple example of calling out into Rust from Python using cffi: https://github.com/maciejkula/python-rustlearn.

The gist of it is: it's really easy.


I don't know when this was last updated, but:

http://jakegoulding.com/rust-ffi-omnibus/

It's got a nice breakdown of how to bring rust libraries into a few languages. There are a few tutorials about how to make rust produce a static or shared library, but it's pretty straightforward.


You don't necessarily need C header files. Rust is able to export symbols easily with the C ABI; if your language has the ability to take a library and call such symbols (Python/Ruby do; for example), you're fine. It's only C++ where you need a header file because that's how C++ binds with any library. It's not a Rust-to-any-language issue, header files are a Rust-to-C++ issue only; really, an any-language-to-C++-or-C issue (I think such a tool exists, too).


A C header is not needed at runtime, it is purely a way to easily describe the symbols in a library that exist in a (somewhat) type-safe way. It's the lingua franca for describing libraries, and tooling (such as Rust's bindgen, or Python's cffi) can consume them to do the setup/create the information necessary to call functions from other languages. This is much nicer than manually trying to transcribe the Rust (or whatever) signatures into your application.

> header files are a Rust-to-C++ issue only

Or... C? (And of course other languages too, as just discussed.)


> It's the lingua franca for describing libraries, and tooling (such as Rust's bindgen, or Python's cffi) can consume them to do the setup/create the information necessary to call functions from other languages.

Hence the "not necessarily" in my comment. The parent seemed to be painting this as extra unnecessary work; I was saying that a header file is _not_ necessary except for binding to C/C++.

If you want to write a C API that will be called from many languages; you should have a header file so that bindgen tools can consume it. If you want an API that will only be called by Python .... not so necessary, you may want a header file anyway but it depends on the situation.

> Or... C?

Sure, goes without saying :)


Too late for me to edit, but regarding the C header file situation, this tool has been around for a bit:

https://github.com/Sean1708/rusty-cheddar

I haven't used it personally, but it looks useful.


Skylight[1] from what I understand is a ruby gem written in Rust. It monitors your ruby runtime and sends the data to the central servers for analysis.

1: https://www.skylight.io/


It was also one of the first production uses of Rust.


How many new vulnerabilities and bugs will be introduced by doing this ya think?

Rust in and of itself won't make things all better.


> fun aside, name and service are both const char* so I find it funny that they are set in the program, I do understand that from the callers perspective they don't change, but still bad form

Correct me if I'm wrong (I haven't programmed in C++ in forever), but aren't "name" and "service" pointers to constant arrays of characters rather than constant pointers to (mutable) arrays of characters? In the first case, you're saying you have a variable that points to a memory location; the variable itself can be changed, but the data in memory at that location cannot. In the second case, you're saying that you cannot change the variable that contains the memory address; however, you can change the data in memory at that location.

(And if I remember correctly, I believe there are also such things as constant pointers to constant memory...)


http://cdecl.org/

    const char *foo
declares a pointer to a char that is constant.

    const char * const foo
declares a constant pointer to a char that is constant.


You know, you could just

    apt-get install cdecl
And then do it on the command line. But hey, let's turn everything into a web service, with NSA et al. monitoring as a bonus feature.


Not only that, but most people in this thread are STILL missing the multiple elephants in the room.

First, Rust allows unsafe code in the core language [not simply through FFI as in other safe languages]. So there's a gaping hole that we know will be abused (performance! performance!) right there. Even if we grant that this is not the case, here is the deal breaker:

The Rust approach to security depends on an ecosystem that follows the same approach. To think that this is more than an utopic dream is to enter cuckoo-land in my opinion. So we digress back to the castles-built-on-top-of-sand.

There's millions of lines of code written in unsafe languages plus all mainstream operating systems. The Rust approach will never work in this sort of environment.

An approach that might work however is unikernels and using a language that promotes design with failures in mind [and makes it extremely easy to rapidly rearchitect/rebuild/redeploy]. Erlang is the best example in my view, but there could be more.

Alas, Rust is not really suitable for this either due to its static nature.


Your comments in this thread have been inflammatory, condescending, and vague. That amounts to trolling, whether you intended to or not. You've done it quite a bit in previous threads, too, which is not good. Please don't do this on HN.

Here is how to stop: (1) take out everything inflammatory ("It boggles the mind how utterly misguided", etc.) and make neutral statements instead; (2) take out the personal language ("you just don't get it", etc.); (3) replace vague grand claims with specific factual statements.

If you do this, you'll not only no longer be breaking the HN guidelines, you'll also be sharing what you know more effectively, which benefits all of us.

We detached this subthread from https://news.ycombinator.com/item?id=11162577 and marked it off-topic.


  > we know will be abused (performance! performance!)
None of the programs (or at least most, I only checked the first 5) in which Rust is faster than C use unsafe directly. It's in the libraries they use, but safe Rust is very performant.

We'll have to agree to disagree about the rest. :)


It boggles the mind how utterly misguided the "let's rewrite everything in Rust!" people are when it comes to understanding security and its implications.

Let me begin by introducing my premise: Rust will do NOTHING for security, it is not an improvement in any way, and at least as far as security is concerned, it will lead to at best colossal time waste, at worst actively damage the cause by misdirection, making ppl feel warm and fuzzy, providing illusion of security.

What??? B-b-but memory safety, I hear you say. How can this even be possible I hear you cry.

Memory safety (assuming that Rust completely solves it, which it absolutely DOES NOT) is but one (small) piece of the entire puzzle. In the same way that the skilled craftsman knows that he can't build a castle on top of sand, the skilled (and security conscious) software engineer should realize that memory corruption (and race conditions in the same unit/process) are not the foundation of the security chain. I dare say that a lot of the bugs exploited out there today (but not necessarily made public), are pure LOGIC bugs (that include race conditions) that stem from the interactions between extremely complex autonomous subsystems. Rust is simply operating at a too high-level abstraction layer to deal with any of these issues. This is the logical progression of Sergey Bratus's weird machines taken to the next level.

Some examples:

The Linux kernel. Any UNIX operating system taken as a whole. Any Windows taken as a whole. Any OSX system.

Anything built on top any of the above. Anything built on combinations of any of the above. Weird machines are not limited to isolated units, you know, they very well exhibit EMERGENT behavior.

Are you starting to get the picture now?

And then of course we still have the bugs that stem from unsafe languages, as long as there's a path that cuts through all the intermediate layers of "safe" code. Graphics drivers and webgl anyone? Truetype in the kernel?

Rust has plenty of things in its favor but to position it as a cure for issues that it doesn't even know how to address is a colossal mistake. We have given rise to a beast that threatens to consume us all. It's one thing to despair due to the immense complexity of the domain and quite another to step into an imaginary realm and solve illusionary problems that we create just to feel "safe".


There were about 36 000 traffic fatalities in the US in 2015. This is inherent to the trillions of miles traveled in affordable machines operated by drivers of variable competence, and nobody has a solution to fix the problem today. Maybe one will emerge, but between now and that day we're going to keep driving and keep killing each other.

Should engineers, admittedly lacking an absolute solution to traffic fatalities, forego seeking designs and materials that reduce the frequency and consequences of failure?

Rust delivers a higher degree of memory safety. It is a better tool in the tool box and arguing that engineers should ignore it because their efforts are inherently flawed won't work, any more than arguing that a new headlamp or traffic light design is futile.

Also, you should understand now what you're up against. The legacy stack is riddled with flaws; every day we face a deluge of security notices, some large fraction of which are caused by memory safety problems. In other words, your opponents in this debate have an endless supply of ammunition.

Good luck with that.


> here were about 36 000 traffic fatalities in the US in 2015

> nobody has a solution to fix the problem today.

You're entire premise revolves around 0.01% of the population. That's not a good basis.

There's about 34,000 automobile related deaths annually in the US[1]. There's about 323,000,000 people in the US.[2]

The point I'm making, is let's not get carried away with exaggerating how "bad" a "problem" is. According to the CDC, more people die annually from accidental poisoning (about 39,000) than automobile related accidents - but I don't hear all the calls to "solve" that problem.

Will things be "safer" written in Rust? Maybe. Does Rust solve everything? Absolutely not. Yes, a lot of bugs are "unsafe" memory access issues, but a lot of bugs are not. Re-writing everything in a pet language that happens to be popular today in 2016 is not a good call. Rust is fairly new, and nobody has any idea if it will stand the test of time. C has, clearly.

Instead of getting out our pitchforks, we should rally to guarantee these critical projects are fully funded and staffed with full time developers. That alone, will yield far greater results than some lofty goal of completely re-writing 100's of thousands of lines of code which have been working, tested, and matured for almost 3 decades.

[1] http://www.cdc.gov/nchs/fastats/accidental-injury.htm

[2] http://www.census.gov/popclock/


> Yes, a lot of bugs are "unsafe" memory access issues, but a lot of bugs are not.

A huge number are. For example: https://www.cvedetails.com/vulnerability-list/vendor_id-72/p...

> That alone, will yield far greater results than some lofty goal of completely re-writing 100's of thousands of lines of code which have been working, tested, and matured for almost 3 decades.

Windows, the popular Web browser engines, and antivirus software are all examples of systems software that are very well funded. But they still regularly fall to memory safety problems. The converse is also interesting to look at: djbdns and qmail are examples of poorly funded software, but they have had very few memory safety problems.

I agree with the general principle that funding helps security overall, though.


You're entire premise revolves around 0.01% of the population. That's not a good basis.

Mine is the basis of billions of dollars of engineering and untold amounts of legislative and regulatory efforts around the planet. A lot of people seem to think it's a pretty important basis.

let's not get carried away with exaggerating how "bad" a "problem" is

On one hand you ask others not to exaggerate, next you're talking about pitchforks. The story we're discussing is about someone reimplementing one little 300 line procedure. I made no more of Rust than to call it a better tool in the toolbox. Calm yourself; these pitchfork wielding exaggerators you speak of are fictions inside your head.

stand the test of time. C has, clearly

The buffer overflows, dangling pointers, double frees, use after frees and leaks recorded daily as CVEs is the most demonstrative thing time has revealed about C et al. If C had past the test of time Rust wouldn't exist.


"Poisoning" in the CDC statistics includes alcohol poisoning and drug overdoses [1, table 18, also see definitions of codes X40-49 and X60-69]. There've been plenty of public health initiatives against this, notably: Prohibition, the War on Drugs, DARE, child-proof pill bottles, pharmacist licensing, the [poison control] OneBox on Google, etc.

I think that's pretty good evidence of the grandparent's point: no, you're never going to make anything completely safe, but society can and does put a lot of effort toward harm reduction.

[1] http://www.cdc.gov/nchs/data/nvsr/nvsr64/nvsr64_02.pdf


I have trouble understanding what you try to say - but a library like glibc must not have memory corruption problems to start with. Clearly, it seems that currently it has those problems. Either you can find maintainers for the C code which will never create a memory corruption problem, or use a tool which assists the maintainers with this. Also, more modern languages than C would in general make the code more maintainable, again helping with weeding out security problems, be they coming from memory corruption or any other cause.


[flagged]


It would likely have LESS memory corruption problems, as you're eliminating places in the code that that can occur. The real question is: Does Rust allow you to write less bugs? That's a somewhat open question, but it definitely eliminates certain classes of bugs which are common today.


From intensive but still hobby usage for the past 10+ months I get a feeling that I have a lot /less/ bugs, and if I do have one it is an algorithmical error rather than some UB.

This is of course just my view and is heavily skewed towards what I usually do, which is Games and Web Apps. It also depends on how you qualify a bug. (Is a panic a bug? Might or might not be.)

To continue that train of thought: I have a feeling Rust will change what one would consider a bug (inside the Rust ecosystem at least). Since you do not actually corrupt memory most of the time (minus unsafe shenanigans) you actually do not get a lot of cases where you get a crash and you don't know why. RUST_BACKTRACE always told me where something panicked which is pretty much always sufficient to debug since you just have to verify your invariants you thought were correct when you for example 'unwrap' or call panic! yourself.


If you are not putting forward an argument, then you are not contributing to the conversation, just wasting people's time reading your comment. Therefore I am downvoting you.

There are cogent arguments to be made about why Rust isn't a panacea. (I have a few I'm partial to, like integer overflow / truncation bugs.) But if you want people to listen to those arguments, make them.


> Memory safety (assuming that Rust completely solves it, which it absolutely DOES NOT) is but one (small) piece of the entire puzzle.

Visit https://www.cvedetails.com/vulnerability-list/vendor_id-72/p.... Count the number of memory safety issues. The first five, for example, are all memory safety problems.


Viewing Rust as a panacea for security issues is certainly misguided. However, people should at least attempt to use a more memory safe language to write this stuff. If it proves to be worse code, then we're not forced to use it - we already have getaddrinfo to fall back on.


It boggles the mind how people think the only benefit of Rust is memory safety. Rust has novel features for solving concurrency issues, what you call "pure LOGIC bugs (that include race conditions)".

Of course memory safety is one small piece of the entire puzzle. That's why Rust has features besides just being a memory-safe version of C.


Read my post again cause you obviously didn't understand anything of what I wrote.

You can have 2 components written in 100% safe language with no memory corruption and no race conditions.

You can have security critical race conditions that arise out of the interaction of same components.

How is Rust or whatever solving this? It doesn't.


"How is Rust or whatever solving this? It doesn't."

Actually, yes, it does. The borrow checker composes. Two correct Rust components for race conditions and memory safety will indeed compose together correctly. That's a great deal of the point of the whole thing, after all.

I don't think you've been keeping up with the state of the art in the last few years. Maybe less yelling and more listening is called for here.


This reminds me of a post I once read arguing that type-safe languages weren't actually helpful, because they (generally) still let you write programs that could violate type safety. I thought that argument was silly, and I think yours is too. Yes, I'm quite confident that Rust isn't a panacea, anymore than functional programming will be, or object oriented programming has been, or type safety is. The point is that each of those techniques helps you to avoid certain classes of bugs. And so far as I can tell, Rust genuinely does have features that make writing certain kinds of bugs much less likely. Yes, Rust doesn't help you prevent every kind of bug. (Shocker!) But I don't get the point of insisting that decreasing an attacker's surface space isn't worthwhile.


Security is all or nothing. There are no in-between states. If there's something to get from all my posts, is that we need to learn to operate with the assumption of compromise in mind, plan for failures and learn to rebuild, rapidly. Rust simply solves the wrong problems.

For a language that certainly has the mindset, look at Erlang. Unikernels and Erlang will do more for actual security than a million monkeys cranking out perfectly safe Rust code.

"Decreasing an attacker's surface" is pragmatically, bullshit. No competent attacker (and that doesn't include just nation states these days) will be deterred by a decreased attack surface.


I'm sorry, but this line of argument is not even wrong as it relates to the entire modern infosec field, which is founded on the fact that there is no such thing as "100% security"; that is why concepts such as "threat models" and "defense in depth" exist.

Also, proving a program "correct" (for some definition of correctness that presumably includes "secure") is undecidable, ergo there cannot be such a thing as a "100% secure language". No, not even Erlang, nor Haskell, nor anything which is remotely close to Turing-complete. So all we can do is, in fact, decrease the attack surface.


> No, not even Erlang, nor Haskell, nor anything which is remotely close to Turing-complete. So all we can do is, in fact, decrease the attack surface.

You often don't even need Turing completeness.


Practically, I think it's wrong to say "Security is all or nothing", with no in-between states. Most attacks and/or security bugs are built on a combination of problems. Anytime you fix one of those problems, you make it less likely that someone will find a chain of problems that ultimately allows them through. If you take the example of the Heartbleed bug (a classic buffer overflow), it would still be possible to have written it in Rust, but it would have been more difficult, and hence less likely. That's a worthwhile trait for a language to have.


Rust isn't just a safe language. It has other features. For instance, it's a much more strongly-typed language. You can use strong type systems to solve that exact problem.

If you give me a more concrete example, besides "you can have race conditions," I can give you a more concrete way Rust fixes it, besides "you can use types."


You still don't get it (this exchange is a great example of how hard it is for ordinary technically-minded people to shift into the proper mindset and begin to understand what the real issues are).

The race conditions I refer to DO NOT EXIST in the static pieces of code written in Rust or whatever ivory tower language. They are EMERGENT pieces of DYNAMIC behavior that only manifest at RUNTIME due to subsystem interactions.

And by subsystem I don't just mean pieces of code...


Can you give a concrete example of a recent major security issue caused by the sort of dynamically emergent interaction you're referring to? Anecdotally, the hair-on-fire security issues in fundamental components that keep coming up always seem to involve unsafe memory usage.


Buffer overflows seem to be a pretty recurring theme in these security issues, yep.



Row_hammer

You're citing a hardware flaw as a reason not to pursue programming tools and techniques that produce fewer software defects? That's a false dichotomy; we don't forego researching cancer treatments just because some of the people that are saved will end up getting shot.

Earlier you wrote "Security is all or nothing".

That's another amazingly bad point of view. There is no "all." Nothing is absolutely secure. There is only raising the bar. Important things are provided more protection than less important things. That is the best that can ever be achieved. Since your premise relies on a fiction your conclusions about the value of Rust are meaningless.


Rowhammer is a very good point. Hrm.

Rowhammer is basically mitigated if you don't let untrusted processes run CLFLUSH, right? That's sort of orthogonal to your choice of programming language (which might be your point, but then, I'm not sure I believe that Erlang or unikernels solves this either). It requires a world in which you've got something Native Client-like wrapping all userspace processes, which definitely seems like a good goal to work towards, and also seems easier to implement reliably in Rust than in C.


I agree that they are emergent behaviors between multiple systems. I am claiming that these individual components can capture knowledge of other components via strong type systems, and thereby eliminate race conditions. Can you explain why this is untrue?

I am trying to shift my thinking, but all I'm hearing is "No it can't." Can you explain why it can't?


One of my personal internet observations is that any post containing the formulation "b-b-but" is a bad one. Usually betrays a sort of sarcastic know-it-all attitude.

I see you've used it. I think it sets a bad tone for an argument.


My rule for internet observations is, any post containing "you" is argumentative and off topic. The topic is never the other commenter. Using "you" is often received as a personal affront, derailing the conversation. It betrays a me-vs-you superior attitude?


Not a bad rule, I have to admit (and true in my case, my post was certainly off topic). As a general rule it's a bit broad though, I think. If one wants to address another's points directly, it can be hard to avoid the second person pronoun.


It takes practice. Addressing the points as points instead of something 'you' said is about all there is to it. But we're so used to conversational modes, its easy to fall back.


Please call your implementation getaddrrinfo


Some people, when confronted with a problem, think “I know, I'll rewrite this in another programming language.” Now they have two problems.


This is a great story to make glib comments on.


This glib comment has a long history in technology. So it seems appropriate.

    http://regex.info/blog/2006-09-15/247


I thought your parent was making a pun about 'glibc' and 'glib'.




Applications are open for YC Summer 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: