Rust fixes for v6.9
- Soundness: make internal functions generated by the 'module!' macro inaccessible, do not implement 'Zeroable' for 'Infallible' and require 'Send' for the 'Module' trait. - Build: avoid errors with "empty" files and workaround 'rustdoc' ICE. - Kconfig: depend on '!CFI_CLANG' and avoid selecting 'CONSTRUCTORS'. - Code docs: remove non-existing key from 'module!' macro example. - Docs: trivial rendering fix in arch table. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmYtL80ACgkQGXyLc2ht IW3MvA//SwYchw/ydVO/OrDV/tkH4E7vjFYIUm+AJvOpaBJUMGusFpdn0gtl7bQ8 x4z09Y96Hn9yweejcsUvLSEyx8JBhTZ+z5/hL5FAw8atBUWnoSCoNdR+CJs/10aE 3hRt/Zts5LEdy0CuTb3S8GOJkMCa9RE9X0XPu6M8xIq7oU4RlOl2OANy2JDT8QJq A8nMESOvBc1SmWimc7gl1rBO9HmRkdSxalRDuAyDv3JCTgynoJFftRVOZfDhJgZ2 gIX0c9rLTNzxPmykAC0Ck4+WzU6/h3nPoZauUPjssV4KK1UgrSSveWoRBLA/Js+L GVOvb6VCthZj77wAYhojc7erjAEzrxHQ2aGlfZhQntzxIs3eagZEFE+y7HwId9LZ ybGaATUXz9oj6Vfh/LReM54SKbzBYzdiVO0HwJQE2CQuZjjEn7KxMtl0Vq+SRO+I Fa6Cd9qOxFeUv7e8xym5CVGEW2KokJEsroRmINusZJ2dk0LxLNDl9f6IAAKhUuJo vGggMBn1FvYJLmMtDGFYacZr3B42Xn0ANd30Lf3uOxvpSDxeghA3A7LoyXdzM2Qu twf6nvFOx7h1a68fbmbusnJY8G999t4Inc3htTAoFgYZiQ4UzLBLNEsFtlq4xmz8 DNjfmFMAOQis2dzBkyVXQzKgRuUqK4UZpQFuBq9EqVT469RMsro= =WaUJ -----END PGP SIGNATURE----- Merge tag 'rust-fixes-6.9' of https://github.com/Rust-for-Linux/linux Pull Rust fixes from Miguel Ojeda: - Soundness: make internal functions generated by the 'module!' macro inaccessible, do not implement 'Zeroable' for 'Infallible' and require 'Send' for the 'Module' trait. - Build: avoid errors with "empty" files and workaround 'rustdoc' ICE. - Kconfig: depend on '!CFI_CLANG' and avoid selecting 'CONSTRUCTORS'. - Code docs: remove non-existing key from 'module!' macro example. - Docs: trivial rendering fix in arch table. * tag 'rust-fixes-6.9' of https://github.com/Rust-for-Linux/linux: rust: remove `params` from `module` macro example kbuild: rust: force `alloc` extern to allow "empty" Rust files kbuild: rust: remove unneeded `@rustc_cfg` to avoid ICE rust: kernel: require `Send` for `Module` implementations rust: phy: implement `Send` for `Registration` rust: make mutually exclusive with CFI_CLANG rust: macros: fix soundness issue in `module!` macro rust: init: remove impl Zeroable for Infallible docs: rust: fix improper rendering in Arch Support page rust: don't select CONSTRUCTORS
This commit is contained in:
commit
2c81593889
|
@ -16,7 +16,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
|
||||||
Architecture Level of support Constraints
|
Architecture Level of support Constraints
|
||||||
============= ================ ==============================================
|
============= ================ ==============================================
|
||||||
``arm64`` Maintained Little Endian only.
|
``arm64`` Maintained Little Endian only.
|
||||||
``loongarch`` Maintained -
|
``loongarch`` Maintained \-
|
||||||
``um`` Maintained ``x86_64`` only.
|
``um`` Maintained ``x86_64`` only.
|
||||||
``x86`` Maintained ``x86_64`` only.
|
``x86`` Maintained ``x86_64`` only.
|
||||||
============= ================ ==============================================
|
============= ================ ==============================================
|
||||||
|
|
|
@ -1899,11 +1899,11 @@ config RUST
|
||||||
bool "Rust support"
|
bool "Rust support"
|
||||||
depends on HAVE_RUST
|
depends on HAVE_RUST
|
||||||
depends on RUST_IS_AVAILABLE
|
depends on RUST_IS_AVAILABLE
|
||||||
|
depends on !CFI_CLANG
|
||||||
depends on !MODVERSIONS
|
depends on !MODVERSIONS
|
||||||
depends on !GCC_PLUGINS
|
depends on !GCC_PLUGINS
|
||||||
depends on !RANDSTRUCT
|
depends on !RANDSTRUCT
|
||||||
depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
|
depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
|
||||||
select CONSTRUCTORS
|
|
||||||
help
|
help
|
||||||
Enables Rust support in the kernel.
|
Enables Rust support in the kernel.
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,6 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
|
||||||
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
|
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
|
||||||
OBJTREE=$(abspath $(objtree)) \
|
OBJTREE=$(abspath $(objtree)) \
|
||||||
$(RUSTDOC) --test $(rust_flags) \
|
$(RUSTDOC) --test $(rust_flags) \
|
||||||
@$(objtree)/include/generated/rustc_cfg \
|
|
||||||
-L$(objtree)/$(obj) --extern alloc --extern kernel \
|
-L$(objtree)/$(obj) --extern alloc --extern kernel \
|
||||||
--extern build_error --extern macros \
|
--extern build_error --extern macros \
|
||||||
--extern bindings --extern uapi \
|
--extern bindings --extern uapi \
|
||||||
|
|
|
@ -1292,8 +1292,15 @@ impl_zeroable! {
|
||||||
i8, i16, i32, i64, i128, isize,
|
i8, i16, i32, i64, i128, isize,
|
||||||
f32, f64,
|
f32, f64,
|
||||||
|
|
||||||
// SAFETY: These are ZSTs, there is nothing to zero.
|
// Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
|
||||||
{<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, Infallible, (),
|
// creating an instance of an uninhabited type is immediate undefined behavior. For more on
|
||||||
|
// uninhabited/empty types, consult The Rustonomicon:
|
||||||
|
// <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
|
||||||
|
// also has information on undefined behavior:
|
||||||
|
// <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
|
||||||
|
//
|
||||||
|
// SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
|
||||||
|
{<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
|
||||||
|
|
||||||
// SAFETY: Type is allowed to take any value, including all zeros.
|
// SAFETY: Type is allowed to take any value, including all zeros.
|
||||||
{<T>} MaybeUninit<T>,
|
{<T>} MaybeUninit<T>,
|
||||||
|
|
|
@ -65,7 +65,7 @@ const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
|
||||||
/// The top level entrypoint to implementing a kernel module.
|
/// The top level entrypoint to implementing a kernel module.
|
||||||
///
|
///
|
||||||
/// For any teardown or cleanup operations, your type may implement [`Drop`].
|
/// For any teardown or cleanup operations, your type may implement [`Drop`].
|
||||||
pub trait Module: Sized + Sync {
|
pub trait Module: Sized + Sync + Send {
|
||||||
/// Called at module initialization time.
|
/// Called at module initialization time.
|
||||||
///
|
///
|
||||||
/// Use this method to perform whatever setup or registration your module
|
/// Use this method to perform whatever setup or registration your module
|
||||||
|
|
|
@ -640,6 +640,10 @@ pub struct Registration {
|
||||||
drivers: Pin<&'static mut [DriverVTable]>,
|
drivers: Pin<&'static mut [DriverVTable]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do
|
||||||
|
// from any thread because `phy_drivers_unregister` can be called from any thread context.
|
||||||
|
unsafe impl Send for Registration {}
|
||||||
|
|
||||||
impl Registration {
|
impl Registration {
|
||||||
/// Registers a PHY driver.
|
/// Registers a PHY driver.
|
||||||
pub fn register(
|
pub fn register(
|
||||||
|
|
|
@ -35,18 +35,6 @@ use proc_macro::TokenStream;
|
||||||
/// author: "Rust for Linux Contributors",
|
/// author: "Rust for Linux Contributors",
|
||||||
/// description: "My very own kernel module!",
|
/// description: "My very own kernel module!",
|
||||||
/// license: "GPL",
|
/// license: "GPL",
|
||||||
/// params: {
|
|
||||||
/// my_i32: i32 {
|
|
||||||
/// default: 42,
|
|
||||||
/// permissions: 0o000,
|
|
||||||
/// description: "Example of i32",
|
|
||||||
/// },
|
|
||||||
/// writeable_i32: i32 {
|
|
||||||
/// default: 42,
|
|
||||||
/// permissions: 0o644,
|
|
||||||
/// description: "Example of i32",
|
|
||||||
/// },
|
|
||||||
/// },
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// struct MyModule;
|
/// struct MyModule;
|
||||||
|
|
|
@ -199,17 +199,6 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
|
||||||
/// Used by the printing macros, e.g. [`info!`].
|
/// Used by the printing macros, e.g. [`info!`].
|
||||||
const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
|
const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
|
||||||
|
|
||||||
/// The \"Rust loadable module\" mark.
|
|
||||||
//
|
|
||||||
// This may be best done another way later on, e.g. as a new modinfo
|
|
||||||
// key or a new section. For the moment, keep it simple.
|
|
||||||
#[cfg(MODULE)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[used]
|
|
||||||
static __IS_RUST_MODULE: () = ();
|
|
||||||
|
|
||||||
static mut __MOD: Option<{type_}> = None;
|
|
||||||
|
|
||||||
// SAFETY: `__this_module` is constructed by the kernel at load time and will not be
|
// SAFETY: `__this_module` is constructed by the kernel at load time and will not be
|
||||||
// freed until the module is unloaded.
|
// freed until the module is unloaded.
|
||||||
#[cfg(MODULE)]
|
#[cfg(MODULE)]
|
||||||
|
@ -221,81 +210,132 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
|
||||||
kernel::ThisModule::from_ptr(core::ptr::null_mut())
|
kernel::ThisModule::from_ptr(core::ptr::null_mut())
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
|
// Double nested modules, since then nobody can access the public items inside.
|
||||||
/// # Safety
|
mod __module_init {{
|
||||||
///
|
mod __module_init {{
|
||||||
/// This function must not be called after module initialization, because it may be
|
use super::super::{type_};
|
||||||
/// freed after that completes.
|
|
||||||
#[cfg(MODULE)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[no_mangle]
|
|
||||||
#[link_section = \".init.text\"]
|
|
||||||
pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
|
|
||||||
__init()
|
|
||||||
}}
|
|
||||||
|
|
||||||
#[cfg(MODULE)]
|
/// The \"Rust loadable module\" mark.
|
||||||
#[doc(hidden)]
|
//
|
||||||
#[no_mangle]
|
// This may be best done another way later on, e.g. as a new modinfo
|
||||||
pub extern \"C\" fn cleanup_module() {{
|
// key or a new section. For the moment, keep it simple.
|
||||||
__exit()
|
#[cfg(MODULE)]
|
||||||
}}
|
#[doc(hidden)]
|
||||||
|
#[used]
|
||||||
|
static __IS_RUST_MODULE: () = ();
|
||||||
|
|
||||||
// Built-in modules are initialized through an initcall pointer
|
static mut __MOD: Option<{type_}> = None;
|
||||||
// and the identifiers need to be unique.
|
|
||||||
#[cfg(not(MODULE))]
|
|
||||||
#[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[link_section = \"{initcall_section}\"]
|
|
||||||
#[used]
|
|
||||||
pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
|
|
||||||
|
|
||||||
#[cfg(not(MODULE))]
|
// Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
|
||||||
#[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
|
/// # Safety
|
||||||
core::arch::global_asm!(
|
///
|
||||||
r#\".section \"{initcall_section}\", \"a\"
|
/// This function must not be called after module initialization, because it may be
|
||||||
__{name}_initcall:
|
/// freed after that completes.
|
||||||
.long __{name}_init - .
|
#[cfg(MODULE)]
|
||||||
.previous
|
#[doc(hidden)]
|
||||||
\"#
|
#[no_mangle]
|
||||||
);
|
#[link_section = \".init.text\"]
|
||||||
|
pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
|
||||||
|
// SAFETY: This function is inaccessible to the outside due to the double
|
||||||
|
// module wrapping it. It is called exactly once by the C side via its
|
||||||
|
// unique name.
|
||||||
|
unsafe {{ __init() }}
|
||||||
|
}}
|
||||||
|
|
||||||
#[cfg(not(MODULE))]
|
#[cfg(MODULE)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
|
pub extern \"C\" fn cleanup_module() {{
|
||||||
__init()
|
// SAFETY:
|
||||||
}}
|
// - This function is inaccessible to the outside due to the double
|
||||||
|
// module wrapping it. It is called exactly once by the C side via its
|
||||||
|
// unique name,
|
||||||
|
// - furthermore it is only called after `init_module` has returned `0`
|
||||||
|
// (which delegates to `__init`).
|
||||||
|
unsafe {{ __exit() }}
|
||||||
|
}}
|
||||||
|
|
||||||
#[cfg(not(MODULE))]
|
// Built-in modules are initialized through an initcall pointer
|
||||||
#[doc(hidden)]
|
// and the identifiers need to be unique.
|
||||||
#[no_mangle]
|
#[cfg(not(MODULE))]
|
||||||
pub extern \"C\" fn __{name}_exit() {{
|
#[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
|
||||||
__exit()
|
#[doc(hidden)]
|
||||||
}}
|
#[link_section = \"{initcall_section}\"]
|
||||||
|
#[used]
|
||||||
|
pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
|
||||||
|
|
||||||
fn __init() -> core::ffi::c_int {{
|
#[cfg(not(MODULE))]
|
||||||
match <{type_} as kernel::Module>::init(&THIS_MODULE) {{
|
#[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
|
||||||
Ok(m) => {{
|
core::arch::global_asm!(
|
||||||
unsafe {{
|
r#\".section \"{initcall_section}\", \"a\"
|
||||||
__MOD = Some(m);
|
__{name}_initcall:
|
||||||
|
.long __{name}_init - .
|
||||||
|
.previous
|
||||||
|
\"#
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(not(MODULE))]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
|
||||||
|
// SAFETY: This function is inaccessible to the outside due to the double
|
||||||
|
// module wrapping it. It is called exactly once by the C side via its
|
||||||
|
// placement above in the initcall section.
|
||||||
|
unsafe {{ __init() }}
|
||||||
|
}}
|
||||||
|
|
||||||
|
#[cfg(not(MODULE))]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern \"C\" fn __{name}_exit() {{
|
||||||
|
// SAFETY:
|
||||||
|
// - This function is inaccessible to the outside due to the double
|
||||||
|
// module wrapping it. It is called exactly once by the C side via its
|
||||||
|
// unique name,
|
||||||
|
// - furthermore it is only called after `__{name}_init` has returned `0`
|
||||||
|
// (which delegates to `__init`).
|
||||||
|
unsafe {{ __exit() }}
|
||||||
|
}}
|
||||||
|
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function must only be called once.
|
||||||
|
unsafe fn __init() -> core::ffi::c_int {{
|
||||||
|
match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
|
||||||
|
Ok(m) => {{
|
||||||
|
// SAFETY: No data race, since `__MOD` can only be accessed by this
|
||||||
|
// module and there only `__init` and `__exit` access it. These
|
||||||
|
// functions are only called once and `__exit` cannot be called
|
||||||
|
// before or during `__init`.
|
||||||
|
unsafe {{
|
||||||
|
__MOD = Some(m);
|
||||||
|
}}
|
||||||
|
return 0;
|
||||||
|
}}
|
||||||
|
Err(e) => {{
|
||||||
|
return e.to_errno();
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
return 0;
|
|
||||||
}}
|
}}
|
||||||
Err(e) => {{
|
|
||||||
return e.to_errno();
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function must
|
||||||
|
/// - only be called once,
|
||||||
|
/// - be called after `__init` has been called and returned `0`.
|
||||||
|
unsafe fn __exit() {{
|
||||||
|
// SAFETY: No data race, since `__MOD` can only be accessed by this module
|
||||||
|
// and there only `__init` and `__exit` access it. These functions are only
|
||||||
|
// called once and `__init` was already called.
|
||||||
|
unsafe {{
|
||||||
|
// Invokes `drop()` on `__MOD`, which should be used for cleanup.
|
||||||
|
__MOD = None;
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
{modinfo}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
fn __exit() {{
|
|
||||||
unsafe {{
|
|
||||||
// Invokes `drop()` on `__MOD`, which should be used for cleanup.
|
|
||||||
__MOD = None;
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
|
|
||||||
{modinfo}
|
|
||||||
",
|
",
|
||||||
type_ = info.type_,
|
type_ = info.type_,
|
||||||
name = info.name,
|
name = info.name,
|
||||||
|
|
|
@ -273,7 +273,7 @@ rust_common_cmd = \
|
||||||
-Zallow-features=$(rust_allowed_features) \
|
-Zallow-features=$(rust_allowed_features) \
|
||||||
-Zcrate-attr=no_std \
|
-Zcrate-attr=no_std \
|
||||||
-Zcrate-attr='feature($(rust_allowed_features))' \
|
-Zcrate-attr='feature($(rust_allowed_features))' \
|
||||||
--extern alloc --extern kernel \
|
-Zunstable-options --extern force:alloc --extern kernel \
|
||||||
--crate-type rlib -L $(objtree)/rust/ \
|
--crate-type rlib -L $(objtree)/rust/ \
|
||||||
--crate-name $(basename $(notdir $@)) \
|
--crate-name $(basename $(notdir $@)) \
|
||||||
--sysroot=/dev/null \
|
--sysroot=/dev/null \
|
||||||
|
|
Loading…
Reference in New Issue