C2Rust Linux Kernel Module尝试-实践篇

·

5 min read

cargo install --force c2rust --version 0.14.0

报错❌

error: failed to compile `c2rust v0.14.0`, intermediate artifacts can be found at `/tmp/cargo-installNnW8Ru`

Caused by:
  failed to parse manifest at `/root/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.17.2/Cargo.toml`

Caused by:
  feature `edition2021` is required

  this Cargo does not support nightly features, but if you
  switch to nightly channel you can add
  `cargo-features = ["edition2021"]` to enable this feature

这个错误表明,c2rust v0.14.0依赖的once_cell库需要使用Rust 2021 edition的功能,但是你当前使用的Rust版本可能不支持。你需要切换到nightly版本的Rust才能使用这个特性。

可以使用以下命令切换到Rust的nightly版本:✅🌃

rustup default nightly

然后你可以再次尝试安装c2rust v0.14.0

如果你之后想要切换回稳定版的Rust,可以使用:

rustup default stable

值得注意的是,nightly版本的Rust包含一些尚未稳定的功能,可能会有一些不稳定和未预料到的行为。只有当你确实需要这些特性时,才建议使用nightly版本。

└─$ c2rust transpile ./compile_commands.json --emit-no-std \
  --emit-modules -o bareflank-rs "$@"

--emit-no-std: 这个选项告诉c2rust生成的Rust代码不应该依赖于Rust的标准库,也就是说生成的代码可以在不提供Rust标准库的环境中运行,比如裸机或嵌入式环境。
--emit-modules: 这个选项告诉c2rust为每个转换的C源文件生成一个单独的Rust模块。这样的话,每个C源文件就会对应一个.rs文件,而不是全部合并到一个.rs文件中。
-o bareflank-rs: 这个选项指定了转换后的Rust源代码文件的输出目录,即生成的Rust代码会被保存在bareflank-rs这个目录中。
"$@": 这是一个bash脚本的特殊参数,代表所有传递给脚本的参数。在这个上下文中,它代表所有额外传递给c2rust命令的参数。
这个命令的总体目标是将compile_commands.json中描述的C源代码转换成不依赖Rust标准库的Rust源代码,并将结果保存在bareflank-rs目录中,每个C源文件对应一个Rust模块(.rs文件)。

bear -- make -j

bear -- make -j8 CC=clang -C /home/kali/linux-4.19.288  M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules

# -C DIRECTORY, --directory=DIRECTORY
#                               Change to DIRECTORY before doing anything.

这个命令实际上由两部分组成:bear -- 以及其后面的 make 命令。下面我分别对这两部分进行解释:

  1. bear -- :Bear 是一个命令行工具,它的全称是 Build EAR,用于生成编译数据库,通常这个数据库是一个名为 compile_commands.json 的 JSON 文件。这个文件详细地列出了每个文件的编译命令,这对于很多工具(包括一些代码编辑器、静态分析工具、重构工具等)非常有用,因为它们需要知道如何为每个文件构建正确的编译命令。-- 是 Bear 的一个选项,用于告诉 Bear 后面的参数应该被当作是要运行并拦截其编译命令的构建系统。

  2. make -j8 -C /home/kali/linux-4.19.288 M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules :这部分是用 make 工具来构建一个项目。具体来说,-j8 告诉 make 在同一时间最多可以有 8 个任务并行执行;-C /home/kali/linux-4.19.288 告诉 make 切换到 /home/kali/linux-4.19.288 目录,并在这个目录下读取 MakefileM=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux 是传递给 Makefile 的一个参数,通常 M= 被用于指定外部模块的路径modules 是一个 make 的目标,通常这个目标会在你的 Makefile 中定义,用于构建项目中的所有模块。

所以,总的来说,这个命令的意思是:“使用 Bear 工具运行 make 命令,以并行的方式(最多 8 个任务)在指定的目录下构建所有模块,并生成一个名为 compile_commands.json 的编译数据库。”

  1. 转换1

bear 是一个工具,用于生成编译命令的数据库,

└─$  clang --version
Debian clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

└─$ gcc --version
gcc (Debian 12.2.0-14) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  1. -mfunction-return=thunk-extern:这是一个GCC的编译选项,用于改变函数的返回方式。然而,在你的情况下,你正在使用clang编译器,它不支持这个选项,因此需要删除

  2. -fconserve-stack:这个选项在GCC中用于尽可能地减小栈的使用。同样,clang并不支持这个选项,所以需要移除

  3. -mrecord-mcount:这个选项用于支持GCC的一个功能,即ftrace框架。ftrace允许在运行时跟踪和记录函数调用。然而,clang并不支持这个选项,所以需要删除

  4. -ftrivial-auto-var-init=zero:这是一个clang选项,用于将自动变量初始化为0。然而,这个选项在你的情况下被禁用了,提示你需要手动开启。所以我们将它替换为了开启选项 -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang

