Rust linux kernel modules

Rust linux kernel modules

Linux kernel modules in safe Rust

For most purposes, if you’re interested in writing Linux kernel modules in Rust, you should look at https://github.com/Rust-for-Linux/linux, which is an effort to contribute that process to the upstream kernel.

This is a framework for writing loadable Linux kernel modules in Rust, using safe abstractions around kernel interfaces and primitives.

For more information on the motivation and goals for this project, check out our presentation at Linux Security Summit North America 2019 and the video on YouTube. We’re immediately focusing on making this project viable for out-of-tree modules, but we also see this project as a testing ground for whether in-tree components could be written in Rust.

There is a simple demo module in the hello-world directory, as well as various other examples in the tests/ directory.

We run bindgen on the kernel headers to generate automatic Rust FFI bindings. bindgen is powered by Clang, so we use the kernel’s own build system to determine the appropriate CFLAGS. Then we write safe bindings to these types (see the various files inside src/ ).

Each kernel module in Rust lives in a staticlib crate, which generates a .a file. We pass this object to the Linux kernel’s own module build system for linking into a .ko .

The kernel is inherently multi-threaded: kernel resources can be accessed from multiple userspace processes at once, which causes multiple threads of execution inside the kernel to handle system calls (or interrupts). Therefore, the KernelModule type is Sync , so all data shared by a kernel module must be safe to access concurrently (such as by implementing locking).

Читайте также:  Sound toys bundle mac os

We’re currently only running CI on Linux 4.15 (Ubuntu Xenial) on amd64, although we intend to support kernels from 4.4 through the latest release. Please report a bug (or better yet, send in a patch!) if your kernel doesn’t work.

Other architectures aren’t implemented yet, but should work as long as there’s Rust and LLVM support — see #112 for expected status. They’ll need src/c_types.rs ported, too.

You’ll need to have Rust — in particular Rust nightly, as we use some unstable features — and Clang installed. You need LLVM/Clang 9 (released September 2019) or higher for multiple reasons, primarily support for asm goto . If you’re on Debian, Ubuntu, or a derivative, https://apt.llvm.org is great.

If the binary named clang is too old, make sure to set the CC or CLANG environment variable appropriately, e.g., CC=clang-9 .

Very recent kernels may require newer versions of Clang — try Clang 11 if older versions don’t work for you.

Источник

Rust linux kernel modules

Writing Linux Kernel Module in Rust

Device drivers on Linux-powered embedded or IoT systems execute in kernel space thus must be fully trusted. Any fault in drivers may significantly impact the whole system. However, third-party embedded hardware manufacturers usually ship their proprietary device drivers with their embedded devices. These out-of-tree device drivers are generally of poor quality because of a lack of code audit.

We propose an approach that helps third-party developers to improve the reliability and safety of device drivers without modifying the kernel: Rewriting device drivers in a memory-safe programming language called Rust. Rust’s rigorous language model assists the device driver developers to detect many security issues at compile time. We designed a framework to help developers to quickly build device drivers in Rust. We also utilized Rust’s security features to provide several useful infrastructures for developers so that they can easily handle kernel memory allocation and concurrency management, at the same time, some common bugs (e.g. use-after-free) can be alleviated.

Читайте также:  Как отключить автоопределение подключаемых разъемов windows 10

We demonstrate the generality of our framework by implementing a real-world device driver on Raspberry Pi 3, and our evaluation shows that device drivers generated by our framework have acceptable binary size for canonical embedded systems and the runtime overhead is negligible.

More details about the design and implementation can be found in our paper: Securing the Device Drivers of Your Embedded Systems: Framework and Prototype.

Rust nightly. Tested on nightly-2018-09-30-x86_64-unknown-linux-gnu .

ARMv7 (Raspberry Pi)

Rust nightly. In addition, you need to install the new target:

And the arm-linux-gnueabihf- cross-compiler.

Linux Kernel Headers

A pre-built kernel (with configuration and header files) is needed.

Your Linux distribution should provide a package for this. For example, on Ubuntu, you can try:

ARMv7 (Raspberry Pi)

You need to compile your own kernel in order for bindgen to work.

  1. cargo-xbuild , rust-src and rustfmt-preview

Compile into a static library

Link as a kernel module

If you want to clean it up

Examples are tested on Ubuntu 18.04 (Linux kernel 4.15.0-46-generic), smsc95xx is tested on Raspberry Pi 3 (Linux kernel 4.19.29).

The simplest kernel module. It just prints «hello» and «goodbye».

A simple character device which is similar to the yes Unix command.

A simple sysctl device driver.

There is another way to read/write the sysctl value:

A simple example to illustrate the use of Spinlock and Mutex .

The above code snippet will output like this:

A highly simplified real-world device driver for LAN9512 USB to Ethernet controller, which is used on Raspberry Pi 3. The implementation resembles the C version.

The efforts of writing kernel modules in Rust can be traced back to 2013 (the first commit of rust.ko), long before Rust’s first stable version was released. Here we list some of the objectives that people have already achieved and what we plan to achieve in the future.

  • Generate OS-independent machine code by using JSON specification files
  • Recompile pre-compiled libraries (core, compiler_builtins, alloc) by using cargo-xbuild
  • Generate Rust bindings for kernel headers to reuse existing data structures and functions defined inside the kernel by using bindgen.
  • Kernel allocator by using the GlobalAlloc trait.
  • Kernel synchronizations by reimplementing the synchronization primitives.
  • A simple real-world device driver for LAN9512.
  • Minimize the use of unsafe Rust.
  • Find a idiomatic way to define callback functions.
  • Failure recovery.
  • Use static analysis tool to reason about unsafe Rust code.
Читайте также:  Как удалить автозапуск приложений windows 10

Thanks to these previous works on writing Linux kernel driver in Rust. Their attempts inspire us a lot.

Источник

Оцените статью