fishinabarrel / linux-kernel-module-rust

Framework for writing Linux kernel modules in safe Rust
GNU General Public License v2.0
1.33k stars 120 forks source link

`-DMODULE` CFLAG doesn't propagate correctly to cargo on Arch Linux #241

Closed Bobo1239 closed 4 years ago

Bobo1239 commented 4 years ago

I'm unfamiliar with the kernel build system but it seems that at least on Arch Linux the c_flags environment variable doesn't contain -DMODULE when cargo is invoked when building the hello-world example. This causes issues since __this_module is then incorrectly defined. It seems -DMODULE is only included in c_flags when invoking ld in the other make target.

c_flags of $(src)/target/x86_64-linux-kernel/debug/libhello_world.a:

c_flags=-Wp,-MD,/home/bobo1239/University/WS2021/rootkit-programming-rs/linux-kernel-module-rust/hello-world/target/x86_64-linux-kernel/debug/.libhello_world.a.d -nostdinc -isystem /usr/lib/clang/10.0.1/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Qunused-arguments -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 -no-integrated-as -Werror=unknown-warning-option -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mstack-alignment=8 -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mretpoline-external-thunk -fno-delete-null-pointer-checks -Wno-address-of-packed-member -O2 -Wframe-larger-than=2048 -fstack-protector-strong -Wno-format-invalid-specifier -Wno-gnu -mno-global-merge -Wno-unused-const-variable -g -gdwarf-4 -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-array-bounds -fno-strict-overflow -fno-merge-all-constants -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -fmacro-prefix-map=./= -fcf-protection=none -Wno-initializer-overrides -Wno-format -Wno-sign-compare -Wno-format-zero-length -Wno-tautological-constant-out-of-range-compare    -DKBUILD_MODFILE='"/home/bobo1239/University/WS2021/rootkit-programming-rs/linux-kernel-module-rust/hello-world/libhello_world"' -DKBUILD_BASENAME='"libhello_world"' -DKBUILD_MODNAME='"libhello_world"'

c_flags of %.rust.o:

c_flags=-Wp,-MD,/home/bobo1239/University/WS2021/rootkit-programming-rs/linux-kernel-module-rust/hello-world/.hello_world.rust.o.d -nostdinc -isystem /usr/lib/clang/10.0.1/include -I./arch/x86/include -I./arch/x86/include/generated  -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -Qunused-arguments -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 -no-integrated-as -Werror=unknown-warning-option -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mstack-alignment=8 -mtune=generic -mno-red-zone -mcmodel=kernel -Wno-sign-compare -fno-asynchronous-unwind-tables -mretpoline-external-thunk -fno-delete-null-pointer-checks -Wno-address-of-packed-member -O2 -Wframe-larger-than=2048 -fstack-protector-strong -Wno-format-invalid-specifier -Wno-gnu -mno-global-merge -Wno-unused-const-variable -g -gdwarf-4 -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-array-bounds -fno-strict-overflow -fno-merge-all-constants -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -fmacro-prefix-map=./= -fcf-protection=none -Wno-initializer-overrides -Wno-format -Wno-sign-compare -Wno-format-zero-length -Wno-tautological-constant-out-of-range-compare  -DMODULE  -DKBUILD_BASENAME='"hello_world.rust"' -DKBUILD_MODNAME='"hello_world.rust"'

(look at the very end of each line)

The issue is probably that the build system thinks libhello_world.a is not part of the module which causes KBUILD_CFLAGS_MODULE=-DMODULE to not be included in c_flags. Unfortunately I'm not sure what the proper way to fix this is. (What does definitely work is just appending the value of KBUILD_CFLAGS_MODULE to the rest of the cflags in build.rs.)

(edit: And surely enough just after posting I see that https://github.com/fishinabarrel/linux-kernel-module-rust/issues/152#issuecomment-672683896 already noticed this problem.)

geofft commented 4 years ago

Yup, I ran into that last night and I don't exactly know why / what the proper fix is, yet. To be fair, ${c_flags} is kind of internal and there's no guarantee that it's all of what we should be using.

Also I wonder if this is actually a change in upstream Kbuild and it's just that Arch/Manjaro use very recent kernel, but nothing sticks out at me yet... It seems like this is probably the part-of-module macro in scripts/Makefile.lib, though.

geofft commented 4 years ago

This is (fortunately?) not Arch-specific - I can repro the same error with Debian unstable's kernel:

root@lkm:~/linux-kernel-module-rust/hello-world# make CLANG=clang-12 KDIR=/lib/modules/5.7.0-2-amd64/build
make -C /lib/modules/5.7.0-2-amd64/build M=/root/linux-kernel-module-rust/hello-world CC=clang-12 CONFIG_CC_IS_CLANG=y
make[1]: Entering directory '/usr/src/linux-headers-5.7.0-2-amd64'
cd /root/linux-kernel-module-rust/hello-world; abs_srctree=/usr/src/linux-headers-5.7.0-2-amd64 cargo build -Z build-std=core,alloc --target=x86_64-linux-kernel
   Compiling linux-kernel-module v0.1.0 (/root/linux-kernel-module-rust)
error[E0425]: cannot find value `__this_module` in module `bindings`
  --> /root/linux-kernel-module-rust/src/chrdev.rs:58:49
   |
58 |                 cdevs[i].owner = &mut bindings::__this_module;
   |                                                 ^^^^^^^^^^^^^ not found in `bindings`

error[E0425]: cannot find value `__this_module` in module `bindings`
  --> /root/linux-kernel-module-rust/src/filesystem.rs:64:44
   |
64 |             owner: unsafe { &mut bindings::__this_module },
   |                                            ^^^^^^^^^^^^^ not found in `bindings`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0425`.
error: could not compile `linux-kernel-module`.

To learn more, run the command again with --verbose.
make[3]: *** [/root/linux-kernel-module-rust/hello-world/Kbuild:10: /root/linux-kernel-module-rust/hello-world/target/x86_64-linux-kernel/debug/libhello_world.a] Error 101
make[2]: *** [/usr/src/linux-headers-5.7.0-2-common/Makefile:1745: /root/linux-kernel-module-rust/hello-world] Error 2
make[1]: *** [/usr/src/linux-headers-5.7.0-2-common/Makefile:180: sub-make] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.7.0-2-amd64'
make: *** [Makefile:9: all] Error 2

5.2 is fine, so it's something in between the two of those....

geofft commented 4 years ago

OK, this seems to be torvalds/linux@986662b90352d79c4842dd7d4e678f50824ed729 from v5.4. I'm guessing the thing we're doing "wrong" here is that our Makefile target is in a subdirectory (target/debug/...) and so the refactored rule doesn't pick it up, but the old rule worked with targets in subdirectories because of the magic of Makefile patterns. Not sure yet what the best thing to do about it is.

alex commented 4 years ago

I think the idea to just add KBUILD_CFLAGS_MODULE=-DMODULE in build.rs sounds fine. Want to send a PR for that?