Building FreeBSD Kernel Module on Rust.

Building FreeBSD Kernel Module on Rust.

In this article will be demonstrated how to build the kernel module written on Rust for the FreeBSD kernel.

Intro

Currently, Rust has reached some point in its development where it can be used as a second main programming language for building a kernel drivers and modules. Not a long time ago, a “Rust for Linux” was released for this purpose, but purely for Linux. However, for FreeBSD there were only some examples available, which used a crate that performs the conversion of C structures to Rust compatible FFI bindings. The drawbacks of this method is it requires to collect all necessary structs and functions into a single file which will be converted on the fly. This crate is not able to translate inline assembly and some macroses correctly.

For this reason I started a project, the main goal of which is to have a crate for API bindings to the kernel and a crate which wraps the unsafe methods in order to provide safe interface. I started this project about 3 years ago during FreeBSD 13.1 was the latest release, but I postponed the development for sometime because of the global events. Now, I resumed working on this project.

Release Engineering

Unfortunately, people with whom I invited to work on the code base and release engineering have quit for various reasons (mostly personal i.e problems in personal life, job, etc..). So, I can not afford supporting previous versions of both branches RELEASE/STABLE and most recent STABLE.

For the reason above, at the moment only FreeBSD 14.0-RELEASE is supported. As soon as 14.1 will be released, the work on 14.0 version will be stopped. And when 15.0-RELEASE will be released, the development for 14.x will be stopped.

Structure of the project

There are two crates:

both are available at 'crates io' or in my public repository hosted on gitlab.

The freebsd-kpi-rs is a raw bindings to the FreeBSD kernel of specific version. It does not implement any Rust programming approaches. There are only function signatures, structures or its signatures, macroses, inline assembly. The code is unsafe. During compilation of the crate, a build script of the crate is capable to read the config file of the FreeBSD kernel which is located in directory ‘/usr/src/sys/<arch>/conf’ from where it determines which features are enabled. By modifying the environment variable, it is possible to control the path or disable this feature and enable features manually.


The freebsd-kmi-rs is a either a safe implementation of different function which are provided by kernel or additional implementations which could be usefull in the kernel. It depends on 'freebsd-kpi-rs'. For example: heap memory management (malloc), safe implementation of the different sync items like: mutexes. The default ‘GlobalAllocator’ is implemented in this crate however it is recommended to compile the crate with feature which disables it and call the macros to implement your own in order to avoid problems with naming.

Example:

In the repository there is a repository called ‘freebsd-kmod-template’ with the template for the kernel module. In this demo crate it is demonstrated how to initialize the kernel module and build it.

At the moment, the crate is built using FreeBSD kernel module building system, for this reason an empty ‘.c’ file is needed and a Makefile is provided. Remember that the kernel sources must present in the /usr/src directory in order to compile it. And the Rust-nightly compiler also should present and be accessible. The Rust code is compiled into a static library which is then linked to the project.

In future, when I will figure out how to compile the code and link it as ELF with non standard entry point, the FreeBSD module build system will no longer be needed.

By calling ‘make’ in the root directory of the project file, the project will be compiled, liked and files will be generated in the same directory. By default, the Rust code optimization is enabled. Modify the options in the ‘cargo.toml’ to change this behavior.

In case when the project is renamed, the Makefile should also be modified. The name of the crate should be changed, otherwise make will not be able to find the lib.

Proof:

On the image above the kernel module was loaded and unloaded several times to make sure that everything works as expected.

Plans and ToDo:

In both crates, there are a lot of tasks left to do and more to add too. In the KPI crate it is required to complete some files because some code was left incomplete. Also, a testing of the struct sizes and correct aligment should also be performed.

In the KMI, also a lot of work left + testing.

Also, it is important to know, that some approaches like conditional compilation which is widely used in C header files of the kernel is not available in Rust. In Rust it is not possible to perform partial equal on the integers in features. Also, there are some problems calculating the offset in the structures. And Rust compiler performs alignment of the structures not always as it does Clang.

要查看或添加评论,请登录

Aleksandr M.的更多文章

社区洞察

其他会员也浏览了