|
|
Subscribe / Log in / New account

Too much kool-aid

Too much kool-aid

Posted Feb 12, 2025 9:14 UTC (Wed) by alx.manpages (subscriber, #145117)
In reply to: Too much kool-aid by mirabilos
Parent article: Maintainer opinions on Rust-for-Linux

Indeed.

Buffer overflows in user-space tends to be one of the most dangerous things. Because other bugs rarely grant permissions to an attacker.

But in a kernel, or in a setuid root program, logic errors can be as bad as any UB. Toggling a conditional without triggering UB can similarly result in granting permissions. If jumping to a new language completely kills the memory classes of bugs (and while it may significantly reduce them, it cannot kill them all) but can reintroduce subtle logic errors, we're not much better. Plus, all the churn makes it impossible to analyze where and why the bug was introduced.

On the other hand, with good APIs, one can write C code which is theoretically not memory-safe, but which is hardened enough that such bugs will be rare, and with these, the logic bugs will also be rare. Overall, I think C is still a safer language than Rust, even if it can theoretically have more buffer overflows.

I do think Rust is a good experiment, in order to test ideas that might be later introduced in C. I agree with other commenters that old C programmers were too reticent to improving the language in necessary ways (e.g., killing 0 as a null pointer constant), and maybe the Rust pressure has allowed us to improve C.


to post comments

Too much kool-aid

Posted Feb 12, 2025 15:33 UTC (Wed) by taladar (subscriber, #68407) [Link] (3 responses)

> On the other hand, with good APIs, one can write C code which is theoretically not memory-safe, but which is hardened enough that such bugs will be rare, and with these, the logic bugs will also be rare. Overall, I think C is still a safer language than Rust, even if it can theoretically have more buffer overflows.

We literally have 50 years of proof that there is a wide gap between theory and practice. The "sufficiently disciplined/diligent/... programmer" model has just failed us and it is time to admit that maybe, just maybe, 20 years into the development of programming languages was not yet the time when the perfect language emerged.

Too much kool-aid

Posted Feb 12, 2025 15:46 UTC (Wed) by alx.manpages (subscriber, #145117) [Link] (2 responses)

I fully agree that K&R C isn't a great language today. But GNU C2y is far from being K&R C.

Plan9 was also better than Unix in many ways, and we still use a Unix clone today. We have adapted it with the ideas of Plan9 (e.g., proc(5)). Plan9 was a useful experiment, just like Rust is useful today to backport improvements into C.

Linux is far from being a Unix V7/BSD/SysV clone, let alone Unix V1, just like GNU C2y isn't K&R C anymore.

Too much kool-aid

Posted Feb 12, 2025 20:20 UTC (Wed) by jmalcolm (subscriber, #8876) [Link] (1 responses)

Why are we calling it "GNU" C2y?

Unless I misunderstand, C2y is a placeholder for a C standard that does not yet exist. So, it is a bit of a weird place to make the argument around C maturity from to start with. I think C2y is expected to become C26 but it could easily be C27 or C28 (in 2028). It could be never. Being a "future" standard, the reference also supports the other side of the argument regarding the CURRENT state of the C language.

But, if that is what we mean by GNU C2y, I should point out that Clang has a C2y flag as well (-std=c2y). C2y is not a GNU standard. If anything, I would expect GNU C2y to refer to only the proposed changes to the current C standard that the GNU compiler has implemented.

How does limiting your reference to the proposed changes in C2y to the subset implemented in GNU software support your argument?

Too much kool-aid? Who are we referring to?

Too much kool-aid

Posted Feb 12, 2025 20:49 UTC (Wed) by alx.manpages (subscriber, #145117) [Link]

By GNU C2y I refer to -std=gnu2y, so a mix of ISO C2y with GNU extensions.

While GCC has not yet merged some changes, there are patches for them which will likely be available in the next version of the compiler. Most of those changes will be backported to older dialects (so available if you specify -std=gnu17), so while they're not written in stone in the standard, and are not already available in GCC, they will be very soon available in all GNU dialects, as *stable* features.

Too much kool-aid

Posted Feb 12, 2025 20:42 UTC (Wed) by roc (subscriber, #30627) [Link] (12 responses)

> Overall, I think C is still a safer language than Rust, even if it can theoretically have more buffer overflows.

Is this bait? There is ample real-world evidence to the contrary, too much to even cite here, but you can start by comparing the CVE record for rustls vs OpenSSL.

Mass-rewriting of C into Rust might introduce a few logic errors. It is likely to eliminate more, since Rust provides powerful tools for avoiding logic errors, newtypes and the Result type, that are infeasible in C. And if you choose Rust instead of C for new code (e.g. new kernel drivers), the logic error advantage of Rust is clear.

Too much kool-aid

Posted Feb 12, 2025 21:12 UTC (Wed) by alx.manpages (subscriber, #145117) [Link] (11 responses)

The fact that you're allowed to write unsafe code in C doesn't mean that there aren't subsets of the language that inherently prevent certain mistakes.

I don't know what C dialect is used by OpenSSL, but I looked at a random file in their source code, and immediately identified some less-than-ideal patterns. Also, the language isn't enough; you also need to design non-error-prone APIs, which is something that no tool can help you with (at least not enough).

That Rust defaults to not allow certain things is nice. We should severely restrict what is allowed in modern dialects of C.

Here's the example of unsafe code I identified in OpenSSL:

<https://github.com/openssl/openssl/blob/6f3ada8a14233e76d...>

```
ret = OPENSSL_zalloc(sizeof(*ret))
```

A better API (only implementable as a macro) would ask for a number of elements and a type:

```
ret = XXX_ZALLOC(1, OSSL_COMP_CERT);
```

Here's an example of such an API:
<https://github.com/shadow-maint/shadow/blob/master/lib/al...>

And here are the commits that added such an API, which document the kind of improvements it adds:
<https://github.com/shadow-maint/shadow/commit/6e58c127525...>
<https://github.com/shadow-maint/shadow/commit/09775d3718d...>

Too much kool-aid

Posted Feb 12, 2025 21:43 UTC (Wed) by mb (subscriber, #50428) [Link] (1 responses)

Your comments very much reads like AI generated.

No, you're not talking to a random text generator

Posted Feb 12, 2025 23:05 UTC (Wed) by alx.manpages (subscriber, #145117) [Link]

> Your comments very much reads like AI generated.

It is not, if you're asking that. I considered not responding, because your comment looked plausibly trolling, but I think I should respond, in case your comment was honest.

Signed-off-by: Alejandro Colomar <alx@kernel.org>

Too much kool-aid

Posted Feb 13, 2025 4:48 UTC (Thu) by roc (subscriber, #30627) [Link] (8 responses)

> Also, the language isn't enough; you also need to design non-error-prone APIs, which is something that no tool can help you with (at least not enough).

Rust helps with this because you have to encode ownership and thread-safety information in the API. E.g.

fn new_blagh(s: &str) -> Blagh
vs
Blagh new_blagh(char* s);

In the Rust API, unlike the C API:
* The callee can be sure that `s` won't be modified by another thread while `foo` is running
* The callee can be sure that it is not responsible for freeing `s`
* The callee understands that if `Blagh` contains part of `s` then it needs to copy that data into `Blagh`
* The caller can be sure that the returned object does not depend on `s` being kept alive
* The caller can be sure that it retains ownership of `s`
* The caller can be sure that it has exclusive ownership of `Blagh`, i.e. nothing depends on it keeping `Blagh` alive
Of course Rust not only forces you to write these critical properties into the code, it also checks that the caller and callee maintain them.

And in Rust you can go much much further towards making APIs difficult to misuse. For just one example see how rustls's API prevents certain kinds of configuration errors: https://docs.rs/rustls/latest/rustls/struct.ConfigBuilder...

Too much kool-aid

Posted Feb 13, 2025 10:15 UTC (Thu) by alx.manpages (subscriber, #145117) [Link] (7 responses)

> Rust helps with this because you have to encode ownership and thread-safety information in the API.

I only work with single-threaded projects at the moment. That aspect is not very appealing to me at the moment.

> * The callee can be sure that it is not responsible for freeing `s`

Consistent use of the [[gnu::malloc(free)]] attribute can help with that too.

---

Look, Rust does have very good ideas. I don't claim it doesn't. But:

- You can improve your C code's safety significantly just by designing good APIs and self-limiting to a subset of the language.

- As a longer-term goal, you can probably add those Rust features to C.

In the end, a safe language is a language that prevents you from accidentally granting rights to an attacker.

You may call it luck, but I have been refactoring shadow-utils at a very high rate (including complaints by packagers that were worried that such rate of churn would introduce security vulnerabilities almost certainly) for quite a few years already. So far, I have introduced 0 remote holes in a heck of a long time (at least, for what we know). The code is now significantly safer than it was before I started. The more I refactor it, the safer I feel when doing so. You just need to follow some rules, and at least you'll have a hard time introducing a vulnerability. It's not impossible, but it's all a compromise.

I know the language so damn well that that offsets the theoretical benefits that Rust could give me. People talk their mother tongue better, even if it's significantly more complex than other languages, because they know it by heart. They say Norwegian is similar to English but simpler (and thus easier), but we speak English because we already know it. Would it be better if there was a big-bang change in the world to make Norwegian the global language? Maybe it would help learners in the long term, but we'll agree that it's not a good idea. The same holds for Rust and C, IMO.

Plus, for a setuid-root set of programs (which is what I'm mainly working on at the moment, apart from the Linux man-pages project), a logic error is as bad as a buffer overflow. If I toggle a conditional and grant root privileges to a random user in su(1), I've screwed as badly as if I would have caused the worst UB. That also diminishes the reasons for using Rust, _in my case_.

Too much kool-aid

Posted Feb 14, 2025 23:33 UTC (Fri) by mathstuf (subscriber, #69389) [Link] (6 responses)

> I know the language so damn well that that offsets the theoretical benefits that Rust could give me.

I hope your projects survive you moving on. Projects using arcane knowledge to hold themselves up are at risk of becoming like one of the `roff` implementations (`nroff`?): inscrutable to even the other Unix prophets so as to be left alone after the original author's untimely end[1].

[1] At least if my memory of a BSD podcast which interviewed Bryan Cantrill where it was mentioned is accurate.

C arcange knowledge, bus factor

Posted Feb 14, 2025 23:45 UTC (Fri) by alx.manpages (subscriber, #145117) [Link]

> I hope your projects survive you moving on. Projects using arcane knowledge to hold themselves up are at risk

That's a valid concern. I try to educate the other co-maintainers and regular contributors on those matters. But I should be more careful on that effort, just in case.

Too much kool-aid

Posted Feb 15, 2025 23:40 UTC (Sat) by mirabilos (subscriber, #84359) [Link] (4 responses)

I’ll have you know I’m using AT&T nroff (under the Caldera licence) and in the process of bringing it sufficiently up to standards that I can build it with newer GCC to run UBSan and Valgrind on it and already found and fixed some issues, yielding quite the speed-up as well.

J�rg Schilling (rip.) also used to maintain a fork, similarily.

Too much kool-aid

Posted Feb 17, 2025 7:32 UTC (Mon) by mathstuf (subscriber, #69389) [Link] (3 responses)

Good to hear it's being tackled! Looking at the source code I found[1], it does look quite hairy, but not completely inscrutable.

Here's the source of my claim as well: https://www.youtube.com/watch?v=l6XQUciI-Sc&t=5315s

[1] https://9p.io/cm/cs/who/bwk/toolsbook/

Too much kool-aid

Posted Feb 17, 2025 21:23 UTC (Mon) by mirabilos (subscriber, #84359) [Link] (2 responses)

I have no idea what programming language that even is. (I know there’s also a version in Limbo, for Inferno…)

No, we’re talking about the 32V-based one.
https://mbsd.evolvis.org/cvs.cgi/src/usr.bin/oldroff/nroff/ still shows some of the horrors.

Too much kool-aid

Posted Feb 17, 2025 21:55 UTC (Mon) by excors (subscriber, #95769) [Link] (1 responses)

That appears to be Ratfor, which is a Fortran preprocessor that lets you use more C-like syntax. (Ratfor was developed by Brian Kernighan and based on Dennis Ritchie's C, before they became K&R.)

Too much kool-aid

Posted Feb 17, 2025 22:42 UTC (Mon) by mirabilos (subscriber, #84359) [Link]

Ah! I heard of it but have never seen it. Thanks!


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds