Coder Social home page Coder Social logo

linux-kernel-module-rust's Introduction

Writing Linux Kernel Module in Rust

Build Status

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.

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.

Requirements

Toolchain

  • x86_64

    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:

    $ rustup target add arm-unknown-linux-gnueabi

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

Linux Kernel Headers

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

  • x86_64

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

    $ sudo apt-get install linux-headers-`uname -r`
  • ARMv7 (Raspberry Pi)

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

Build

  1. cargo-xbuild, rust-src and rustfmt-preview
$ cargo install cargo-xbuild
$ rustup component add --toolchain=nightly rust-src
$ rustup component add rustfmt-preview
  1. Select an example
$ cd hello_world
  1. Compile into a static library

    • x86_64
      $ RUST_TARGET_PATH=$(pwd)/.. cargo xbuild --target x86_64-linux-kernel-module
    • ARMv7 (Raspberry Pi)
      $ RUST_TARGET_PATH=$(pwd)/.. KDIR=<path-to-your-compiled-kernel> cargo xbuild --target armv7l-linux-kernel-module
  2. Link as a kernel module

    • x86_64
      $ make
    • ARMv7 (Raspberry Pi)
      $ make TARGET=armv7l-linux-kernel-module KDIR=<path-to-your-compiled-kernel> CROSS=arm-linux-gnueabihf-
  3. Load and test

    See below.

  4. If you want to clean it up

    • x86_64
      $ make clean;cargo clean
    • ARMv7 (Raspberry Pi)
      $ make clean TARGET=armv7l-linux-kernel-module KDIR=<path-to-your-compiled-kernel> CROSS=arm-linux-gnueabihf-;cargo clean

Load and Test

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).

hello_world

The simplest kernel module. It just prints "hello" and "goodbye".

$ sudo insmod helloworld.ko # load the module
$ sudo rmmod helloworld # remove the module
$ dmesg # dump kernel messages

yes_chardev

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

$ sudo insmod yes_chardev.ko
$ cat /proc/devices # find the major number of the device 'yes', for example, 243
$ sudo mknod /dev/yes c 243 0 # make a filesystem node (replace 243 with your own major number)
$ sudo cat /dev/yes # read from the device
$ sudo rmmod yes_chardev

simple_sysctl

A simple sysctl device driver.

$ sudo insmod simple_sysctl.ko
$ cat /proc/sys/rust/example/test # the default value should be 1
$ sudo sh -c "echo 2 > /proc/sys/rust/example/test" # change the value
$ cat /proc/sys/rust/example/test # now the value is 2
$ sudo rmmod simple_sysctl

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

$ sysctl rust.example.test # read
$ sudo sysctl -w rust.example.test=2 # write

sync_example

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

let mutex_data = sync::Mutex::new(50);
let mut data = mutex_data.lock();
println!("Data {} is locked by a mutex", *data);
*data = 100;
println!("Now data is {}", *data);
println!("Hello from Rust!");

The above code snippet will output like this:

[  424.328154] Mutex is locked!
[  424.328156] Data 50 is locked by a mutex
[  424.328158] Now data is 100
[  424.328158] Hello from Rust!
[  424.328160] Mutex is dropped!

smsc95xx

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.

Roadmap

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.

Acknowledgment

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

License

GPL-2.0

linux-kernel-module-rust's People

Contributors

lizhuohua avatar mssun avatar jkonecny12 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.