sed -i -e 's/-mfunction-return=thunk-extern//g' \
       -e 's/-fconserve-stack//g' \
       -e 's/-mrecord-mcount//g' \
       -e 's/-ftrivial-auto-var-init=zero/-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang/g' \
       compile_commands.json
└─$ bear -- make -j8 CC=clang 
make -C /lib/modules/6.1.0-kali7-amd64/build M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules
make[1]: Entering directory '/usr/src/linux-headers-6.1.0-kali7-amd64'
  CC [M]  /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.o
  CC [M]  /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/entry.o
  AS [M]  /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/intrinsics.o
  CC [M]  /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/../../common.o
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'

转换2

  • -mpreferred-stack-boundary=3:这是一个用于优化的GCC选项,它设置堆栈边界对齐。这在 Rust 中是不被支持的,因为 Rust 有自己的内存模型和堆栈管理方式。

    • 告诉 gcc 编译器生成的代码应该尽可能使栈边界对齐到2的3次方(也就是8字节)。这样可以提高程序的性能。但是这个选项在 clang 和 c2rust 中并不被支持。
  • -mindirect-branch=thunk-extern-mindirect-branch-register:这两个选项都是用于控制间接跳转的方式。这是 Intel CPU 对抵抗某种漏洞的控制,如 Spectre 漏洞。这在 Rust 中是不被支持的。

    • 这两个选项是为了支持 Intel 的 Control-flow Enforcement Technology (CET)。CET 是一种防止控制流劫持攻击的技术,如跳转/调用指令劫持(Jump/Call Oriented Programming, JOP/COP)以及返回指令劫持(Return Oriented Programming, ROP)。这两个选项在 clang 和 c2rust 中并不被支持。
  • -fno-allow-store-data-races:这是一个 Clang 的选项,用于禁止在编译期间假定没有数据竞态条件。这在 Rust 中不被支持,因为 Rust 有自己的并发和同步原语。

    • 用于在多线程程序中防止数据竞争。这个选项在 clang 和 c2rust 中并不被支持。
  • -fno-var-tracking-assignments:这是一个用于优化的GCC选项,用于关闭变量跟踪,可以减少调试信息,加快编译速度。这在 Rust 中是不被支持的。

    • 关闭 gcc 的变量跟踪功能。变量跟踪可以帮助调试,但是在某些情况下可能会增加编译时间和内存使用。这个选项在 clang 和 c2rust 中并不被支持。
  • -fconserve-stack:这是一个GCC选项,尽可能减少堆栈使用,用于在内存受限的环境下编译。这在 Rust 中是不被支持的。

    • 应该尽可能少地使用栈空间。这对于栈空间有限的环境非常有用,例如嵌入式系统或内核代码。这个选项在 clang 和 c2rust 中并不被支持。
  • -mrecord-mcount:这个选项在 gcc 中用于 ftrace 功能,但在 rust 中并不支持。

    • 告诉 gcc 在每个函数入口处生成特定的代码,这些代码在运行时可以用于记录函数的调用次数。这对于性能分析代码覆盖率分析非常有用。然而,这个选项在 clang 和 c2rust 中并不被支持。
sed -i \
    -e 's/-mpreferred-stack-boundary=3//g' \
    -e 's/-mindirect-branch=thunk-extern//g' \
    -e 's/-mindirect-branch-register//g' \
    -e 's/-fno-allow-store-data-races//g' \
    -e 's/-fno-var-tracking-assignments//g' \
    -e 's/-fconserve-stack//g' \
    -e 's/-mrecord-mcount//g' \
    compile_commands.json
  1. -falign-jumps=1-fmerge-constants:这两个是优化标志,分别用于控制跳转指令的对齐和合并相同的常量。在 clang 中,这些标志并不被支持。

  2. -mrecord-mcount:这个选项告诉 gcc 在每个函数入口处生成特定的代码,这些代码在运行时可以用于记录函数的调用次数。这对于性能分析和代码覆盖率分析非常有用。然而,这个选项在 clang 和 c2rust 中并不被支持。

添加 -fPIC 选项是因为它让编译器生成位置无关代码(Position Independent Code),这对于生成动态链接库或者被动态链接的代码非常重要。在某些系统中,例如许多 Linux 发行版,使用位置无关代码是强制的。

添加 -std=c99 是因为它指定了你要用的 C 语言标准。因为 C 语言的不同版本之间有一些差异,所以这是必要的。c2rust 可能需要这个信息来正确地转换你的代码。

