Commit 2c815938 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 57865f39 19843452
...@@ -16,7 +16,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file. ...@@ -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 ...@@ -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 $< ...@@ -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 @@ macro_rules! impl_zeroable { ...@@ -1292,8 +1292,15 @@ macro_rules! 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 @@ ...@@ -65,7 +65,7 @@
/// 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 { ...@@ -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 @@ ...@@ -35,18 +35,6 @@
/// 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 { ...@@ -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,6 +210,22 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { ...@@ -221,6 +210,22 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
kernel::ThisModule::from_ptr(core::ptr::null_mut()) kernel::ThisModule::from_ptr(core::ptr::null_mut())
}}; }};
// Double nested modules, since then nobody can access the public items inside.
mod __module_init {{
mod __module_init {{
use super::super::{type_};
/// 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;
// Loadable modules need to export the `{{init,cleanup}}_module` identifiers. // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
/// # Safety /// # Safety
/// ///
...@@ -231,14 +236,23 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { ...@@ -231,14 +236,23 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
#[no_mangle] #[no_mangle]
#[link_section = \".init.text\"] #[link_section = \".init.text\"]
pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{ pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
__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.
unsafe {{ __init() }}
}} }}
#[cfg(MODULE)] #[cfg(MODULE)]
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
pub extern \"C\" fn cleanup_module() {{ pub extern \"C\" fn cleanup_module() {{
__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 `init_module` has returned `0`
// (which delegates to `__init`).
unsafe {{ __exit() }}
}} }}
// Built-in modules are initialized through an initcall pointer // Built-in modules are initialized through an initcall pointer
...@@ -264,19 +278,35 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream { ...@@ -264,19 +278,35 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
__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
// placement above in the initcall section.
unsafe {{ __init() }}
}} }}
#[cfg(not(MODULE))] #[cfg(not(MODULE))]
#[doc(hidden)] #[doc(hidden)]
#[no_mangle] #[no_mangle]
pub extern \"C\" fn __{name}_exit() {{ pub extern \"C\" fn __{name}_exit() {{
__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() }}
}} }}
fn __init() -> core::ffi::c_int {{ /// # Safety
match <{type_} as kernel::Module>::init(&THIS_MODULE) {{ ///
/// 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) => {{ 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 {{ unsafe {{
__MOD = Some(m); __MOD = Some(m);
}} }}
...@@ -288,7 +318,15 @@ fn __init() -> core::ffi::c_int {{ ...@@ -288,7 +318,15 @@ fn __init() -> core::ffi::c_int {{
}} }}
}} }}
fn __exit() {{ /// # 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 {{ unsafe {{
// Invokes `drop()` on `__MOD`, which should be used for cleanup. // Invokes `drop()` on `__MOD`, which should be used for cleanup.
__MOD = None; __MOD = None;
...@@ -296,6 +334,8 @@ fn __exit() {{ ...@@ -296,6 +334,8 @@ fn __exit() {{
}} }}
{modinfo} {modinfo}
}}
}}
", ",
type_ = info.type_, type_ = info.type_,
name = info.name, name = info.name,
......
...@@ -273,7 +273,7 @@ rust_common_cmd = \ ...@@ -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 \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment