rustc-1.62: allow to build out-of-tree kernel modules in Rust

Bug #2011355 reported by Andrea Righi
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
rustc-1.62 (Ubuntu)
Fix Released
Undecided
Unassigned
Jammy
New
Undecided
Unassigned
Lunar
Fix Released
Undecided
Unassigned

Bug Description

[Impact]

Rust 1.62 is required by the kernel to provide the proper infrastructure to build kernel modules (in Rust).

Unfortunately trying to build an out-of-tree kernel module in Rust gives an error like the following:

 error[E0461]: couldn't find crate `core` with expected target triple target-10951614936105594995
  |
  = note: the following crate versions were found:
  crate `core`, target triple target-3759196539525232825: /usr/src/linux-headers-6.2.0-16-generic/rust/libcore.rmeta

It is possible to workaround this problem by downloading the kernel source, copying the right config and running a `make modules_prepare`.

However, this is not an appropriate method for distributing Rust support in the kernel. A more suitable approach would be to use the data provided by the linux-headers package and build out-of-tree kernel modules by simply running "make".

[Test case]

Install the latest lunar/linux 6.2 kernel and try to build a simple hello world kernel module in Rust out-of-tree.

[Fix]

The reason of this problem is that rustc generates the target triple using the path of target.json, instead of the content of target.json. So during the build of linux-headers in the ppa the absolute path of target.json is completely different than the path of the same file when linux-headers is installed, causing a different target triple hash number, therefore rustc detects a mismatch when trying to link against the Rust libraries provided by the kernel.

The solution is generate the target triple using the content of target.json. This change has been merged upstream in rustc, starting with 1.63. However we can't upgrade rustc to 1.63, because the kernel is still enforcing the constraint of using rustc == 1.62.

Therefore the proper solution is to apply only the patch that changes the target triple generation to use the content of target.json.

See also: https://github.com/Rust-for-Linux/linux/issues/792

[Regression potential]

Changing the target triple generation behavior can potentially break users of rustc-1.62. However, considering that the only user of rustc-1.62 is the kernel itself, there is basically zero risk of regressions (there's no reason for any other user to use rustc-1.62, since they can use the stock rustc provided in Ubuntu).

ProblemType: Bug
DistroRelease: Ubuntu 23.04
Package: rustc-1.62 1.62.1+dfsg1-1ubuntu3
ProcVersionSignature: Ubuntu 6.2.0-16.16-generic 6.2.2
Uname: Linux 6.2.0-16-generic x86_64
ApportVersion: 2.26.0-0ubuntu2
Architecture: amd64
CasperMD5CheckResult: pass
Date: Sun Mar 12 22:37:28 2023
InstallationDate: Installed on 2022-07-25 (230 days ago)
InstallationMedia: Ubuntu 22.10 "Kinetic Kudu" - Alpha amd64 (20220724)
SourcePackage: rustc-1.62
UpgradeStatus: Upgraded to lunar on 2023-02-11 (29 days ago)

Revision history for this message
Andrea Righi (arighi) wrote :
Revision history for this message
Andrea Righi (arighi) wrote :

debdiff in attach allows to properly build out-of-tree kernel modules using rustc-1.62, without "refreshing" the content of linux-headers using `make modules_parepare` and without downloading the whole kernel source code (but only using the content provided by linux-headers).

tags: added: patch
Revision history for this message
Simon Chopin (schopin) wrote :

Would it be possible to have some more detailed instructions for the test case than that? :)

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

i guess more minimal test case is to make a `hello world` type of crate, that is built with custom target.json, then change/move that target.json to a new filepath and attempt a rebuild?

Revision history for this message
Andrea Righi (arighi) wrote :

A proper kernel test case can be the following:

 - install the latest lunar/linux 6.2 (only available on ppa:canonical-kernel-team/bootstrap at the moment)

 - try to build the following hello world kernel module:

09:59 ubuntu@lunar$ cat Makefile
NAME=hello_rust