二次错误

  1. -Wno-format-truncation: 此选项告诉编译器忽略可能会导致字符串截断的格式化字符串警告。如果在c2rust中不受支持,那就需要移除。

  2. -Wno-format-overflow: 此选项告诉编译器忽略可能会导致字符串溢出的格式化字符串警告。如果在c2rust中不受支持,那就需要移除。

  3. -Wno-dangling-pointer: 此选项告诉编译器忽略悬空指针警告。如果在c2rust中不受支持,那就需要移除。

  4. -Wno-stringop-truncation: 此选项告诉编译器忽略可能会导致字符串截断的字符串操作警告。如果在c2rust中不受支持,那就需要移除。

  5. -Wno-zero-length-bounds: 此选项告诉编译器忽略零长度数组边界警告。如果在c2rust中不受支持,那就需要移除。

  6. -Wno-stringop-overflow: 此选项告诉编译器忽略可能会导致字符串溢出的字符串操作警告。如果在c2rust中不受支持,那就需要移除。

  7. -Wno-restrict: 此选项告诉编译器忽略restrict限定符相关警告。如果在c2rust中不受支持,那就需要移除。

  8. -Wno-maybe-uninitialized: 此选项告诉编译器忽略可能会导致使用未初始化变量的警告。如果在c2rust中不受支持,那就需要移除。

  9. -Werror=designated-init: 此选项告诉编译器将设计的初始化警告视为错误。如果在c2rust中不受支持,那就需要移除。

  10. -Wno-packed-not-aligned: 此选项告诉编译器忽略打包但未对齐的警告。如果在c2rust中不受支持,那就需要移除。

  11. -falign-jumps=1: 此选项告诉编译器跳转对齐设置为1。如果在c2rust中不受支持,那就需要移除。

  12. -fmerge-constants: 此选项告诉编译器合并常量。如果在c2rust中不受支持,那就需要移除。

所有这些选项被移除的原因是,c2rust可能不支持这些选项,或者对这些选项的解释和你使用的C编译器不同。如果不移除这些选项,可能会导致c2rust无法正确地解析和转换你的C代码。


└─$ c2rust transpile compile_commands.json 
warning: Skipping existing file /home/kali/hypervisor-2.0/bfdriver/src/common.rs
warning: unknown warning option '-Wno-format-truncation' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-format-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-dangling-pointer' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-truncation'; did you mean '-Wno-string-concatenation'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-zero-length-bounds'; did you mean '-Wno-zero-length-array'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-restrict' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-maybe-uninitialized'; did you mean '-Wno-uninitialized'? [-Wunknown-warning-option]
warning: unknown warning option '-Werror=designated-init' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-packed-not-aligned'; did you mean '-Wno-over-aligned'? [-Wunknown-warning-option]
warning: optimization flag '-falign-jumps=1' is not supported [-Wignored-optimization-argument]
warning: optimization flag '-fmerge-constants' is not supported [-Wignored-optimization-argument]
warning: unknown warning option '-Wno-format-truncation' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-format-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-dangling-pointer' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-truncation'; did you mean '-Wno-string-concatenation'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-zero-length-bounds'; did you mean '-Wno-zero-length-array'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-restrict' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-maybe-uninitialized'; did you mean '-Wno-uninitialized'? [-Wunknown-warning-option]
warning: unknown warning option '-Werror=designated-init' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-packed-not-aligned'; did you mean '-Wno-over-aligned'? [-Wunknown-warning-option]
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
./include/linux/mm.h:2106:15: error: passing 'const char[14]' to parameter of type 'char *' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
                                  poison, "unused kernel");
                                          ^~~~~~~~~~~~~~~
./include/linux/mm.h:2060:24: note: passing argument to parameter 's' here
                                        int poison, char *s);
                                                          ^
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:19:24: warning: c2rust: Cannot translate GNU address of label expression
        __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
                              ^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
                                                               ^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:32:23: warning: c2rust: Cannot translate GNU address of label expression
        __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
                             ^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
                                                               ^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:19:24: warning: c2rust: Cannot translate GNU address of label expression
        __local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
                              ^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
                                                               ^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:32:23: warning: c2rust: Cannot translate GNU address of label expression
        __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
                             ^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
                                                               ^~
14 warnings and 1 error generated.
Error while processing /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c.
sed -i \
    -e 's/-Wno-format-truncation//g' \
    -e 's/-Wno-format-overflow//g' \
    -e 's/-Wno-dangling-pointer//g' \
    -e 's/-Wno-stringop-truncation//g' \
    -e 's/-Wno-zero-length-bounds//g' \
    -e 's/-Wno-stringop-overflow//g' \
    -e 's/-Wno-restrict//g' \
    -e 's/-Wno-maybe-uninitialized//g' \
    -e 's/-Werror=designated-init//g' \
    -e 's/-Wno-packed-not-aligned//g' \
    -e 's/-falign-jumps=1//g' \
    -e 's/-fmerge-constants//g' \
    compile_commands.json