Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Running Charon on Rust-for-Linux’s kernel

Rust-for-Linux’s kernel crate is built by Kbuild rather than Cargo. Running Charon on it requires some acrobatics.

You must be able to build the kernel crate, and have charon in your PATH.

Setup

The following assumes that the current directory is a clone of the kernel.

Pick an output path and some options to pass to Charon:

$ export CHARON_OUTPUT="$PWD/kernel.llbc"
$ export CHARON_OPTIONS="--extract-opaque-bodies --monomorphize"

Find Charon and the toolchain it needs:

$ export CHARON_BIN="$(command -v charon)"
$ export CHARON_RUSTC="$(charon toolchain-path)/bin/rustc"

Prepare a build directory and enable rust support:

$ mkdir -p ../linux-build
$ export KERNEL_BUILD_DIR="$(realpath ../linux-build)"
$ make LLVM=1 O="$KERNEL_BUILD_DIR" RUSTC="$CHARON_RUSTC" rustavailable
$ make LLVM=1 O="$KERNEL_BUILD_DIR" RUSTC="$CHARON_RUSTC" defconfig
$ scripts/config --file "$KERNEL_BUILD_DIR/.config" -e RUST
$ make LLVM=1 O="$KERNEL_BUILD_DIR" RUSTC="$CHARON_RUSTC" olddefconfig

Write the following script to $KERNEL_BUILD_DIR/charon-rustc:

#!/usr/bin/env sh
set -eu

is_kernel=false
previous=
for argument in "$@"; do
    if [ "$previous" = "--crate-name" ] && [ "$argument" = "kernel" ]; then
        is_kernel=true
        break
    fi
    previous=$argument
done

if [ "$is_kernel" = true ]; then
    export CHARON_EMIT_ARTIFACTS=1
    exec "$CHARON_BIN" rustc \
        $CHARON_OPTIONS \
        --sysroot default \
        --dest-file "$CHARON_OUTPUT" \
        -- "$@"
else
    exec "$CHARON_RUSTC" "$@"
fi

and make it executable:

$ chmod +x "$KERNEL_BUILD_DIR/charon-rustc"

The wrapper acts just like rustc except that if we’re compiling a crate called kernel, it will also extract it via Charon into the $CHARON_OUTPUT file.

Run Charon

Build the kernel crate with the wrapper:

$ touch rust/kernel/lib.rs
$ make LLVM=1 \
    O="$KERNEL_BUILD_DIR" \
    RUSTC="$KERNEL_BUILD_DIR/charon-rustc" \
    rust/kernel.o

The output llbc file can then be found in $CHARON_OUTPUT.

For example, the layout of Linux’s C struct list_head can be inspected with:

$ charon pretty-print --include-layouts "$CHARON_OUTPUT" > kernel.pretty
$ rg -A24 \
    'Full name: bindings::bindings_raw::list_head$' \
    kernel.pretty