It’s time for a memory safety intervention
tonyarcieri.com
tonyarcieri.com
Curl should be replaced by something memory safe. But it cannot happen today, because the infrastructure isn't there. We don't have memory safe languages suitable for system programming that's widely available on all kinds of architectures. Rust may become that language, but today it is not. It's not as portable, not as easy to integrate etc. pp.
Stenberg said, and may believe, that C is not the source of most of curl's security problems. But examining counts of security vulnerabilities, it definitely is.
Putting that batch of 10 CVEs aside, the number of memory related bugs is quite small.
In the greater scope of things, ~60 CVEs over the course of 17 years is pretty small.
It does matter. No vulnerability can be used without knowledge of that vulnerability, therefore it matters who found it (did they publish or abuse the vulnerability?) and when (was it published shortly after the first discovery?).
My English is usually decent, but I still sometimes make stupid mistakes.
Yes, yes we do. Go is available on a ton of architectures; Lisp is available on a ton of architectures; ML is available on a ton of architectures.
Yes, C is available on more. Yes, for some architecture C is the only reasonable choice. But on x86 & ARM, there's no good reason to write new code in C.
What about any application that cares in the slightest about performance? In this case, memory layout is incredibly important, and many (most?) of those higher level languages are immediately disqualified.
I'm sure there are other reasons why Go would rarely be considered for a hard real time system, but purely from a memory management perspective you could simply disable the GC.
And then of course there is also Rust.
The most difficult thing about using Rust instead of C is that you must wrap your head around the borrow checker.
Sorry, but this is pure ignorance. Please let me know when was the last time you've tried to implement a CFD or FEA code in Go or Lisp ?
I think that http://www.femlisp.org/ is a finite element analysis for Common Lisp.
Case in point FEMLISP uses C or Fortran libraries (Triangle, Tetgen, OpenMP, various linear algebra libraries) under the hood for the actual computation :).
Haskell: https://wiki.haskell.org/Kernel_Modules
And you can find a few others.
Yes, we need it badly. Because I am still seeing a lot of folks either deny that memory safety is a big problem of programming in C or some even accept the fact.[1]
Without admitting that and start taking action to improve infrastructure software, I don't see how we can build a securer future. That's an intervention, it should start now.
[1] Pretty obvious from the beginning. The creators of C made a pragmatic choice and created a language which basically does not guarantee anything. This allowed them to write a compiler fast enough for the limited computing power they had at hand.
//edit: Also "C is great because I like programming in C" does not help here. If you like C nobody says you shouldn't ever use it anymore but you should be aware of the problems it drags along and maybe consider sth. else for security critical code.
Not to mention if you could not execute data, your programs would not load.
Interesting exercise : take a large Java server application and figure out if somewhere, somehow, it can be made to execute a string sent by a client.
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppC...
https://github.com/Microsoft/GSL
https://msdn.microsoft.com/en-us/library/mt762841.aspx
https://blogs.msdn.microsoft.com/vcblog/2016/10/12/cppcorech...
Microsoft has been embracing the idea. But, the GSL and Checker are both compiler-independent.
Is there some doc that explains how the Core Guidelines Checker could achieve Rust-like safety given what it has to work with?
Still, major improvement. Could very well be "enough", practically speaking.
Edit: apparently MS did release an experimental version that can check a small subset of the rules.
I just spent ~1.5 days tracking down a dangling pointer bug in interop code from Rust to C. It's so easy to do when you don't have lifetimes on pointers. I'd gotten so comfortable with lifetimes that I'd started taking it for granted.
Yes Rust can be hard to write, but the time and pain we spend of the other side of that equation can be just as important if not more so.
Some([u8; 32]).map(|v| v.as_ptr()).unwrap_or(::std::ptr::null());
Which the map(..) copies by value and immediately goes out of scope so now you have a dangling pointer to the stack(fun!). If it was a reference I'd be totally covered but since pointers drop lifetime semantics that's where I got bit.Love bindgen though, just whitelisting the function I needs generates awesome interop APIs. At the end of the day though unsafe is unsafe.
Yep, unsafe is unsafe and needs more scrutiny.
That doesn't mean people shouldn't switch to safe languages for new projects if they can, but it does mean that they should use the tooling available for C much more. Unlike what the article claims, they don't -- at least not those who write programs with lots of memory safety issues. There are static analyzers that can guarantee -- 100% -- no memory safety issues. Airtight guarantees may take some work, but it's still far, far cheaper to achieve using state-of-the-art tools than switching to a new language for many projects (even new ones in organizations where C is established, let alone old ones). Unlike what the article claims, programmers utilizing state-of-the-art C tooling and best practices do not "constantly produce programs riddled with severe memory safety vulnerabilities".
Unfortunately, those state-of-the-art tools and practices are used almost exclusively by authors of safety-critical software, and are not commonly used in more mundane kinds, let alone in open-source projects. An intervention more likely to work in the short term should push for that, regardless of longer-term solutions in the form of safe languages.
This is untrue, at least for any practical interpretation of such a guarantee. Which product do you think does this?
Note that for it to count, it has to return the results before the programmer is dead.
Sound static analyzers are not 100% automatic. They require user help in the form of annotations in cases where they can't prove everything automatically. But the work required is similar -- probably less -- than writing tests.
Also, note that it's very easy to find all memory safety errors in a sound way -- you just report every pointer and array access that's unsafe. The problem isn't identifying all errors, but proving the memory safety of the cases that aren't (and that's where they may ask for help in the form of annotation -- to convince them of the absence of an error).
So, like I said then. Doesn't exist in any practical form :) Annotations are clearly a non-starter.
If you can't get anybody to use something, it's a non-starter. It doesn't matter why. It just hasn't happened and it wont happen.
For new projects I don't really see why that should always be the case. It probably depends on the type of project, on the organization, on any integration requirements and on the willingness of developers to make the change.
I see this SEI blog entry [1] that cites a report, with a bitrotted link (I think it's [2]). The blog summarizes the report associating buffer overflow as a source of "14 percent of software security vulnerabilities and 35 percent of critical vulnerabilities making it the leading cause of software security vulnerabilities overall." Though it seems to be the easiest to track and a leading error, buffer overflow is only one category of memory safety problem.
[1] https://insights.sei.cmu.edu/sei_blog/2014/08/performance-of...
[2] https://courses.cs.washington.edu/courses/cse484/14au/readin...
[1] https://www.cs.rutgers.edu/~santosh.nagarakatte/softbound/ ; presentation: https://media.ccc.de/v/30C3_-_5412_-_en_-_saal_1_-_201312271...
Swift's probably on par with go. You have to diverge a bit from normal practice or involve concurrency to be unsafe. This is in contrast to C, where "normal practice" often produce buffer overflows.
I think there's really nothing to read into here.
> If I were going to write the Ten Golden Rules of Software, the top of the list would be:
> Error Prone == Evil
> Although this concept is obvious to 99.999% of the general population, it's only accepted by 2% of computer programmers. The remaining 98% subscribe to a competing philosophy, namely: "Error Prone = Manly". Never mind that they just assigned "Manly" to the variable "Error Prone", and the expression always returns true; that happens to be the correct value in this case, so it's an acceptable hack.
[0] https://sites.google.com/site/steveyegge2/ten-predictions
You don't have to move to Rust, but you do have to move away from C.
(but my general point was about sandstorm not fixing all the problems, just a subset -- not about whether other languages fix all those problems)
The curl devs were totally irresponsible, and worse, outright intellectually dishonest to pretend memory safety wasn't a serious problem for them or anyone else.
> It supports a wide variety of platforms,
> and might even run on that microcontroller
> you think can’t run anything but C.
Hahaha.
Oh, you're serious...let me laugh harder...
When the rust compiler can produce code that runs on my micro with harvard architecture, 14-bit instruction words, and 64 bytes (not megabytes or kilobytes) of RAM, we can talk.
.
EDIT: loving the downvotes. Keep them coming! Because nothing says "civilized debate" like quiet underhanded unexplained disagreement :)
I wrote a chess program that ran on a PIC 16 series with 176 bytes of RAM and I got 5 levels of look-ahead with a compiler that didn't support recursion. No dynamic allocation anywhere.
I laugh when people claim a Raspberry Pi 3 is an "embedded system". Sure you can embed it in something, but it's got an ocean of resources compared to most.
“Cortex-M3 micro (no FPU) @ 8MHz”
Basically, there are experimental ways to get it to work, but it's a huge ways away from being useful in a production environment.
https://github.com/hackndev/zinc https://forge.rust-lang.org/platform-support.html
Additionally:
> Please resist commenting about being downvoted. It never does any good, and it makes boring reading.
Pretty irrelevant in this case because your micro doesn't matter for the type of code we talk here. I doubt things the size of libcurl, openssl or anything like that will run on this thing.
Such a restricted machine unfortunately is not amenable to any abstraction and I have no idea what such bad hardware would be used for. Nor why.
I'm guessing that the other comment is referring to PIC microcontrollers. Over a billion such microcontrollers are sold every year. Not all of them are that limited, but many are.
And they are amenable to the abstraction of C. That's kind of the whole point of that comment.
The world of computing is far larger than PCs and smartphones. One could make a convincing argument that those are a small minority, in fact.
Well, that's sort of the problem, right? C was made so portable (because, admittedly at the time of development hardware was less uniform) that a lot of assumptions we take for granted are actually undefined, because you can't make those assumptions about the underlying hardware. What makes C usable and useful on these architectures is the same thing that causes problems for the other 99.9% of people programming in it.
Should a language with obvious shortcomings in the name of portability be one of the de-facto standard languages for all types of library development? Do i even trust a crypto or XML parser library written in C on a platform with a non "standard" word or byte sizes that wasn't developed specifically for that architecture, or those constraints?
> The world of computing is far larger than PCs and smartphones. One could make a convincing argument that those are a small minority, in fact.
As a question of where to optimize, I would say it pays to get a much safer language on these devices, both because it would prevent crashes, bugs and security problems, and because (I think?) far less people are responsible for writing the code, so a little extra work on their part pays of more overall).
I think C is as prominent as it is today because of how history played out, not necessarily because of its inherent merits.
You would use it for places where the uC is cheaper than a few transistors or flip-flops, for example to flash lights in a pattern. Also when you need extremely low power consumption, like a digital watch or BTLE beacon.
There are uCs in everything these days.
Incredibly common chips, less so today, but historically they were all over the place. Looking at Wikipedia, it seems the 14bit instruction set PIC had a whopping 128 bytes of memory.
For managing a bunch of toggle switches or dials with 8 positions, I imagine that was more than enough.
I can't tell if you're using hyperbole, or if you mean "any abstraction" literally.
If you mean it literally, we should probably discuss that.
I expect I'd agree with this article's substance, but I gave up in the first paragraph. I find myself unable to maintain giving a shit what this person has to say.