
Linux kernel drivers in Rust might become an option in the future - jobstijl
https://lwn.net/Articles/797828/
======
vardump
I think we should just evaluate Rust based on its merits. Ignore fanboys and
ignore the opposite as well.

In other words, Rust is just another tool. Regard it as one without subjective
emotions either way. Be constructive, don't only look for faults, but also
ways how to overcome them. But don't close your eyes from them either.
Acknowledging weaknesses is the first step to improvement.

Some possible questions and measures to consider below. I'm sure there's a lot
more to add on this list.

1) Stability. Other than for development, unstable kernels are a no go. Can
possible negative effects be mitigated?

2) Security is often what Rust is expected to bring on the table. So is Rust
actually more secure in the environment kernel requires? This could be tested
by "clean-room" reimplementing something that is historically known to have
many security issues.

3) Are there showstoppers for kernel builds? Interoperability, build
performance, architectures unsupported by Rust, etc. If so, could these be
mitigated? Conversely, is there something positive Rust could provide?

4) How does it affect runtime performance? Average case. Bloat issues? Any
pathologic cases? Any benefits?

5) What other unexpected it brings on the plate? Both benefits and
disadvantages. For example, could Rust types also be used to catch errors
other than memory related, like invalid states?

6) <Your consideration here or above>

~~~
mehrdadn
> 6) <Your consideration here or above>

"Would C++ fare better or worse than Rust on these fronts?" is the question I
would have.

~~~
mikekchar
I was a C++ developer a long time ago (I've actually used CFront as a
professional -- that's how long ago ;-) ). C++ is a fine language. You can
write good code in C++. I've worked on large projects that were extremely
stable and easy to work with. It can be done.

The one thing I will say about C++ from long ago was that you needed to be
skilled at C++. You needed to understand it and you needed to know how to
write code that wasn't going to cause you problems in the future. You also
needed to work on a team that allowed you to use your skill. The language is
so different now that it's practically I different language so I don't know
how much of that still remains, but I guess quite a lot.

I've been doing some Rust recently. I like Rust. There are bits I think still
need work, but generally it's a fine language. The biggest difference I see
between it and C++ from long ago is that Rust helps you _a lot_. It's very
convenient and friendly. It also scolds me when I do something stupid, which I
appreciate.

However, I don't really feel like I need to know less than I did as a C++
programmer. With Rust, it helps you, but if you start causing problems for
yourself you can be in for a world of hurt trying to understand what the
compiler doesn't like. It will catch that thing that slips by you, which is
awesome, but you _still_ have to understand what's going on under the hood.

So in my book, it feels very much like C++ with a super friendly and super
powerful linter. I mean it's really, really nice, but I don't think you could
just hire random people off the street and give them a Rust compiler and say
"This will protect you".

So to answer your question (finally), I think you won't really fare much
better or worse, but the journey seems a little bit more relaxed with Rust.

~~~
roca
The failure modes of "can't get code to compile" and "something weird and
possibly exploitable could happen at runtime" may both be frustrating to
developers, but they're worlds apart in practice. Looking at it from the point
of view of a kernel maintainer evaluating submissions, the former is not your
problem --- in fact it keeps the bad code from ever coming to your attention
--- but the latter creates ongoing problems for you.

~~~
CountSessine
This is true, but there's also a lot of trivial busy-work and confusion that
the compiler and language foist on you that isn't security related. Like the
fact that you always seem to have a &str when you actually need a String or
vice-versa and your code is littered with .to_string() everywhere. Or figuring
out what type your iteration is at a particular stage and why you can't call
map() on it. Or figuring out the vicissitudes of what collect() will accept
and convert for you and what it won't. Or clumsily dealing with a Vec of
Results when what you really want is a Result with a Vec

Having a really sophisticated type system means...dealing with types a lot. I
love Rust - especially ADTs and everything being an expression - but I
wouldn't call it more productive than C++. And I think that was mikekchar's
point?

~~~
mplanchard
Just wanted to make sure you knew, you can use `.collect()` to convert an
iterable of results into a Result with an iterable.

See the 6th example here: [https://doc.rust-
lang.org/std/iter/trait.Iterator.html#examp...](https://doc.rust-
lang.org/std/iter/trait.Iterator.html#examples-24)

------
geofft
We're working on it: [https://github.com/fishinabarrel/linux-kernel-module-
rust](https://github.com/fishinabarrel/linux-kernel-module-rust)

Check out the demo in PR #122, which lets you create three boolean sysctls and
a character device that prints the state of those sysctls in JSON (using
serde).

We gave a talk about it last week at Linux Security Summit, I'll submit it
once the recording is up :) Slides are at [https://ldpreload.com/p/kernel-
modules-in-rust-lssna2019.pdf](https://ldpreload.com/p/kernel-modules-in-rust-
lssna2019.pdf) .

~~~
zaphirplane
For those like I was, wondering why a framework is required to write out of
tree Linux modules in rust

It’s to auto create rust bindings. Link between rust crates and kernel build
system

~~~
geofft
Half that, and half to create safe interfaces that feel like native Rust
("ergonomic") and not like you're writing C in Rust.

For instance, the kernel wants you to define a character device by passing a
struct with a bunch of C function pointers for how to read, write, seek,
ioctl, etc. on the device. Rust has a trait / interface system that's a good
match for this use case, so in src/chrdev.rs we define a Rust trait with all
these methods, and we have a helper function to create the C struct with FFI-
safe function pointers that call the various methods on the Rust trait.

The broad goal is that you don't need to use the "unsafe" keyword to write
kernel modules that don't access memory directly themselves (filesystems,
network protocols, etc.: device drivers might still need unsafe code where
actually talking to the device, but it should be as little as possible). That
means the interface used by kernel modules can't involve any unwrapped C
functions or raw C pointers.

