6 ms·
> In conclusion, the empirical research supports the proposition that using memory-safe programming languages for these projects would result in a game-changing
by gizmo 5y ago
> In conclusion, the empirical research supports the proposition that using memory-safe programming languages for these projects would result in a game-changing reduction in total number of vulnerabilities.
I think this is too strong a conclusion. How many of the major data leaks and ransomware attacks exploit memory safety issues? Not many. The bulk of them target misconfigurations, vulnerabilities caused by bad text-based protocols, logic errors in software, and social engineering.
That's not to say memory safety doesn't matter, and you can get very pernicious and subtle bugs when you get too clever in C-based languages. That said, the languages that boast about their memory safety are written in C/C++ (python, ruby, Java, llvm) and run on operating systems that provide process isolation with memory safety written in C/C++ on top of hypervisors which are also written in C/C++.
You can argue, as the article does, that use of C/C++ inevitably results in many memory safety issues, and that therefore we should use memory safe languages. Except this doesn't take into account the entire categories of vulnerabilities that have been entirely eliminated because of good C/C++ abstractions like process isolation, virtual memory, filesystems, tcp-ip, hypervisors, and so on. But we take these luxuries for granted, and the benefits they confer become invisible.
I think there is a much more mundane lesson here. Good abstractions prevent entire classes of vulnerabilities, and bad abstractions are leaky no matter how careful you are. C and C++ are pretty bad languages insofar they give you limited options for building good abstractions, but with careful programming it can be done and much of the best and most reliable and most complex software is written these low level memory unsafe languages and all major security advancements we've actually made in the real world are still implemented in memory unsafe languages.
- jstimpfle 5y ago> I think there is a much more mundane lesson here. Good abstractions prevent entire classes of vulnerabilities This is how I try to write C, in the end there there is very little "unsafe" code in it - few complicated pointer dereferences, few dynamic allocations, almost no transfer of ownership anywhere. No callbacks, and requiring e.g. a ref-counted handle is very rare. Mostly function calls, pointers only valid during function call (or make a copy, e.g. ID strings), creating the data in the module that understands it, using suitable allocation strategies and centralized resource release. Asynchronous messaging instead of hard to follow callbacks (which break the flow of execution). The current code I have has grown to be devoid of dynamic memory allocations simply for performance/latency reasons. It now has good MISRA compliance without ever trying hard. There have been a few bugs (including very silly and obvious concurrency bugs) but due to the app being so "fixed" those have always turned up pretty quickly (so far) and have been easy to spot and fix. For larger projects, I feel like the value of bottled abstractions is more and more decreasing. To connect things in an efficient and maintainable way all these layers have to be unwrapped.
- dcow 5y agoThe Rust compiler essentially automates all this. Nobody is saying you can't write good C. The argument is that the data suggests a memory-safe language eliminates an entire realm of possibilities available in C. This is an attempt to push the general impression out of "hypothetically safe languages are safer" (which tends to be the talking point ad nauseam in language flame wars) to "we've established theory that safe languages empirically result in fewer CVEs by at least 65%". Safe Rust doesn't really let you introduce concurrency bugs either, which you admit show up even in well abstracted C.
- jstimpfle 5y ago> Safe Rust doesn't really let you introduce concurrency bugs either, which you admit show up even in well abstracted C. It was really obvious stuff that was immediately reproduced though. Related to a refactor taking into account some learnings that restricted concurrency almost to a single implementation file. My conjecture is that if code is littered with synchronization primitives, the structure is wrong. A system that automates the painful part of getting the use of synchronization primitives right is possibly rewarding bad structure, at least in the short term.
- dcow 5y agoI think it really depends on the project/application. More often than not you should probably have a framework for handling concurrency (whether you've written it yourself or someone else), sure. But sometimes you find yourself writing/maintaining the framework, too. I've experienced times where, when writing concurrent code, I thought what I should be doing was okay because I would have done the same thing in C but Rust stepped in and said "actually I can't allow you to do that, Dave". I don't know if you've ever experienced something similar but it's pretty awesome when it happens.
- jstimpfle 5y agoI don't disagree, TBH I find stuff like memory models kind of mind bending. Concurrency is easy to get wrong, that's why it might be best to avoid (centralize) it. That's what Golang did I think. I'm not up to date with a lot of the high-tech SMP stuff that is found in e.g. Linux - I'm sure they have a lot of direct memory sharing, I found sth in their Red-black tree for example, and for sure there a lot of spinlocks, schedule calls, and what not. I wonder if there has been a trend of turning back the explicit-synchronization dial a little, even there? It would make sense to me, memory has been becoming slower and slower (in terms of latency not performance, and relative to increasing CPU throughput), and there seems to be a trend for more asynchronous (non-blocking, message passing) stuff like io_uring.
- NotSwift 5y agoFrom An Empirical Study of Vulnerabilities in Cryptographic Libraries[0]: > Among our most interesting findings is that only 27.2% of > vulnerabilities in cryptographic libraries are cryptographic > issues while 37.2% of vulnerabilities are memory safety is- > sues, indicating that systems-level bugs are a greater secu- > rity concern than the actual cryptographic procedures. These libraries were developed by security experts and even they made some serious errors. [0]https://arxiv.org/abs/2107.04940 https://arxiv.org/abs/2107.04940
- pjmlp 5y ago> That said, the languages that boast about their memory safety are written in C/C++ (python, ruby, Java, llvm) and run on operating systems that provide process isolation with memory safety written in C/C++ on top of hypervisors which are also written in C/C++. Not all of them, and it is more a consequence of building on top of existing tooling instead of doing everything from scratch. D was originally implemented in C++, nowadays the reference compiler is pure D. Go was originally implemented in C, nowadays the reference compiler is pure Go. C# and VB.NET were originally implemented in C++, nowadays the compilers are pure C# and VB.NET, while Microsoft keeps porting the runtime from C++ to C#, with each release. Java compilers like JikesRVM, MaximeVM and GraalVM are implemented fully in Java. Just like bringing new parties into power, first accept the existing forces, then rebuilt the system once enough parliament seats have been assured.
- l33t2328 5y ago> that use of C/C++ inevitably results in many memory safety issues, and that therefore we should use memory safe languages. Except this doesn't take into account the entire categories of vulnerabilities that have been entirely eliminated because of good C/C++ abstractions like process isolation, virtual memory, filesystems, tcp-ip, hypervisors, and so on. I don’t see your point here. Yes, C/C++ abstractions like process isolation, virtual memory, etc. are good, but languages like Rust don’t eliminate them.
- easterncalculus 5y ago> The bulk of them target misconfigurations, vulnerabilities caused by bad text-based protocols, logic errors in software, and social engineering. Unfortunately, often these are not called "vulnerabilities", or rather when people talk about "vulnerabilities" they are referring to bugs like these which are not often the main attack vectors used in real data breaches. This is a semantic terminology thing and not really useful to most people, and is part of the reason why the conclusion is a little overblown, because even though it might cut down on the number of CVEs, the reality is that it probably won't have much impact on the amount of data breaches and ransomware attacks. It's much more commonly started by phishing and with less frequency well-known vulnerabilities of all classes - memory corruption being only a fraction of that fraction. It's just not super relevant to security anymore, at least in comparison to what is costing people billions of dollars a year.
- pclmulqdq 5y agoUnfortunately, CVEs come up when security researchers find something interesting to publish, whereas actual breaches usually come from a hacker exploiting some sysadmin's poor configuration.
- babatuba 5y ago> C and C++ are pretty bad languages insofar they give you limited options for building good abstractions Which abstractions can you not create in C++? The only clumsy abstraction I can think about is algebraic data types—and C++ is not a functional language. C++ has an extremely powerful type system for any abstraction you can imagine. But that is also part of the problem :) Personally, I think C is a better language for lower level development, as it is so simple that upon creating well established practices they are much easier to follow. The idea that codebases become over 10 million lines of code in each of these cases maybe is a sign that there are other architectural issues of scalability. I'd be curious to compare something like OpenBSD and look at _WHY_ those codebases have less vulnerabilities? I think there's a lot more to this than language choice. Change velocity is of course one of them—maybe we need to slow down? It looks like OpenBSD had only 1 vulnerability last year: https://stack.watch/product/openbsd/openbsd/ https://stack.watch/product/openbsd/openbsd/ I would like to see a simple language like C with Rust memory safety guarantees. These modern languages literally try to shoe-horn EVERY feature from EVERY language so they can appeal to the lowest-common-denominator. But what do you get with that? A systems-level Java?