Microsoft has been working on allowing driver developers to write Windows drivers in Rust, and the company has published a progress report detailing this effort. In the windows-drivers-rs GitHub repository you’ll find a bunch of Rust crates for writing Windows drivers in Rust.
Using these crates, driver developers can create valid WDM, KMDF, and UMDF driver binaries that load and run on a Windows 11 machine.
[…]Drivers written in this manner still need to make use of unsafe blocks for interacting with the Windows operating system, but can take advantage of Rust’s rich type system as well as its safety guarantees for business logic implemented in safe Rust. Though there is still significant work to be done on abstracting away these unsafe blocks (more on this below), these Rust drivers can load and run on Windows systems just like their C counterparts.
↫ Nate Deisinger at the Windows Driver Developer Blog
As mentioned above, there’s still work to be done with reducing the amount of unsafe Rust code in these drivers, and Microsoft is working on just that. The company is developing safe Rust bindings and abstractions, as well as additional safe structs and APIs beyond the Windows Driver Framework, but due to the complexity of Windows drivers, this will take a while.
Microsoft states that it believes memory-safe languages like Rust are the future of secure software development, but of course, in true Microsoft fashion, the company doesn’t want to alienate developers writing traditional drivers in C either.
As much as I have a personal distaste against Rust syntax, I have to commend their approach to relevancy.
Just a note, there are basically a very short list of proven languages: C, C++, Java, PHP, Python, and Assembly. Everything else is syntactic sugar
Now do not get me wrong, syntactic sugar can be helpful. TypeScript is for example better for many projects than plain JavaScript, or a language like Go can be useful for writing backend services or command line tools.
That being said, … the Rust developers seems to recognize this. Either explicitly, or implicitly steer for a relevancy goal with a two pronged attack: a niche in machine learning and integrating into established codebases for additional benefits (like security and reliability in driver authoring).
Will this work? Only time will tell.
However they are at least pushing in the right directions.
(list of proven languages) Not even LISP ?
Kochise,
LISP is a very good language. A historically important one, and has influence on many others. I even wrote an interpreter once back in the day.
However, my criteria for established languages is:
For example,
C has: Linux kernel
C++ has: Windows, macOS, Google Search, Chrome, (maybe) Firefox among others.
Java has: (again) Google Search, Android
PHP has: Facebook (though their own dialect), Wikipedia
Python has: YouTube (had?), PyTorch
Assembly: Basically all devices
Yes, there are portions in other languages in those code bases. But I was thinking about the main ones. And… it also shows languages are not standalone, but ecosytems.
You either use one of the established ones.
Or use “syntactic sugar” to target the libraries written in one of the established ones.
(Can “Go” for example exist without C standard libraries)?
There was a time when LISP could/should have taken over the world. Concise programming language, made for AI before it was a thing, but too many parenthesis perhaps.
Then Prolog entered the game.
I really wish things turned different.
Kochise,
While I can acknowledge LISP’s strengths, it feels more like an intermediate AST representation of a program than a programming language for humans to write software in.
https://en.wikipedia.org/wiki/Abstract_syntax_tree
However I do see the merit in logic programming languages and was drawn to Prolog. I also though haskel had some really cool features compared to the languages I was otherwise being exposed to in my career. Alas, like most people though, I ended up working on more mainstream languages because that’s where the work is at – this is an important driver in the language popularity contest and has little to do with merit.
I see this being a common stumbling block across the linux and windows kernels. C interfaces will keep hindering rust’s approach to safety until the C interfaces get replaced with rust ones. It’s logistically difficult to update so much code, and also unpopular with developers who don’t want to switch.
I see this as a very tough balance. Technically there’s a good case for designing kernels to be memory safe from the start rather than trying to mix highly incompatible models together. But in the real world the issue is always the same: new operating systems/kernels face serious adoption challenges and chicken and egg problems. No drivers, no users, no marketshare, etc. Cramming memory safe language into a legacy code base, even if the hybrid approach defeats the benefits, may be the only way forward within the confines of real world operating system popularity contests.
Alfman,
It is not a difficult problem, but an impossible one. Our CPU and overall computer design makes it necessary to have unsafe codes, whether in C or in Rust.
How do you access hardware buffers without de-referencing raw pointers, usually with magic addresses like oxB8000? How do you even build a safe memory allocator, without first building a raw list of allocatable regions on RAM? Or worse the virtual memory which could map into RAM, PCIe, disk, or even uninitialized at any time?
The only thing Rust will bring is explicitly marking all these pointers as “unsafe”. But we already know that in the kernel domain.
LISP to the rescue again : https://github.com/vygr/ChrysaLisp or https://github.com/froggey/Mezzano
Back in the days : https://en.wikipedia.org/wiki/Genera_(operating_system)
sukru,
Ok, but were talking about very little code there. I could say it’s impossible to write a C kernel because you need bits of assembly to program special CPU registers like descriptor tables. That’s true, but we can just create abstractions for those bits and move on, it’s not really an issue. In the same vein, we’re not going to reach 100% safe rust either, but we can create abstractions for the unsafe code and have them be orders of magnitude less than the safe code.
I should study more how redox handles it, but thinking off the cuff I think that ideally one would create a safe resource abstraction that knows about the hardware’s memory ranges (through bios tables or plug and play) and drivers would access those buffers through the safe abstraction. I understand that the drivers are privileged and still need to be trustworthy, but even so safe abstractions could still limit most of the need for unsafe sections proliferating throughout the kernel.
Safe abstractions would let drivers access their designated buffers without unsafe pointers. Ideally the safe abstractions would compile away into zero cost abstractions, although I accept we may need specific examples to convince ourselves that the compiler’s output is still optimal in practice.