------
kev009
Johannes Lundberg wrote a thesis on doing this with FreeBSD and has a
framework
[https://github.com/johalun/rustkpi](https://github.com/johalun/rustkpi)

[https://kth.diva-
portal.org/smash/get/diva2:1238890/FULLTEXT...](https://kth.diva-
portal.org/smash/get/diva2:1238890/FULLTEXT01.pdf%EF%BB%BF)

------
ufmace
Sounds like the start of something good. Though the comments feel a bit weird.
Maybe it's just a strange day for some reason, but I feel like today, I've
seen an awful lot of comments from people pushing rewriting things in Rust who
know absolutely nothing about the code they're asking about or the problem
domain it runs in.

I mean, I personally think Rust is cool and all that, but come on, who does
that?

~~~
masklinn
> I mean, I personally think Rust is cool and all that, but come on, who does
> that?

Some people have an LDS complex (they've found their messiah and want to
spread the word). Apparently there's also people who've decided that over-the-
top inane "evangelisation" was a good troll and way to turn people off. A
significant number of PL threads on /r/programming have a comment attempting
this sort of shit-stirring.

~~~
Razengan
> _Some people have an LDS complex (they 've found their messiah and want to
> spread the word)._

Or, some craftspeople/artisans prefer tools that are a joy for them to use
instead of just a means to an end, and have the luxury to choose what they
work with.

~~~
__s
He's referring to people who open issues on random projects asking the project
owners to RIIR. These people often don't create much on their own, so they're
pushing a "I can't help this cool project because it's not using a language
like Rust that would make me capable of contributing, if they rewrote it in
Rust then they'd have the reward of my presence in their codebase" when in
reality language choice is a small hill to climb

I was recently having someone do this on a web project of mine that's written
entirely in ES6 Javascript

------
ajxs
If I recall correctly, Torvalds already addressed the hype around this (
totally not new ) idea by pointing out that memory errors really make up only
tiny part of the intricacies of building a kernel. This idea predates Rust,
and for better or worse will probably outlive it.

~~~
WilliamEdward
He also said that most of the issues with writing kernels have nothing to do
with choice of programming language, but instead hardware compatibility.
Neither Rust nor anything else could help this.

~~~
ajxs
Here's the source of the original quote:
[https://www.infoworld.com/article/3109150/linux-
at-25-linus-...](https://www.infoworld.com/article/3109150/linux-at-25-linus-
torvalds-on-the-evolution-and-future-of-linux.html) Admittedly, kernel and
driver development are different things. The original quote was to do with
kernel development.

"That's not a new phenomenon at all. We've had the system people who used
Modula-2 or Ada, and I have to say Rust looks a lot better than either of
those two disasters.

I'm not convinced about Rust for an OS kernel (there's a lot more to system
programming than the kernel, though), but at the same time there is no
question that C has a lot of limitations.

