Giter Site home page Giter Site logo

rust.ko's Introduction

rust.ko

a minimal Linux kernel module written in rust.

Requirements

  • A recent build of Rust (latest nightly)

This code uses feature flags, so you'll need to use a nightly version of Rust to compile it.

TL;DR

  1. Create a file config.mk in the root directory of the repository.

  2. Set RUST_ROOT in this file to the directory containing bin/rustc, e.g. RUST_ROOT := /usr

  3. Compile rust.ko:

     $ make
    
  4. Try it out:

     # insmod hello.ko
     # rmmod hello
     $ dmesg | tail -3
       [54024.186997] hello: init
       [54024.187000] hello from rust
       [54024.191963] hello: exit
    

make command-line options

Currently there are a few parameters you can pass to make to affect the build:

  • V=1: Enable verbose output
    • All commands run by make and cargo will be printed to the screen
  • RELEASE=1: Create a release build
    • rustc will compile all code in --release mode
    • Debugging information will not be added to the final binary

Notes

Cargo.lock

When running make for the first time cargo will generate a Cargo.lock file in the project's root directory. This file contains information about the exact versions of the dependencies of your project. Since this is an example project it will not ship any Cargo.lock file, but it's recommended that you commit it to your source tree if you're actually trying to build a project based on this code.
(Please don't make any pull requests to this code containing a Cargo.lock file through.)

Build targets

Since Linux code can be compiled for a lot of different architectures, we have to be able to generate CPU code that is in line with what the kernel expects. This means specifically:

  • No floating-point operations in kernel mode at all
  • No CPU instructions that write to floating-point registers (SSE, SMID, … on x86 for instance)
  • No usage of the red zone
  • No target operating system (after all: When you are in kernel mode, you are the operating system)

Currently this source code only ships with a target specification file for the x64_64 architecture. If you get an error similar to the following, you'll have the honor of creating and submitting one for favourite architecture: 😉

cd "…/rust.ko" && /usr/local/bin/cargo rustc --target="armhf-unknown-none-gnu" --  --emit obj -o "…/rust.ko/build/hello-rust.o"
failed to run `rustc` to learn about target-specific information

Some ideas on how to do this may be found here under the Creating a target file section.

Kernel API and ABI stability

Due to the fact that Linux does not provide any ABI stability (not even for two identical copies of its source code), we must build kernel modules against its API instead. While this is trivially done in C, by building the code against the headers of that kernel version, it's not that easy to do in Rust. Most importantly because Rust cannot read C headers of course, but also because any extern "C" function bindings and, more importantly, any #[repr(C)] structure definitions you define, will link against the kernel's ABI not the API!

Here is an incomplete list of things that affect the kernel's ABI stability:

  • Using a different version of gcc or clang to compile the kernel's source code
  • Adding or removing private fields from kernel data structures (may even happen in minor releases!)
  • Changing kernel build options:
    • Some build options cause data structures to contain extra fields
    • Some functions might just disappear
    • Memory alignment or field ordering might change to make data structures more memory efficient

Check out the kernel documentation for more information on kernel API (in)stability.

Currently rust-bindgen is invoked at the module's build time to generate Rust counterparts for all C data structures, enumerations, functions and types defined by the kernel headers. This addresses most of the issues mentioned above, but is not a silver bullet: No bindings are generated for C macro definitions and in-line functions. Most importantly this matters, because, for a C developer it is often irrelevant whether they declare a bunch of macros for different states of something, or use an enum definition instead; after all, the result is the same, right? While this is certainly true from a C programmers perspective, it is not the same from the compiler's point of view: C macros are expanded during the preprocessor stage, while enums are expanded during the main compiling/assembling stage. For rust-bindgen (that operates on the main compiling stage) this means that all macros have disappeared by the time it gets to look at the source code's AST. There is no way to use C macro definitions because of this at the current time.

Compilation times

The first build will be ratter slow as the kernel header bindings are generated by rust-bindgen. Also, when you target another kernel or change the list of headers used (with the KERNEL_INCLUDE option), you will also experience a delay while the bindings are regenerated.

Please see the Kernel API and ABI stability section for details on why this is necessary for any serious use of the kernel interfaces.

refs

rust.ko's People

Contributors

bluet avatar cuviper avatar fhahn avatar int-index avatar ms705 avatar mtahmed avatar ntninja avatar panicbit avatar tbelaire avatar tsgates avatar tupshin avatar wfraser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust.ko's Issues

Allows SIMD and floating point

There's no trivial solution. This article is a good discussion of the problem. I thought I'd mention it in case you want to update this, or in case someone else is debugging mysterious memory corruption.

Compilation error: Could not find specification for target "x86_64-unknown-none-gnu"

$ rustup run nightly make KERNEL_BUILD_PATH=/lib/modules/4.17.11-arch1/build/ CARGO=/home/frol/.cargo/bin/xargo
error: failed to run `rustc` to learn about target-specific information

Caused by:
  process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --sysroot /home/frol/.xargo -Z force-unstable-if-unmarked --target x86_64-unknown-none-gnu --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro` (exit code: 1)
--- stderr
error: Error loading target specification: Field target-c-int-width in target specification is required
  |
  = help: Use `--print target-list` for a list of built-in targets

I have updated the x86_64-unknown-none-gnu.json file with the version from rust-barebones-kernel, but still cannot get through error:

$ rustup run nightly make KERNEL_BUILD_PATH=/lib/modules/4.17.11-arch1/build/ CARGO=/home/frol/.cargo/bin/xargo
   Compiling core v0.1.0 (https://github.com/phil-opp/nightly-libcore.git#54571deb)
   Compiling kernel32-sys v0.2.2
   Compiling log v0.4.3
   Compiling clang-sys v0.5.4
error: Error loading target specification: Could not find specification for target "x86_64-unknown-none-gnu"
  |
  = help: Use `--print target-list` for a list of built-in targets

error: Could not compile `core`.
warning: build failed, waiting for other jobs to finish...
error: build failed
make[2]: *** [/mnt/storage/projects/linux-kernel-basecamp/rust.ko/build/Makefile:46: /mnt/storage/projects/linux-kernel-basecamp/rust.ko/build/libhello.a] Error 101
make[1]: *** [Makefile:1571: _module_/mnt/storage/projects/linux-kernel-basecamp/rust.ko/build] Error 2
make: *** [Makefile:36: all] Error 2

Can anyone help me?

ld: unrecognized option '--require-defined=...'

Hi, I'm really excited about the newest patch, with bindgen support, but I'm getting errors when compiling it.

ld -m elf_x86_64   --gc-sections --entry=init_module --require-defined=cleanup_module  -r -o /home/tbelaire/Code/rust.ko/build/hello.o /home/tbelaire/Code/rust.ko/build/src/module.o /home/tbelaire/Code/rust.ko/build/libhello.a 
ld: unrecognized option '--require-defined=cleanup_module'

$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.24
Copyright 2013 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

My binutils package is up to date, should I be using a llvm linker or something?

Oh, and I needed to add in

 "-fno-delete-null-pointer-checks",

to the CLANG_ARGS_BLACKLIST, but that's fine.

FTBFS: error: error: unknown argument: '-fno-delete-null-pointer-checks'

I'm getting the clang error, and failed to build from source.

bluet@Titania:~/workspace/rust.ko$ make Compiling linux-std v0.1.0 (file:///home/bluet/workspace/rust.ko/std) error: failed to run custom build command forlinux-std v0.1.0 (file:///home/bluet/workspace/rust.ko/std) Process didn't exit successfully:/home/bluet/workspace/rust.ko/target/debug/build/linux-std-b8b7ab4d3d9bbe98/build-script-build` (exit code: 101)
--- stdout
Working directory: /usr/src/linux-headers-3.19.0-58-generic
LLVM arguments: -Wp,-MD,/home/bluet/workspace/rust.ko/build/.libhello.a.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.8/include -I./arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -Iinclude -I./arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -Iubuntu/include -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -m64 -DKBUILD_STR(s)=#s -Werror=implicit-int -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -Werror=strict-prototypes -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -fno-delete-null-pointer-checks -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -DKBUILD_BASENAME=KBUILD_STR(libhello) -pg -DMODULE -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -Dfalse=__false -Dtrue=__true -Du64=__u64 /home/bluet/workspace/rust.ko/target/x86_64-unknown-none-gnu/debug/build/linux-std-b8b7ab4d3d9bbe98/out/kernel-include.h

--- stderr
error: error: unknown argument: '-fno-delete-null-pointer-checks'
warning: warning: unknown warning option '-Wno-unused-but-set-variable'; did you mean '-Wno-unused-const-variable'? [-Wunknown-warning-option]
warning: include/asm-generic/int-ll64.h:25:28: warning: redefinition of typedef '__u64' is a C11 feature [-Wtypedef-redefinition]
thread '

' panicked at 'Error generating bindings!', std/build.rs:160
note: Run with RUST_BACKTRACE=1 for a backtrace.

make[2]: *** [/home/bluet/workspace/rust.ko/build/libhello.a] Error 101
make[1]: *** [module/home/bluet/workspace/rust.ko/build] Error 2
make: *** [all] Error 2
My env
bluet@Titania:/workspace/rust.ko$ uname -a
Linux Titania 3.19.0-58-generic #64
14.04.1-Ubuntu SMP Fri Mar 18 19:05:43 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
bluet@Titania:/workspace/rust.ko$ clang -v
Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)
Target: x86_64-pc-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/4.8
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/4.8.4
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/4.9
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/4.9.3
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9.3
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.8.4
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/i686-linux-gnu/4.9.3
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.3
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8
bluet@Titania:
/workspace/rust.ko$ rustc -V
rustc 1.9.0-nightly (b678600ac 2016-03-29)
bluet@Titania:~/workspace/rust.ko$ cargo -V
cargo 0.10.0-nightly (d38f03b 2016-03-29)
`

Does not work with recent Rust versions

It seems like there have been a bit of changes, so that e.g. #![feature(libc)] and #![feature(core)] aren't readily available any more. Are you able to compile this code yourself w/ rustc 1.2 or newer versions?

--gc-sections causes undefined symbol errors.

I've been forced to remove the --gc-sections line, as it removes functions, including _Unwind_Resume, causing errors at link time.
This is only apparent if you've started using something from the stdlib that can panic, as otherwise there are no references to _Unwind_Resume, but for my rot13 branch, I have been unable to build with --gc-sections.

Build fails due to std crate in kernel binding while std/lib.rs specifies #![no_std] attribute

The project doesn't get compiled out of the box with rustc 1.20.0-nightly (bf0a9e0b4 2017-07-10). Instead of the forked version of bindgen (which doesn't get compiled), I used the original one which generates a kernel binding that uses std crate everywhere. A snippet looks like:

pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
impl <T> __IncompleteArrayField<T> {
    #[inline]
    pub fn new() -> Self {
        __IncompleteArrayField(::std::marker::PhantomData)
    }
    #[inline]
    pub unsafe fn as_ptr(&self) -> *const T { ::std::mem::transmute(self) }
    #[inline]
    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
        ::std::mem::transmute(self)
    }
    #[inline]
    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
        ::std::slice::from_raw_parts(self.as_ptr(), len)
    }
    #[inline]
    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
        ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
    }
}

While compiling, I get the following errors (a lot of similar ones because of use of std crate).

error[E0433]: failed to resolve. Could not find `marker` in `std`
 --> std/src/os/kernel.rs:5:38
  |
5 | pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
  |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Could not find `marker` in `std`

I wonder how the original project was even compiled. Any idea how can I get around the issue?

rust_main undefined on latest nightly

I'm using linux kernel 4.20.6 and the following clang and rust versions[0]. The make command succeds for me, but I get the following warning. Seems like the module compiles successfully but the linking to rust library is broken.

WARNING: "rust_main" [/usr/src/rust.ko/build/hello.ko] undefined!

Let me know if more information is needed to debug this issue.
[0]:

[root@host rust.ko]# rustc --version
rustc 1.35.0-nightly (70f130954 2019-04-16) 
[root@host rust.ko]# clang --version
clang version 5.0.1 (tags/RELEASE_501/final) 
Target: x86_64-unknown-linux-gnu 
Thread model: posix  
InstalledDir: /opt/rh/llvm-toolset-7/root/usr/bin

missing \0 erminator?

this might not be an issue, but i'm really surprized to see that you ignore the length of the string slice in main.rs while not doing anything about null terminators. Or does fixup add a null terminator to the &'static str somehow?

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.