ifndef KERNELRELEASE
ifndef KDIR
KDIR:=/lib/modules/`uname -r`/build
endif
PWD := $(shell pwd)

all:
 $(MAKE) -C $(KDIR) M=$(PWD) modules
install:
 $(MAKE) -C $(KDIR) M=$(PWD) modules_install
clean:
 rm -f *.o *.ko *.mod* .*.cmd *.d Module.symvers modules.order
 rm -rf .tmp_versions
else
 obj-m := $(NAME).o
endif
6.2.0-17-generic ~/hello (master)
09:59 ubuntu@lunar$ cat hello_rust.rs
// SPDX-License-Identifier: GPL-2.0

//! Rust hello world example.

use kernel::prelude::*;

module! {
    type: HelloRust,
    name: "hello_rust",
    author: "Andrea Righi <email address hidden>",
    description: "Rust hello world example",
    license: "GPL",
}

struct HelloRust {
}

impl kernel::Module for HelloRust {
    fn init(_module: &'static ThisModule) -> Result<Self> {
        pr_info!("Hello from Rust\n");

        Ok(HelloRust { })
    }
}

impl Drop for HelloRust {
    fn drop(&mut self) {
        pr_info!("Goodbye from Rust\n");
    }
}
10:02 ubuntu@lunar$ make CROSS_COMPILE=x86_64-linux-gnu- HOSTRUSTC=rustc-1.62 RUSTC=rustc-1.62 BINDGEN=bindgen-0.56 RUSTFMT=rustfmt-1.62 RUST_LIB_SRC=/usr/src/rustc-1.62.1/library
make -C /lib/modules/`uname -r`/build M=/home/ubuntu/hello modules
make[1]: Entering directory '/usr/src/linux-headers-6.2.0-17-generic'
  RUSTC [M] /home/ubuntu/hello/hello_rust.o
  MODPOST /home/ubuntu/hello/Module.symvers
  CC [M] /home/ubuntu/hello/hello_rust.mod.o
  LD [M] /home/ubuntu/hello/hello_rust.ko
  BTF [M] /home/ubuntu/hello/hello_rust.ko
Skipping BTF generation for /home/ubuntu/hello/hello_rust.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-6.2.0-17-generic'
6.2.0-17-generic ~/hello (master)

^ make should complete without errors.

And then module can be loaded:

10:02 ubuntu@lunar$ sudo insmod hello_rust.ko
6.2.0-17-generic ~/hello (master)
10:04 ubuntu@lunar$ sudo dmesg | tail -1
[ 273.332115] hello_rust: Hello from Rust
6.2.0-17-generic ~/hello (master)

Revision history for this message
Andrea Righi (arighi) wrote :

Without the extra fix applied to rustc-1.62 make returns an error like the following:

  RUSTC [M] /home/righiandr/src/rust-examples/hello/hello_rust.o
error[E0461]: couldn't find crate `core` with expected target triple target-10951614936105594995
  |
  = note: the following crate versions were found:
          crate `core`, target triple target-3759196539525232825: /usr/src/linux-headers-6.2.0-16-generic/rust/libcore.rmeta

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

rustc-1.62 already vendors new enough serge json, so no need to do anything there.

Changed in rustc-1.62 (Ubuntu Lunar):
status: New → Fix Committed
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package rustc-1.62 - 1.62.1+dfsg1-1ubuntu4

---------------
rustc-1.62 (1.62.1+dfsg1-1ubuntu4) lunar; urgency=medium

  * Allow to build out-of-tree Rust kernel modules (LP: #2011355):
    - debian/patches/ubuntu-use-serde_json-for-target-spec-json.patch
    - debian/patches/ubuntu-make-debug_triple-depend-on-target-json-file-content.patch

 -- Andrea Righi <email address hidden> Sat, 11 Mar 2023 20:14:30 +0000

Changed in rustc-1.62 (Ubuntu Lunar):
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.