...I don't think you actually solve any of the really hard kernel problems
with your choice of programming language. The big problems tend to be about
hardware support (all those drivers, all the odd details about different
platforms, all the subtleties in memory management and resource accounting),
and anybody who thinks that the choice of language simplifies those things a
lot is likely to be very disappointed."

I disagree with him about Ada, for what it's worth, but the overall point is
correct. The real problems of kernel development aren't things a borrow
checker will help with. A big part of developing a kernel takes place before
management of heap memory is even relevant. All this being said. For user-
space applications, Rust has a lot to offer.

~~~
swfsql
I read that slightly differently. I read that as: "even after putting the
shoes on, the marathon still needs to be run". So yes, lifting reasoning
burden away from eg. function interfaces (owning vs uniquely borrowing vs
shared borrowing), lifetime problems (and so on), precisely enables everyone
to put/spend more "effort" on the remaining difficulties.

------
megous
Yeah, I would not like this becomming required. Now, it's still fairly
manageable to keep developing and building my own kernels. You need
binutils/gcc for your host platforms, and that's about all. And I have 3
architectures I build for.

If I also need clang and rust for all the platforms, and learn rust, for some
questionable benefits... That would make things hard.

~~~
josteink
> If I also need clang and rust for all the platforms, and learn rust, for
> some questionable benefits

I can see the arguments against needing 2 different C-compiler toolchains, not
to mention how this may limit target platform-support to the minimum subset
supported by both compilers...

But to argue that Rust only provides "questionable benefits" is really not
reasonable.

Even the hipster Javascript crowd has discovered that providing more
information to a/the compiler (Typescript) almost unconditionally provides
higher code-quality and better results.

When will the C-crowd do the same? When will they shed their "I know better
than any machine"-like elitism?

~~~
megous
Read it as "Questionable benefits in the context of the kernel."

