History

Merge tag 'rust-fixes-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux

Pull Rust fixes from Miguel Ojeda: "Toolchain and infrastructure: - Fix KCFI failures, such as in Rust doctests, by disabling function merging when CFI is enabled. Gary reported the LLVM bug to upstream and it is now fixed in their mainline. - Fix 'objtool' fallthrough warnings under the experimental 'CONFIG_RUST_INLINE_HELPERS' by passing (for the combined Rust and helpers code) the LLVM options needed to preserve the unreachable traps that 'rustc' normally emits. In addition, fix 'objtool' errors when LTO is enabled on top, by also filtering out the LTO flags (for the combined Rust and helpers code) so that the traps are kept in place. - Fix 'objtool' warnings by adding one more 'noreturn' function. - Fix 'make rusttest' target when the 'rustc-dev' component is installed and Rust >= 1.82.0, <= 1.87.0 is used. 'kernel' crate: - 'num' module: fix soundness issue in the 'Bounded' conversion from 'bool' by restricting the conversions to unsigned 'Bounded'. - 'jump_label' module: fix future 'make rusttest' target failures when 'ARCH=' is set to an arch different than the host's. - 'list' module: fix incorrect 'pop_back()' comment" * tag 'rust-fixes-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux: rust: kbuild: disambiguate `zerocopy_derive` for `rusttest` rust: num: restrict bool conversion to unsigned Bounded kbuild: rust: keep Rust objects out of Clang LTO with inline helpers kbuild: rust: preserve unreachable traps with inline helpers rust: cfi: disable function merging if CFI is enabled rust: jump_label: skip arch-specific asm in `testlib` builds objtool/rust: add one more `noreturn` Rust function rust: kernel: list: fix incorrect pop_back example comment

Linus Torvalds committed 2 months ago

Commit f59c0742 parents 0fe792f 1b0bab47 files · +53 −14Browse files

Unified · Split

7 files
  1. Makefile +12 −1
  2. rust/Makefile +4 −2
  3. rust/kernel/jump_label.rs +12 −0
  4. rust/kernel/list.rs +1 −1
  5. rust/kernel/num/bounded.rs +21 −9
  6. scripts/Makefile.build +2 −1
  7. tools/objtool/check.c +1 −0
