Memory safety CVEs differ between Rust and C/C++

nicoburns1 pts0 comments

How memory safety CVEs differ between Rust and C/C++ | Kobzol’s blog

CVE is a database used for categorizing and reporting security vulnerabilities in software. There<br>are various kinds of vulnerabilities that can be reported. Some of them are caused simply by bugs<br>in the program logic (like a recent CVE reported in Cargo), but some of the most nasty<br>ones are caused by memory unsafety, which can easily lead to exploits. In this post I want to focus<br>on the latter kind of CVEs, how they are reported, especially in libraries, and how it differs<br>between Rust and C or C++.

Because sometimes I see people online who compare the number of CVEs in Rust and C/C++ software, which<br>tends to be accompanied by claims about Rust not being really memory safe or not being worth<br>adopting when CVEs can still exist in it. And sometimes I also observe similar views when I teach Rust<br>to programmers who are used to programming in C or C++.

Now, anyone is, of course, free to do such comparisons, and make their own conclusions based on it. But I think that there is an important difference in how potential vulnerabilities related to memory safety are treated in Rust and C/C++, which might not be obvious at first, especially if you don’t know how Rust works. I’d like to explain that in this post.

But first, I should clarify that it is absolutely possible to cause memory unsafety bugs and undefined<br>behaviour in Rust. In the vast majority of cases1, the unsafe keyword is required for<br>this to happen, but anyone who claims that Rust programs cannot experience UB at all is simply incorrect.<br>It is also perfectly possible to cause general vulnerabilities (meaning those unrelated<br>to memory unsafety) in Rust. Forgetting to add a check that your admin dashboard is only accessible to admins can happen in any language, after all.

And yet, there is something very different between potential vulnerabilities in Rust and C or C++, which is<br>related to the core reason of why Rust is actually much more memory safe in practice than C<br>or C++. I’ll try to demonstrate it on the curl networking library, which is written in C.

Potential vulnerability in curl?

(lib)curl is one of the most used and well-maintained open source libraries in the world. Its primary<br>developer, Daniel Stenberg, is one of the most prolific open source maintainers of our time,<br>and together with many other people, he has been dilligently improving this library for the past 30 years.<br>Despite having to deal with a recent avalanche of CVEs found by LLMs,<br>he and his collaborators are doing a very good job of keeping curl safe from potential exploits and vulnerabilities,<br>and they take pride in curl being a very robust piece of software.

So, let’s take that to the test, shall we? I opened the documentation<br>of libcurl and found the first function I saw that accepts an argument, curl_getenv. This is supposed to be a simple function that provides a portable<br>abstraction for getting the value of an environment variable across different operating systems.<br>curl is supposed to be safe and robust, so surely this function doesn’t contain any UB or memory unsafety, right?<br>So what about the following C program?

#include

int main(void) {<br>curl_getenv(NULL);

This 5-line C program is as simple as it gets, it just calls the curl_getenv function with a<br>NULL pointer argument, and compiles without any warnings. And yet, when you execute it, you (might)<br>get a segfault, and thus a memory safety bug, and thus a potential vulnerability/exploit:

$ gcc test.c -otest -lcurl -Wall -Wextra<br>$ ./test<br>Segmentation fault (core dumped)

Of course, this program is artificially simple, but that’s kind of the point. In practice, situations<br>like this can (and do) easily happen in larger programs by accident all the time.

Huh. So maybe curl isn’t so safe after all? Should I go and report this as a vulnerability in curl?!

No, of course not. That would be stupid. I know that, you know that. But how do we actually know it?<br>That’s the interesting part.

Consider a very similar program that would call the function like this: curl_getenv("FOO"). What if<br>that program would still segfault, and thus contain a potential vulnerability? I am sure that the curl<br>maintainers would like to know about that happening, and would consider it to be a pretty big issue if I reported it! At the same time, I’m sure that they would (rightfully) tell me off if I reported the first program as a vulnerability in curl. Yet those two programs differ only by so little.

So, what gives? Well, in practice, UB like the one in my original example is said to be caused by “wrong usage”2, and it is not considered to be an issue in the library or API that I am using, but in my (application)<br>code. This is done mostly for the following two reasons:

In C, it is often not possible to specify the contract (invariants, preconditions,<br>postconditions, etc.) of APIs precisely3 due to its limited type system, and library authors often<br>don’t bother describing all...

rust memory curl program cves vulnerabilities

Related Articles