------
abcdabcd987
Check out the HotOS'19 paper from our lab :)
[https://danyangzhuo.com/papers/HotOS19-Stone.pdf](https://danyangzhuo.com/papers/HotOS19-Stone.pdf)

------
michaelangerman
Some important links that motivated this story...

[https://hub.packtpub.com/rust-is-the-future-of-systems-
progr...](https://hub.packtpub.com/rust-is-the-future-of-systems-programming-
c-is-the-new-assembly-intel-principal-engineer-josh-triplett/)

[https://lwn.net/Articles/797558/](https://lwn.net/Articles/797558/)

------
acd
Could we have universal standardized hardware interfaces for basic
functionality of hardware devices? For example at least get the same
programming interface for basic functionality of Wifi chips. Then one could
have more accelerated drivers which makes use of all the specific hardware
features of chips.

Network chips has started to offer a common programming api as far as I
understand Switch Abstraction Interface (SAI). Could one do this for more
different than network hardware classes?

------
non-entity
I have Rust on a long backlist of things to check out, but the idea of writing
kernel drivers in something other than C is interesting to say the least.

------
nindalf
Existing languages in the Linux kernel -
[https://www.openhub.net/p/linux/analyses/latest/languages_su...](https://www.openhub.net/p/linux/analyses/latest/languages_summary)

Unsurprisingly it's mostly C (95.6%) with a bit of C++ (2%) and Assembly
(1.6%) and tiny bits of make (0.2%), shell scripts (0.3%), Python (0.1% and
Perl (0.2%). I'd guess it'd be at least half a decade before Rust cracks 1%
here.

~~~
cesarb
> with a bit of C++ (2%)

That sounded strange to me, since the dislike of C++ within the Linux kernel
is well-known, so I took a quick look. All uses I found were on user space
tools, not in the kernel itself, and all of them (except for a "check if this
compiles" test file) are in C++ because they have to call into libraries with
a C++-only API (LLVM and Qt).

------
w8rbt
I think setuid executables would be a good place for rust or go, but I have
reservations about the kernel itself.

------
jjtheblunt
Genuine question: who restricts the sourcecode language in which a kernel
driver is written?

I'm thinking machine opcodes in a .o file, to be linked wherever, are only of
a concern if they're doing function call linkages (and maybe kernel space vs
user space transition bookkeeping) improperly?

------
zelly
C++ written with -pedantic -Wall, smart pointers, and clang static analysis
tools, ASan, valgrind, etc. enabled is just as safe as Rust. Change my mind.

~~~
mlindner
Valgrind is runtime... You're not going to catch a double free that you don't
hit on the common path.

Not to mention race conditions in memory accesses.

------
stef-13013
Did you talk about that to Linus :):) ?

------
known
Give it as an exercise to college grads

------
agumonkey
Pardon the slightly fanboyish comment, but I fail to remember a single
negative response regarding Rust. Considering its domain I'm more than
impressed.

~~~
flukus
There are two types of languages, those people complain about and those nobody
uses, rust is closer to the later at this point in time. Outside a few filter
bubbles like HN rust is virtually unknown or little thought about.

I think the biggest issues are reliance on cargo (the systems language that
ignores your system libraries) and lack of a stable ABI, this is why it will
never replace C. Many people find the borrow checker aggravating. Even rust
fans seem to find the compile times far too long. As with all languages some
will find it too high level and others too low level, should it throw
exceptions or should it use error codes, etc.

And let's not forget the rust fans brigading any disagreement.

edit - do you mean in general or for this specific issue on the LKML, my reply
assumed in general.

~~~
littlestymaar
> Outside a few filter bubbles like HN rust is virtually unknown or little
> thought about.

It's still pretty new, but it's gaining adoption quicker than what I would
have expected. It's now used in Google, Facebook, Amazon, Dropbox and
Microsoft. Most of the time it's for some niche or experimental project, but
it's still an interesting trend.

> I think the biggest issues are reliance on cargo (the systems language that
> ignores your system libraries)

This is not accurate. There is no "reliance" on cargo, you can just use plain
rustc and it would work. And you can of course link dynamically to a system's
library: by default Rust's binaries are even linked with the system's libc
actually, and AFAIK most external C dependencies are linked that way (bindings
to openSSL for instance).

> and lack of a stable ABI

Many people would love to have a stable ABI, but it's way too early for that
because it would freeze Rust development, while there are still a lot of
things that need to be improved in the language.

I agree with you on compile times though and I hope things continue to improve
in that regard.

~~~
agumonkey
> gaining adoption quicker than what I would have expected

Basically that's what I was trying to say but failed somehow.

------
std_throwaway
Wouldn't modern C++ be better suited than Rust because it's closer to C?

I know that old C++ got some bad reputation in the past but I think it's time
to reconsider that with the changes that started with C++11. The only area
where Rust really is better is the management of lifetimes and its associated
higher memory safety.

~~~
the_duke
I'll bite.

C++ has quite a few powerful features that Rust doesn't have, including better
platform support, but Rust has a lot of things going for it that would make it
well suited to kernel development:

* no exceptions, and language features and a type system that is set up for explicit error handling - the kernel would need to disable C++ exceptions anyway, making error handling just as cumbersome as in C.

* the ML inspired type system helps to write correct code (eg sum types)

* the language is not riddled with UB and legacy C support induced cruft. You can opt in to unsafety with `unsafe` blocks, but these can be tightly scoped to where it's necessary and can be especially scrutinized

Especially in the context of a kernel, the increased safety guarantees are
worth a lot.

~~~
majewsky
On the flipside, the kernel developers are a group of people with a detailed
understanding of what makes C unsafe, and how to watch out for it in code
reviews. I'm not saying that every bug gets caught in code review, not by a
long shot, but the kernel developers as a group don't have any experience with
reviewing Rust code, let alone reviewing it for unsafe or undefined behavior.

We're still pretty early in Rust's lifecycle, and there is still a lot to be
learned about what `unsafe` can really break, especially at-a-distance. The
UCG WG is doing this work in [1], but I can understand if the kernel
developers want to hold off on using Rust for more central parts of the kernel
until this work is farther ahead.

[1] [https://github.com/rust-lang/unsafe-code-
guidelines](https://github.com/rust-lang/unsafe-code-guidelines)

~~~
nindalf
In my uninformed opinion, it's fairly simple to write Rust code that's easy to
review. Write unsafe as little as possible and if you need to, put that unsafe
block in as small a module as possible. That's mostly it.

I think it might be at least half a decade before Rust starts being used in
more central parts of the kernel (if at all) because adding a second language
significantly complicates the build process. Also, it is blocked on Rust
supporting _all_ the platforms that Linux supports just as well. It would be
disastrous for Linux to drop support for it's long tail of platforms because
Linux could no longer be built for those platforms.

~~~
majewsky
> Write unsafe as little as possible and if you need to, put that unsafe block
> in as small a module as possible. That's mostly it.

I don't have links at hand, but there were already instances where a bug in an
`unsafe` block had effects in completely different (and seemingly random)
places. Discovering all the ways in which `unsafe` blocks can cause unsafe or
undefined behavior in unrelated places is still an active field of research.

> It would be disastrous for Linux to drop support for it's long tail of
> platforms because Linux could no longer be built for those platforms.

Which is why driver modules are a good place to start. Drivers are specific to
certain pieces of hardware which are oftentimes only used with CPUs of a
specific ISA.

~~~
masklinn
> Discovering all the ways in which `unsafe` blocks can cause unsafe or
> undefined behavior in unrelated places is still an active field of research.

unsafe blocks can cause UB _period_ , UB means the program is broken but the
UB can _manifest_ anywhere.

C or C++ don't make this any better, they just make _the entire program_ into
a source of UB.

~~~
majewsky
Exactly. But many Rust proponents do not communicate that clearly. They often
make it sound like unsafe blocks contain the undefined behavior and prevent it
from spreading to the rest of the program, which they don't.

~~~
masklinn
That's very true. The value of unsafe blocks is that they restrict the number
of places you need to inspect / audit for UBs.

They're just places where you're telling the compiler "I know what I'm doing",
once an unsafe blocks has created an UB thing can break anywhere.

~~~
renox
I don't think that's really true, let's suppose that your unsafe code has a
presupposition that cause an UB if not met. If this is a bug and you can
remove the presupposition, great, but is-it always possible without
performance issue? If not, then you have to audit all the usage of the unsafe
part.

~~~
masklinn
> I don't think that's really true

It is though.

> let's suppose that your unsafe code has a presupposition that cause an UB if
> not met. If this is a bug

It is, or the code should not present as being safe.

> but is-it always possible without performance issue? If not, then you have
> to audit all the usage of the unsafe part.

If it's not possible to fix it (or if you don't want to fix it) _then the
wrapper for that unsafe code should also be unsafe_ , and it should document
its assumptions such that callers can know what to look for.

The tautological contract is that _safe rust is safe_. If it's possible to
trigger UB by passing the "wrong" value to a rust function then that function
is _not_ safe and _must_ be marked as unsafe itself. An unsafe block means the
compiler trusts that you know what you're doing, which is different from
_lying to the compiler_ , which is what you're apparently advocating /
defending.

------
reacweb
At the beginning, C was a handy language with some traps and pitfalls. Thanks
to standardization committees and insane optimizers, it has become a minefield
of undefined behaviors and security issues. Linux is coded in C because of the
"C is the desert island language". This should change and I dream to see
something that will replace C at least in the kernel.

------
youdontknowtho
Looking forward to enough Rust adoption that people stop seeing it as a magic
bullet. Once it's in large scale use and there are still errors that lead to
security problems maybe people will get over themselves.

~~~
roca
Nothing's ever perfect but there is empirical evidence that Rust code is far
less vulnerable than C or C++ code. For example this list of bugs found via
fuzzing: [https://github.com/rust-fuzz/trophy-case](https://github.com/rust-
fuzz/trophy-case) Almost none of those bugs were security-sensitive. Compare
to similar lists for C and C++ projects, e.g.
[http://lcamtuf.coredump.cx/afl/](http://lcamtuf.coredump.cx/afl/).

~~~
johnisgood
I am not exactly sure of the point of this comparison. The OP got it right.
There is not enough adoption. Of course you will find less programs with bugs,
because there are less programs written in Rust! That, and in case of
rewrites, they are almost nowhere complete functionality-wise.

I see that there is one use-after-free bug, and lots of out of range access
bugs. How does that happen?

~~~
steveklabnik
> I see that there is one use-after-free bug, and lots of out of range access
> bugs. How does that happen?

The use after free [1] is because of unsafe code, specifically, a function
that says "trust me, I know what the type of this is."

I only checked a few of the "out of bounds" bugs, and they all are panics [2],
which are not memory unsafe. Of course, someone could cause a real one with
the use of unsafe.

1: [https://github.com/shepmaster/sxd-
document/issues/47#issueco...](https://github.com/shepmaster/sxd-
document/issues/47#issuecomment-311688608)

2: [https://github.com/image-rs/image-
tiff/issues/28](https://github.com/image-rs/image-tiff/issues/28)

~~~
johnisgood
I know that I could probably find this out myself but is there a command-line
switch that would make the use of _unsafe {}_ a compile-time error? Of course
the alternative is just a quick grep for it, but personally I would feel safer
if the code did not compile at all in the presence of a compiler switch/flag
and unsafe blocks.

~~~
steveklabnik
So, there is, but it only works for _your code_. You can do it via an
attribute in the source (#![forbid(unsafe)]) or via a command line flag (cargo
rustc -- -D unsafe).

This will not check your dependencies. You can use other tools, like cargo-
geiger [https://github.com/anderejd/cargo-
geiger](https://github.com/anderejd/cargo-geiger) to check your dependencies.

And of course, at the lowest levels, doing anything useful requires unsafe,
since your operating system doesn't expose a Rust API to do tasks.

~~~
johnisgood
Thank you! I will use that attribute wherever I can.

------
shmerl
Nice development! Would be interesting to see something like amdgpu rewritten
in Rust.

~~~
mkl
Why? Throwing away something useful and reimplementing it again the same from
scratch seems like a silly waste of time.

~~~
Avamander
Slowly rewriting it to Rust does sound beneficial (I wouldn't be seeing memory
leaks) but I don't think the c(++)/Rust interop is good and seamless enough
for that?

~~~
Thiez
Strictly speaking Rust doesn't prevent memory leaks. You can easily create
cycles in reference counted types, or `std::mem::forget` something. No use of
unsafe required either.

That said as long as you don't build graphs with reference counted types it's
hard to leak memory by accident.

------
jstewartmobile
This is running MO for comp sci: adding loads of complexity for a minor gain.

Compile-time borrow-checking works for self-contained applications--the
compiler has a complete picture of what's going on. Move that model inside
kernel space--where blobs are being mutated across separately compiled
modules, different chipsets (CPU/DMA/GPU), sometimes even in parallel--might
as well wrap the whole thing in a big `unsafe` block.

Somebody's going to say " _Oh, you 're exaggerating. It's not that bad in
Redox._" Redox doesn't have to integrate with 28 years of kernel written in C.

~~~
roca
Rust borrow-checking doesn't depend on a closed-world assumption. Federico
converted librsvg to Rust and it worked fine.

~~~
jstewartmobile
" _Foreign functions are assumed to be unsafe so calls to them need to be
wrapped with unsafe {} as a promise to the compiler that everything contained
within truly is safe. C libraries often expose interfaces that aren 't thread-
safe, and almost any function that takes a pointer argument isn't valid for
all possible inputs since the pointer could be dangling, and raw pointers fall
outside of Rust's safe memory model._"

[https://doc.rust-lang.org/nomicon/ffi.html](https://doc.rust-
lang.org/nomicon/ffi.html)

~~~
wtetzner
Not sure what you're getting at. Rust can't catch all bugs, so it's not worth
having it to catch the ones it can?

~~~
jstewartmobile
It is right there in black-and-white: 28 years of C to be interfaced with ->
more FFI -> more unsafe blocks -> less that Rust can verify.

I don't think there will be enough left outside of unsafe blocks to justify a
second toolchain here. If the kernel were also in Rust, it would be a
different story.

~~~
pornel
It's quite the opposite. Wrapping existing C code in Rust FFI can make it
safer.

Rust side can add missing type information to C interfaces. Things that are
"RTFM" for C, such as thread safety of the types involved and which function
arguments are borrowed/owned, can be expressed on the Rust side even for C
code, and automatically enforced when it's used via FFI. This adds a layer of
safety to existing C code.

~~~
jstewartmobile
" _Using C libraries in a portable way involves a bit of work: finding the
library on the system or building it if it 's not available, checking if it is
compatible, finding C headers and converting them to Rust modules, and giving
Cargo correct linking instructions. Often every step of this is tricky..._"

Adding loads of complexity (i.e. more opportunities to screw something up) for
a minor gain.

~~~
pornel
Note that this mess isn't created by Rust. The difficulty of building
arbitrary C libraries on all platforms _comes from C_.

