|
|
Subscribe / Log in / New account

Downsides of C language culture?

Downsides of C language culture?

Posted Aug 23, 2024 7:45 UTC (Fri) by taladar (subscriber, #68407)
Parent article: A review of file descriptor memory safety in the kernel

> Overall, Viro's report shows the kernel to be in a good state. Most of the places where struct fd is used have no problem. One of the exceptions is overlayfs, which uses the fd structure not only to indicate "non-reference-counted file", "reference counted file", or "empty", but also various errors. struct fd is not meant to store errors, and overlayfs's use gets in the way of some of Viro's follow-up work.

I can't help but feel that this sort of thing would just never happen culturally in a language like Rust which emphasizes correctness and clean abstractions even if it is technically possible to do so too.


to post comments

Downsides of C language culture?

Posted Aug 23, 2024 12:01 UTC (Fri) by pizza (subscriber, #46) [Link] (25 responses)

> I can't help but feel that this sort of thing would just never happen culturally in a language like Rust which emphasizes correctness and clean abstractions even if it is technically possible to do so too.

Feel free to go back in time and release current bleeding-edge Rust 35 years ago, in a form that is capable of running on 40-year-old commodity hardware/OSes.

Downsides of C language culture?

Posted Aug 23, 2024 12:06 UTC (Fri) by fishface60 (subscriber, #88700) [Link] (24 responses)

I don't think this was meant to criticise how things got how they are, more that future Rust rewrites could eliminate this class of bug eventually.

Downsides of C language culture?

Posted Aug 23, 2024 12:18 UTC (Fri) by pizza (subscriber, #46) [Link] (18 responses)

> I don't think this was meant to criticise how things got how they are, more that future Rust rewrites could eliminate this class of bug eventually.

...That is a very naive assumption.

When you make your tent bigger to include more folks, the collective culture _will_ change.

(And, incidentally, as long as Linux is a C project with Rust bolted to it, as opposed to a Rust project with lots of C bolted to it, that is not going to change)

...Personally, I find "Rust Culture" incredibly sanctimonious and off-putting. Naturally, much like Agile, that can only be because I'm ClearlyDoingItWrong.

Downsides of C language culture?

Posted Aug 23, 2024 14:09 UTC (Fri) by pbonzini (subscriber, #60935) [Link] (1 responses)

Even if Rust is bolted on the side, the type system can prevent certain bugs in Rust code. Of course it's unlikely that Rust will ever be a majority of Linux code, and that's not a goal at all. But if at some point there will be no reason to write a new driver in C, that will be something.

Downsides of C language culture?

Posted Aug 23, 2024 14:50 UTC (Fri) by pizza (subscriber, #46) [Link]

> But if at some point there will be no reason to write a new driver in C, that will be something.

...In other words, Linux becomes a Rust project with a large pile of legacy/still-necessary C bolted onto it. [1]

Because "But Rust is optional!" only applies if a driver or subsystem *you* need is Rust-only.

Rust-first (and eventually, Rust-only) is the _only_ logical outcome/goal of this entire exercise. [2]

[1] My understanding is that this is already technically possible, at least for some subsystems. However, it is not (yet) "culturally" acceptable.

[2] From Linux's perspective, that is. From Rust's perspective, this exercise has lead to improvements to the core language, tooling, and various libraries.

Downsides of C language culture?

Posted Aug 24, 2024 19:31 UTC (Sat) by ringerc (subscriber, #3071) [Link] (15 responses)

What I'm struggling with is

"I want/need X"

"Rust can't do X so what you want/need is wrong, stop wanting/needing it".

Downsides of C language culture?

Posted Aug 24, 2024 21:07 UTC (Sat) by intelfx (subscriber, #130118) [Link]

> What I'm struggling with is
> "I want/need X"
> "Rust can't do X so what you want/need is wrong, stop wanting/needing it".

Yes, this is unfortunately one of the themes quite prevalent in the Rust community/culture.

Downsides of C language culture?

Posted Aug 26, 2024 11:42 UTC (Mon) by taladar (subscriber, #68407) [Link] (13 responses)

It is less that Rust can't do what you want, in many cases it is more a matter of people trying to bring their idioms from other languages to Rust (that is not a uniquely Rust problem btw) and then complaining that doing it that way won't work. That exact same problem happened 10-15 years ago when everyone was trying to apply Java OOP design patterns to languages that didn't even have OOP and had very different idioms to Java.

Downsides of C language culture?

Posted Aug 26, 2024 12:08 UTC (Mon) by pizza (subscriber, #46) [Link] (12 responses)

> It is less that Rust can't do what you want, in many cases it is more a matter of people trying to bring their idioms from other languages to Rust [...]

Well, sure, but those other languages aren't trying to sell themselves as "encompassing C's use cases" which implies that various necessities are supported. [1]

> and then complaining that doing it that way won't work.

No, the complaint is not that "<X> won't work"; it's being sanctimoniously told "you don't need to accomplish <X> at all".

[1] One year into the the Rust-on-Linux experiment, it _still_ depends on bleeding-edge toolchains and non-stable features. Which is an improvement from requiring out-of-tree patches, but clearly it is not yet a universal replacement for C.

Downsides of C language culture?

Posted Aug 26, 2024 12:19 UTC (Mon) by mb (subscriber, #50428) [Link] (4 responses)

The kernel always required a special C compiler with special non-standard features (gcc).
The standard compliant C compiler llvm was not able to compile the kernel until it also gained additional features (and the kernel was modified as well).

And now Rust also needs to get some more special features for Linux.
So what?

I don't see how on earth this could be *any* hint as to whether Rust is "clearly [..] not yet a universal replacement for C" or not.

And there are other operating systems implemented in Rust.

Downsides of C language culture?

Posted Aug 26, 2024 12:42 UTC (Mon) by pizza (subscriber, #46) [Link] (3 responses)

> And there are other operating systems implemented in Rust.

Good for them. But they don't have the same requirements/features as Linux. And they certainly didn't have approximately eleventy bajillion lines of existing code, with more LoC changing on every release than these "RustOSes" have in their collective (and combined) codebases.

Mind you, I'm not holding Linux up as some holy untouchable artifact here -- But when your sales pitch is "It can do everything you need, only better!" it's incumbent on you to actually make good on that claim instead of moving the goalposts, okay?

It is the hight of hubris to believe that RustCulture(tm) will remain dominant when the TrueBelievers of Lake Woebegone [1] are diluted to homoeopathic levels.

[1] Where all the women are strong, all the men are good-looking, and all the developers are above-average.

Downsides of C language culture?

Posted Aug 26, 2024 12:59 UTC (Mon) by mb (subscriber, #50428) [Link] (2 responses)

Linux is not implemented in standard C.
And Rust never claimed to be "universal replacement for Linux Kernel C".

>it's incumbent on you to actually make good on that claim

ridiculous

Downsides of C language culture?

Posted Aug 26, 2024 13:07 UTC (Mon) by pizza (subscriber, #46) [Link] (1 responses)

> Linux is not implemented in standard C.

As khim and other folks here are so quick to point out, pretty much nothing is implemented in purely "standard" C.

But if you're going to play that card, after many years of work, there are multiple versions of two completely independent toolchains that can be used to compile modern Linux. But only one Rust toolchain. One _version_ (ie the latest at that time) of the only extant Rust toolchain.

Not exactly a good argument to be making.

Downsides of C language culture?

Posted Aug 26, 2024 14:24 UTC (Mon) by intelfx (subscriber, #130118) [Link]

> But if you're going to play that card, after many years of work, there are multiple versions of two completely independent toolchains that can be used to compile modern Linux. But only one Rust toolchain. One _version_ (ie the latest at that time) of the only extant Rust toolchain.
>
> Not exactly a good argument to be making.

As you correctly say, it took the C codebase (and C toolchains) **many years of work** to get to this point. And it's still not "standard C" — it's still a pile of documented, non-documented and semi-documented extensions that only recently ended up being supported by another toolchain besides GCC.

And now a new contender (Rust) appears and in just a few months people are asking it to clear the bar that literally nothing else is held to?

I'm not a believer of the Church of Rust, far from it, but this line of argumentation is ridiculous (and disingenuous).

Downsides of C language culture?

Posted Aug 26, 2024 12:33 UTC (Mon) by ringerc (subscriber, #3071) [Link] (6 responses)

> No, the complaint is not that "<X> won't work"; it's being sanctimoniously told "you don't need to accomplish <X> at all".

This. Or you're wrong for wanting to.

It gets even better when the capabilities of the language/toolchain improve so you can now accomplish<X> ... and now it's ok, you're allowed to want to now.

The Rust community is far from unique in this, to be clear, but it's still very frustrating.

Downsides of C language culture?

Posted Aug 27, 2024 18:41 UTC (Tue) by Wol (subscriber, #4433) [Link] (5 responses)

But is this an "X & Y" problem (or whatever it's called)?

Where X is *your* *perceived* solution, and the actual problem is Y?

Are you fixated on your perceived solution (X), or do you actually want to solve the real problem (Y)? Because X may just be a very bad fit to the language, which has a *different*, totally acceptable, solution to Y.

Certainly I get the impression that the Rust designers may be aggressive in asking "Why do you want X?" But that's because they want to understand what Y is, and provide a solution, just not necessarily the X solution.

Cheers,
Wol

Downsides of C language culture?

Posted Aug 27, 2024 19:42 UTC (Tue) by pizza (subscriber, #46) [Link] (3 responses)

> But is this an "X & Y" problem (or whatever it's called)?
> Where X is *your* *perceived* solution, and the actual problem is Y?

No.

> Are you fixated on your perceived solution (X), or do you actually want to solve the real problem (Y)? Because X may just be a very bad fit to the language, which has a *different*, totally acceptable, solution to Y.

The determination of Y being "totally acceptable" (or even _equivalent_) is not up to the Rust evangelists.

Downsides of C language culture?

Posted Aug 28, 2024 7:33 UTC (Wed) by taladar (subscriber, #68407) [Link] (2 responses)

On the other hand the determination that X is not an acceptable solution is usually based on 50+ years of evidence of C programs having giant security holes or recurring types of bugs because C programmers insist on solving Y by doing X.

Downsides of C language culture?

Posted Aug 28, 2024 10:50 UTC (Wed) by ringerc (subscriber, #3071) [Link]

There are absolutely legitimate reasons to say "we intentionally don't support [X] and think it's a terrible idea; these features provide other ways to solve the same underlying problems without the same hazards."

And sometimes those other ways come with compromises that don't suit everyone. Which is also ok so long as fans of the tool (like Rust) are willing to say "ok, it doesn't look like Rust is a good fit for your specific use case right now."

It becomes a problem when the story is then "this is the only way, if this way conflicts with other constraints you have you need to remove the other constraints and do it our way because that's the one right true way".

Even if it's 10x the time and development effort or mountains of boilerplate, or has a huge runtime performance penalty unacceptable in the use case etc.

For example, as a big postgres fan and sometimes postgres contributor, when someone asks me how to embed Postgres in their application I'll say "you probably shouldn't, there are other DBs that are much more suitable for embedding in apps. You can kind of do it with postgres but it'll be more fragile and harder for the user to back up, run, update and migrate your app. You can probably just use SQLite."

I won't tell them "embedding a DB in an app is fundamentally wrong, educate your users about properly installing and managing a RDBMS and it's backups, rhen have them configure your app to connect to a postgres they install themselves."

Just because postgres is a bad choice for in-app embedding doesn't mean it's wrong to want to embed a DB in your app.

But I've seen this sort of thing a lot, and definitely not just from rust, go, Python, postgres, or any other community. It's especially funny when the tool in question gains a new feature that makes the use case not suck with that tool and now it's ok, when cool, to want to do it when before it was consider a terrible idea irrespective of what tool you used.

Downsides of C language culture?

Posted Aug 28, 2024 12:42 UTC (Wed) by pizza (subscriber, #46) [Link]

> On the other hand the determination that X is not an acceptable solution is usually based on 50+ years of evidence of C programs having giant security holes or recurring types of bugs because C programmers insist on solving Y by doing X.

Since you're making sweeping generalizations, here's one more.

Folks advocating for Y are quick to hype theoretical _benefits_, but completely (and conveniently) ignore its _cost_, be it up front (ie initial implementation), ongoing (maintenance), and at runtime (eg performance, UX, etc)

Downsides of C language culture?

Posted Aug 28, 2024 10:36 UTC (Wed) by ringerc (subscriber, #3071) [Link]

Yes this can absolutely be the case.

I've been on the other side at times telling people "no, this isn't how to approach this problem," "this tool works best using a set-based rather than iterative formulation", "this isn't the right tool to solve your problem". I've also done a lot of walking people back from "I want to do X" until we get to "I want to solve problem Y" then forward again to find effective solutions without their assumptions and preconceptions.

So I get it.

And yes sometimes I too have said "dear God no you don't want to do that and here's why". By which I mean "if you attempt this you are in for a world of pain and slow failure."

But I do my best not to tell people that they're wrong for wanting to solve a problem at all. Or that the tool I'm help them with is unsuitable for their particular problem right now.

The real trouble arises when all problems are reframed around the tool's capabilities.

You don't want dynamic loading of functionality (because golang doesn't/didn't do that), decouple it via gRPC services and immutable containers because it's Just Better(TM). You don't ever want to use dynamic key/value data in relational DB because it's fundamentally wrong, stop wanting to do that (unless your RDBMS has dymaic set types or something in which case you're allowed to want it for appropriate use cases). The list goes on.

Downsides of C language culture?

Posted Aug 23, 2024 14:21 UTC (Fri) by viro (subscriber, #7872) [Link] (4 responses)

You do realize that "future Rust rewrites" would have to do exact same kind of work, don't you? Unless you believe in Sapir-Whorf bollocks to truly breath-taking extent, that is...

Downsides of C language culture?

Posted Aug 23, 2024 17:16 UTC (Fri) by NYKevin (subscriber, #129325) [Link] (3 responses)

I don't think anyone is claiming that Rust is a free lunch. My understanding of the argument is more along the following lines:

* This general category of work has to be done (because otherwise, your code is buggy).
* In Rust, the compiler can enforce that you either do it correctly, or pinky swear that you've done it correctly for this specific line/block of code (i.e. you have to write unsafe).
* In C, the compiler does help you to some extent, but it will not outright fail to compile if you miss a spot or do something wrong.
* Rust doesn't reduce the amount of work that needs to be done, but it does make it easier to confirm that you've done all of the work you wanted to do.
* Arguably, Rust does slightly increase the amount of work to be done, because you probably need to implement some kind of typestate API to enforce correctness, and that is probably more complex than an idiomatic implementation in C would be. But you only have to do this once (per API that you want to protect), and typestates are not especially hard to implement (in Rust). So, assuming lots of callsites that need to be checked for correctness, this is an acceptable tradeoff.

Downsides of C language culture?

Posted Aug 23, 2024 19:33 UTC (Fri) by viro (subscriber, #7872) [Link] (2 responses)

Not the point. I don't give a rat's arse for advocacy and culture wars of any description. Language is a tool; it might be more or less convenient to express some things, but let's not dive into the linguistic relativity nonsense - it does *not* shape ones thoughts. If you are unable to separate the concepts from specific syntax, you simply do not understand the language in question.

Rust type system is interesting in some respects; in any case, C type system is pretty weak. Memory safety is obviously a desirable property of program (and it's a property of program, not of a language), and so are correctness proofs in that area. And automating some parts of those proofs is obviously useful - to an extent determined by how good your build coverage is, which is a bloody serious caveat for the kernel. The hard part is to find out _what_ to verify. And that is language-independent; you need to reason about the things done by the program to come up with invariants and predicates that need to be verified. And if you end up with "OK, it's actually safe here, but the reasons are seriously convoluted", you need to come up with some way to massage the damn thing to make the proof of safety more straightforward, etc.

What's more, you need to be able to follow the proof; without that "compiler will catch any violations" is worse than useless when it comes to the changes you (or somebody else) will be doing several years down the road. If compiler warnings become a black box, or worse, an oracle to be appeased, you are fucked; cargo-culting will follow, and you'll find out that memory safety is not the only thing that can go wrong in code where nobody can tell you why such and such thing is done.

Choice of syntax, etc., to be used for automating the verification is secondary. "It wouldn't be needed with Rust" is asinine - the PITA would be reordered, but it would still be there. All of it. Including coming up with sane semantics for objects, figuring out how to use them safely, etc. And you would not even get the benefit of having all of that done upfront, before there's enough users of that thing to make things painful - even leaving aside the question of how much of a benefit it is, imagine a perfectly memory-safe set of primitives. Refcounted struct file, fget() taking an integer and returning a cloned reference or none and fput() dropping a reference. Memory safety is obviously not an issue for users of that API; descriptor table modifications need to play safe wrt fget(), but that's also not hard to do. All of that is perfectly doable in Rust. Now, at some point somebody points you to noticable overhead on real-world loads, with cacheline ping-pong on refcount modifications found to be contributing a lot.

Now, you notice that considerable part of that could be handled by a switch from cloning to borrowing. Again, perfectly fine for Rust, innit? Except that then you need to figure out how many of the existing users of old API could be converted to the new one and what discipline is needed to keep the things safe afterwards. And _that_ will take exact same kind of analysis. On codebase already in Rust.

Downsides of C language culture?

Posted Aug 24, 2024 0:39 UTC (Sat) by roc (subscriber, #30627) [Link]

> Now, you notice that considerable part of that could be handled by a switch from cloning to borrowing. Again, perfectly fine for Rust, innit? Except that then you need to figure out how many of the existing users of old API could be converted to the new one and what discipline is needed to keep the things safe afterwards. And _that_ will take exact same kind of analysis. On codebase already in Rust.

It all depends on how much of the API's rules can be enforced by the Rust type system. If all of them, then converting users to the new API is a lot easier than with C: just try a mechanical replacement; if the compiler is OK with it, you're done, and the compiler will keep things safe afterwards too. If none of them are, then you're not much better off than with C. If some of them are, you benefit commensurably.

A similar example that I have personally experienced a lot is using Rayon to parallelize loops, which in many cases is as simple as "replace `iter()` with `par_iter()`; if it compiles, then there are no data races, and in practice it will almost always work".

Downsides of C language culture?

Posted Aug 28, 2024 3:37 UTC (Wed) by NYKevin (subscriber, #129325) [Link]

> Not the point. I don't give a rat's arse for advocacy and culture wars of any description. Language is a tool; it might be more or less convenient to express some things, but let's not dive into the linguistic relativity nonsense - it does *not* shape ones thoughts. If you are unable to separate the concepts from specific syntax, you simply do not understand the language in question.

Frankly I do not understand why this is written in response to my comment. I did not make any of the claims you are rebutting, and I explicitly positioned Rust as a tool for solving problems, not an ideology.

> What's more, you need to be able to follow the proof; without that "compiler will catch any violations" is worse than useless when it comes to the changes you (or somebody else) will be doing several years down the road. If compiler warnings become a black box, or worse, an oracle to be appeased, you are fucked; cargo-culting will follow, and you'll find out that memory safety is not the only thing that can go wrong in code where nobody can tell you why such and such thing is done.

Well... this depends on what we're talking about.

For the borrow checker, the rules are pretty well defined (object must outlive references to them, mutable references may not alias anything, shared references guarantee immutability). It is not always easy to understand how the compiler is able to enforce these rules, true, but the rules themselves are very clear to everyone. If you find yourself writing unsafe code, you should know exactly what invariants you are expected to uphold (or else you should have another read of the nomicon before trying to write unsafe code). And if you don't write unsafe code... then it's not your problem in the first place.

For typestate APIs, it's usually as simple as "the foo() function needs an object of type A, you have an object of type B, so you can't call foo() until you call something else that turns Bs into As, and then you can't call anything that takes a B anymore." I'm struggling to imagine how that logic would become difficult to follow. It's just a state machine with extra type safety.

Downsides of C language culture?

Posted Aug 23, 2024 14:07 UTC (Fri) by viro (subscriber, #7872) [Link] (5 responses)

_Which_ sort of thing? disjoint union of cloned refs/borrowed refs/none? Really? And here I thought that Rust had a type system that could express that...

Or do you mean that all abstractions must be there from the very beginning? I'm not fond of Rust as a language, but I think you are doing it a disservice here...

Seriously, if you want to use that thing for kernel work, you'd better be ready to do that sort of analysis, again and again. Figuring out the memory safe abstractions that can express something existing instances could be massaged into, that is. _NOT_ the "oh, we have something that could express the toy cases we'd been able to think of and as for anything else... well, somebody will deal with it somehow - or it can just stay in that legacy stuff and rot" kind of attitude you guys seem to be so fond of.

Downsides of C language culture?

Posted Aug 23, 2024 17:30 UTC (Fri) by NYKevin (subscriber, #129325) [Link] (3 responses)

> _Which_ sort of thing? disjoint union of cloned refs/borrowed refs/none? Really? And here I thought that Rust had a type system that could express that...

This is spelled std::borrow::Cow. Wrap it in Option<T> if you want None as well (which I believe should have no size overhead, because one of the Cow enum variants has a reference in it, and references are non-nullable, so there's a niche the compiler can use for Option layout optimization).

But Cow has its own problems, because it is specifically designed for borrow-checked references. If you want something less restrictive, like refcounted references, then you probably need to use Rc/Arc::make_mut() instead (or one of its sister methods like unwrap_or_clone()).

> Or do you mean that all abstractions must be there from the very beginning? I'm not fond of Rust as a language, but I think you are doing it a disservice here...

In this case, I think the argument is that Rust enforces struct field visibility, so you can't just reach into a Rust struct and fiddle with its members to represent arbitrary states. You would be forced to wrap it in some other struct or enum that describes your additional state data. In practice, you would probably just use Result<T, E> for this use case, because then you get the question mark operator etc. for free.

Downsides of C language culture?

Posted Aug 23, 2024 19:53 UTC (Fri) by viro (subscriber, #7872) [Link] (1 responses)

If you look at the series, you'll see that well over 99% of accesses are fetches of f.file (turned into fd_file(f) in one patch, semi-automatically); what remains is about a dozen of places over the entire kernel (in ~8 files, IIRC) where we do something trickier. All gone very early in that series. The painful parts had been elsewhere...

Downsides of C language culture?

Posted Aug 27, 2024 4:45 UTC (Tue) by NYKevin (subscriber, #129325) [Link]

The other possibility (that I can think of) is something like "cast it to char* and modify the bytes by hand." You can do that in Rust, of course, but Rust is a lot more willing to hit you with the UB hammer if you do something nonsensical like setting a bool to 3, an enum to a nonexistent variant, etc. In C, this sort of restriction either does not exist at all, or if it does exist, it labeled as a "trap representation" and blamed on the hardware. In practice, people are very quick to demand/assume that x86 does not have trap representations, and therefore C-compiled-for-x86 also cannot/should not have trap representations either.

Of course, C does not even have visibility restrictions in the first place, except for really blunt measures like an opaque struct. In Rust, visibility restrictions are considered part of the safety boundary - there are plenty of APIs in the standard library and third-party crates which rely on visibility restrictions to maintain safety. For example, if you reach into a Vec and change its size or capacity, you can cause it to read uninitialized memory or perform other kinds of UB. But that's still considered a sound API, because you can't reach into a Vec and fiddle with its private members (without writing unsafe code that does some kind of type-punning).

Anyway, the end result of all this is that, in Rust, if you care to do so, it is possible to design a struct or enum in such a way that it can only represent those states you actually want it to represent, and anyone who manages to get it to represent some other state has already done UB before your code even runs.

Downsides of C language culture?

Posted Aug 26, 2024 11:37 UTC (Mon) by taladar (subscriber, #68407) [Link]

My argument was less that Rust would prevent you from doing this and more that this sort of micro-optimization at the cost or readability and correctness is part of C culture and Rust culture (and the culture of quite a few other languages) is that you just don't do things like that because they are a bad idea.

Downsides of C language culture?

Posted Aug 26, 2024 11:48 UTC (Mon) by taladar (subscriber, #68407) [Link]

Just reusing fields of some struct from somewhere else in the code base for an unrelated purpose. That just wouldn't be done in most language cultures but especially not in languages like Rust that put clean abstractions and correctness first.

Downsides of C language culture?

Posted Aug 25, 2024 16:37 UTC (Sun) by cytochrome (subscriber, #58718) [Link]

I'm disappointed that it took so long for someone to bring up Rust in the comments for this piece. ;-)


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