Makefile+12−1
@@ -1083,6 +1083,16 @@ endif · 1082 unmodified lines
10831083 export CC_FLAGS_SCS
10841084 endif
10851085
1086+ifdef CONFIG_RUST_INLINE_HELPERS
1087+# `rustc` normally emits traps for unreachable paths during code generation.
1088+# With inline helpers, Clang performs code generation from the linked bitcode
1089+# instead, so request the same behavior explicitly. Otherwise `objtool` may
1090+# follow an impossible Rust path into the next function.
1091+CC_FLAGS_RUST_INLINE_HELPERS := -mllvm -trap-unreachable \
1092+ -mllvm -no-trap-after-noreturn
1093+export CC_FLAGS_RUST_INLINE_HELPERS
1094+endif
1095+
10861096 ifdef CONFIG_LTO_CLANG
10871097 ifdef CONFIG_LTO_CLANG_FULL
10881098 CC_FLAGS_LTO := -flto
@@ -1118,7 +1128,8 @@ endif · 29 unmodified lines
11181128 ifdef CONFIG_RUST
11191129 # Always pass -Zsanitizer-cfi-normalize-integers as CONFIG_RUST selects
11201130 # CONFIG_CFI_ICALL_NORMALIZE_INTEGERS.
1121− RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers
1131+ # Disable function merging as LLVM incorrectly merges functions with different KCFI types.
1132+ RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zmerge-functions=disabled
11221133 KBUILD_RUSTFLAGS += $(RUSTC_FLAGS_CFI)
11231134 export RUSTC_FLAGS_CFI
11241135 endif
rust/Makefile+4−2
@@ -354,7 +354,8 @@ rusttestlib-pin_init: $(src)/pin-init/src/lib.rs rusttestlib-macros \ · 353 unmodified lines
354354 rusttestlib-kernel: private rustc_target_flags = --extern ffi \
355355 --extern build_error --extern macros --extern pin_init \
356356 --extern bindings --extern uapi \
357− --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib --extern zerocopy_derive
357+ --extern zerocopy=$(objtree)/$(obj)/test/libzerocopy.rlib \
358+ --extern zerocopy_derive=$(objtree)/$(obj)/test/$(libzerocopy_derive_name)
358359 rusttestlib-kernel: $(src)/kernel/lib.rs rusttestlib-bindings rusttestlib-uapi \
359360 rusttestlib-build_error rusttestlib-pin_init $(obj)/$(libmacros_name) \
360361 $(obj)/bindings.o rusttestlib-zerocopy rusttestlib-zerocopy_derive FORCE
@@ -656,7 +657,8 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L · 295 unmodified lines
656657 -Zunstable-options \
657658 $(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
658659 $(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
659− $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
660+ $(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
661+ $(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
660662 $(cmd_ld_single)) \
661663 $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
662664 $(cmd_objtool)
rust/kernel/jump_label.rs+12−0
@@ -44,6 +44,7 @@ const _: &str = include!(concat!( · 43 unmodified lines
4444
4545 #[macro_export]
4646 #[doc(hidden)]
47+#[cfg(not(testlib))]
4748 #[cfg(CONFIG_JUMP_LABEL)]
4849 macro_rules! arch_static_branch {
4950 ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {'my_label: {
@@ -61,6 +62,17 @@ macro_rules! arch_static_branch { · 11 unmodified lines
6162 }};
6263 }
6364
65+#[macro_export]
66+#[doc(hidden)]
67+#[cfg(testlib)]
68+#[cfg(CONFIG_JUMP_LABEL)]
69+macro_rules! arch_static_branch {
70+ ($key:path, $keytyp:ty, $field:ident, $branch:expr) => {
71+ // The asm falls through until patched, which never happens on the host.
72+ false
73+ };
74+}
75+
6476 #[cfg(CONFIG_JUMP_LABEL)]
6577 pub use arch_static_branch;
6678
rust/kernel/list.rs+1−1
@@ -249,7 +249,7 @@ pub use self::arc_field::{ · 248 unmodified lines
249249 /// assert_eq!(list.iter().count(), 3);
250250 /// }
251251 ///
252−/// // Pop the items from the list using `pop_front()` and verify the content.
252+/// // Pop the items from the list using `pop_back()` and verify the content.
253253 /// {
254254 /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15));
255255 /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
rust/kernel/num/bounded.rs+21−9
@@ -13,7 +13,10 @@ use core::{ · 12 unmodified lines
1313 };
1414
1515 use kernel::{
16− num::Integer,
16+ num::{
17+ Integer,
18+ Unsigned, //
19+ },
1720 prelude::*, //
1821 };
1922
@@ -174,13 +177,16 @@ fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool { · 154 unmodified lines
174177 /// // `u8` (regardless of the passed value).
175178 /// // let _ = Bounded::<u32, 6>::from(10u8);
176179 ///
177−/// // Booleans can be converted into single-bit `Bounded`s.
180+/// // Booleans can be converted into unsigned `Bounded`s.
178181 ///
179182 /// let v = Bounded::<u64, 1>::from(false);
180183 /// assert_eq!(v.get(), 0);
181184 ///
182185 /// let v = Bounded::<u64, 1>::from(true);
183186 /// assert_eq!(v.get(), 1);
187+///
188+/// // This does not build because `i8` is signed.
189+/// // let _ = Bounded::<i8, 2>::from(true);
184190 /// ```
185191 ///
186192 /// Infallible conversions from a [`Bounded`] to a primitive integer are also supported, and
@@ -203,12 +209,16 @@ fn fits_within<T: Integer>(value: T, num_bits: u32) -> bool { · 16 unmodified lines
203209 /// let _v = Bounded::<u32, 10>::new::<10>();
204210 /// // assert_eq!(u8::from(_v), 10);
205211 ///
206−/// // Single-bit `Bounded`s can be converted into a boolean.
212+/// // Unsigned single-bit `Bounded`s can be converted into a boolean.
207213 /// let v = Bounded::<u8, 1>::new::<1>();
208214 /// assert_eq!(bool::from(v), true);
209215 ///
210216 /// let v = Bounded::<u8, 1>::new::<0>();
211217 /// assert_eq!(bool::from(v), false);
218+///
219+/// // This does not build because `i8` is signed.
220+/// // let v = Bounded::<i8, 1>::new::<-1>();
221+/// // let _ = bool::from(v);
212222 /// ```
213223 ///
214224 /// Fallible conversions from any primitive integer to any [`Bounded`] are also supported using the
@@ -1109,31 +1119,33 @@ impl_into_primitive!( · 894 unmodified lines
11091119 i8 i16 i32 i64 isize
11101120 );
11111121
1112−// Single-bit `Bounded`s can be converted from/to a boolean.
1122+// Unsigned single-bit `Bounded`s can be converted to a boolean.
11131123
11141124 impl<T> From<Bounded<T, 1>> for bool
11151125 where
1116− T: Integer + Zeroable,
1126+ T: Integer<Signedness = Unsigned> + Zeroable,
11171127 {
11181128 fn from(value: Bounded<T, 1>) -> Self {
11191129 value.get() != Zeroable::zeroed()
11201130 }
11211131 }
11221132
1133+// Booleans can be converted to unsigned `Bounded`s.
1134+
11231135 impl<T, const N: u32> From<bool> for Bounded<T, N>
11241136 where
1125− T: Integer + From<bool>,
1137+ T: Integer<Signedness = Unsigned> + From<bool>,
11261138 {
11271139 fn from(value: bool) -> Self {
1128− // SAFETY: A boolean can be represented using a single bit, and thus fits within any
1129− // integer type for any `N` > 0.
1140+ // SAFETY: A boolean is represented by `0` or `1`, so it fits within any valid unsigned
1141+ // `Bounded` width.
11301142 unsafe { Self::__new(T::from(value)) }
11311143 }
11321144 }
11331145
11341146 impl<T> Bounded<T, 1>
11351147 where
1136− T: Integer + Zeroable,
1148+ T: Integer<Signedness = Unsigned> + Zeroable,
11371149 {
11381150 /// Converts this [`Bounded`] into a [`bool`].
11391151 ///
scripts/Makefile.build+2−1
@@ -347,7 +347,8 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@ · 346 unmodified lines
347347 cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
348348 $(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
349349 $(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
350− $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
350+ $(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
351+ $(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
351352 $(cmd_ld_single)) \
352353 $(cmd_objtool)
353354
tools/objtool/check.c+1−0
@@ -196,6 +196,7 @@ static bool is_rust_noreturn(const struct symbol *func) · 195 unmodified lines
196196 return str_ends_with(func->name, "_4core3num20from_str_radix_panic") ||
197197 str_ends_with(func->name, "_4core3num22from_ascii_radix_panic") ||
198198 str_ends_with(func->name, "_4core3num28from_ascii_bytes_radix_panic") ||
199+ str_ends_with(func->name, "_4core3str16slice_error_fail") ||
199200 str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail") ||
200201 str_ends_with(func->name, "_4core6option13expect_failed") ||
201202 str_ends_with(func->name, "_4core6option13unwrap_failed") ||