Skip to content

Commit c84d574

Browse files
committed
Merge tag 'modules-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux
Pull module updates from Daniel Gomez: "Rust module parameter support: - Add Rust module parameter support, enabling Rust kernel modules to declare and use module parameters. The rust_minimal sample module demonstrates this, and the rust null block driver will be the first to use it in the next cycle. This also adds the Rust module files under the modules subsystem as agreed between the Rust and modules maintainers. Hardening: - Add compile-time check for embedded NUL characters in MODULE_*() macros. This module metadata was once used (and maybe still) to bypass license enforcement (LWN article from 2003): https://lwn.net/Articles/82305/ [1] MAINTAINERS: - Add Aaron Tomlin as reviewer for the Modules subsystem" * tag 'modules-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux: MAINTAINERS: Add myself as reviewer for module support module: Add compile-time check for embedded NUL characters media: radio: si470x: Fix DRIVER_AUTHOR macro definition media: dvb-usb-v2: lmedm04: Fix firmware macro definitions modules: add rust modules files to MAINTAINERS rust: samples: add a module parameter to the rust_minimal sample rust: module: update the module macro with module parameter support rust: module: use a reference in macros::module::module rust: introduce module_param module rust: str: add radix prefixed integer parsing functions rust: sync: add `SetOnce`
2 parents 416f99c + 1ddac5c commit c84d574

14 files changed

Lines changed: 717 additions & 27 deletions

File tree

MAINTAINERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17522,6 +17522,7 @@ M: Luis Chamberlain <mcgrof@kernel.org>
1752217522
M: Petr Pavlu <petr.pavlu@suse.com>
1752317523
M: Daniel Gomez <da.gomez@kernel.org>
1752417524
R: Sami Tolvanen <samitolvanen@google.com>
17525+
R: Aaron Tomlin <atomlin@atomlin.com>
1752517526
L: linux-modules@vger.kernel.org
1752617527
L: linux-kernel@vger.kernel.org
1752717528
S: Maintained
@@ -17531,6 +17532,8 @@ F: include/linux/module*.h
1753117532
F: kernel/module/
1753217533
F: lib/test_kmod.c
1753317534
F: lib/tests/module/
17535+
F: rust/kernel/module_param.rs
17536+
F: rust/macros/module.rs
1753417537
F: scripts/module*
1753517538
F: tools/testing/selftests/kmod/
1753617539
F: tools/testing/selftests/module/

drivers/media/radio/si470x/radio-si470x-i2c.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
/* driver definitions */
13-
#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
13+
#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"
1414
#define DRIVER_CARD "Silicon Labs Si470x FM Radio"
1515
#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
1616
#define DRIVER_VERSION "1.0.2"

drivers/media/usb/dvb-usb-v2/lmedm04.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@
7070
#include "ts2020.h"
7171

7272

73-
#define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw";
74-
#define LME2510_C_LG "dvb-usb-lme2510c-lg.fw";
75-
#define LME2510_C_S0194 "dvb-usb-lme2510c-s0194.fw";
76-
#define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw";
77-
#define LME2510_LG "dvb-usb-lme2510-lg.fw";
78-
#define LME2510_S0194 "dvb-usb-lme2510-s0194.fw";
73+
#define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw"
74+
#define LME2510_C_LG "dvb-usb-lme2510c-lg.fw"
75+
#define LME2510_C_S0194 "dvb-usb-lme2510c-s0194.fw"
76+
#define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw"
77+
#define LME2510_LG "dvb-usb-lme2510-lg.fw"
78+
#define LME2510_S0194 "dvb-usb-lme2510-s0194.fw"
7979

8080
/* debug */
8181
static int dvb_usb_lme2510_debug;

include/linux/moduleparam.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
/* Generic info of form tag = "info" */
2828
#define MODULE_INFO(tag, info) \
29+
static_assert( \
30+
sizeof(info) - 1 == __builtin_strlen(info), \
31+
"MODULE_INFO(" #tag ", ...) contains embedded NUL byte"); \
2932
static const char __UNIQUE_ID(modinfo)[] \
3033
__used __section(".modinfo") __aligned(1) \
3134
= __MODULE_INFO_PREFIX __stringify(tag) "=" info

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ pub mod list;
112112
pub mod maple_tree;
113113
pub mod miscdevice;
114114
pub mod mm;
115+
pub mod module_param;
115116
#[cfg(CONFIG_NET)]
116117
pub mod net;
117118
pub mod num;

rust/kernel/module_param.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Support for module parameters.
4+
//!
5+
//! C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
6+
7+
use crate::prelude::*;
8+
use crate::str::BStr;
9+
use bindings;
10+
use kernel::sync::SetOnce;
11+
12+
/// Newtype to make `bindings::kernel_param` [`Sync`].
13+
#[repr(transparent)]
14+
#[doc(hidden)]
15+
pub struct KernelParam(bindings::kernel_param);
16+
17+
impl KernelParam {
18+
#[doc(hidden)]
19+
pub const fn new(val: bindings::kernel_param) -> Self {
20+
Self(val)
21+
}
22+
}
23+
24+
// SAFETY: C kernel handles serializing access to this type. We never access it
25+
// from Rust module.
26+
unsafe impl Sync for KernelParam {}
27+
28+
/// Types that can be used for module parameters.
29+
// NOTE: This trait is `Copy` because drop could produce unsoundness during teardown.
30+
pub trait ModuleParam: Sized + Copy {
31+
/// Parse a parameter argument into the parameter value.
32+
fn try_from_param_arg(arg: &BStr) -> Result<Self>;
33+
}
34+
35+
/// Set the module parameter from a string.
36+
///
37+
/// Used to set the parameter value at kernel initialization, when loading
38+
/// the module or when set through `sysfs`.
39+
///
40+
/// See `struct kernel_param_ops.set`.
41+
///
42+
/// # Safety
43+
///
44+
/// - If `val` is non-null then it must point to a valid null-terminated string that must be valid
45+
/// for reads for the duration of the call.
46+
/// - `param` must be a pointer to a `bindings::kernel_param` initialized by the rust module macro.
47+
/// The pointee must be valid for reads for the duration of the call.
48+
///
49+
/// # Note
50+
///
51+
/// - The safety requirements are satisfied by C API contract when this function is invoked by the
52+
/// module subsystem C code.
53+
/// - Currently, we only support read-only parameters that are not readable from `sysfs`. Thus, this
54+
/// function is only called at kernel initialization time, or at module load time, and we have
55+
/// exclusive access to the parameter for the duration of the function.
56+
///
57+
/// [`module!`]: macros::module
58+
unsafe extern "C" fn set_param<T>(val: *const c_char, param: *const bindings::kernel_param) -> c_int
59+
where
60+
T: ModuleParam,
61+
{
62+
// NOTE: If we start supporting arguments without values, val _is_ allowed
63+
// to be null here.
64+
if val.is_null() {
65+
// TODO: Use pr_warn_once available.
66+
crate::pr_warn!("Null pointer passed to `module_param::set_param`");
67+
return EINVAL.to_errno();
68+
}
69+
70+
// SAFETY: By function safety requirement, val is non-null, null-terminated
71+
// and valid for reads for the duration of this function.
72+
let arg = unsafe { CStr::from_char_ptr(val) };
73+
let arg: &BStr = arg.as_ref();
74+
75+
crate::error::from_result(|| {
76+
let new_value = T::try_from_param_arg(arg)?;
77+
78+
// SAFETY: By function safety requirements, this access is safe.
79+
let container = unsafe { &*((*param).__bindgen_anon_1.arg.cast::<SetOnce<T>>()) };
80+
81+
container
82+
.populate(new_value)
83+
.then_some(0)
84+
.ok_or(kernel::error::code::EEXIST)
85+
})
86+
}
87+
88+
macro_rules! impl_int_module_param {
89+
($ty:ident) => {
90+
impl ModuleParam for $ty {
91+
fn try_from_param_arg(arg: &BStr) -> Result<Self> {
92+
<$ty as crate::str::parse_int::ParseInt>::from_str(arg)
93+
}
94+
}
95+
};
96+
}
97+
98+
impl_int_module_param!(i8);
99+
impl_int_module_param!(u8);
100+
impl_int_module_param!(i16);
101+
impl_int_module_param!(u16);
102+
impl_int_module_param!(i32);
103+
impl_int_module_param!(u32);
104+
impl_int_module_param!(i64);
105+
impl_int_module_param!(u64);
106+
impl_int_module_param!(isize);
107+
impl_int_module_param!(usize);
108+
109+
/// A wrapper for kernel parameters.
110+
///
111+
/// This type is instantiated by the [`module!`] macro when module parameters are
112+
/// defined. You should never need to instantiate this type directly.
113+
///
114+
/// Note: This type is `pub` because it is used by module crates to access
115+
/// parameter values.
116+
pub struct ModuleParamAccess<T> {
117+
value: SetOnce<T>,
118+
default: T,
119+
}
120+
121+
// SAFETY: We only create shared references to the contents of this container,
122+
// so if `T` is `Sync`, so is `ModuleParamAccess`.
123+
unsafe impl<T: Sync> Sync for ModuleParamAccess<T> {}
124+
125+
impl<T> ModuleParamAccess<T> {
126+
#[doc(hidden)]
127+
pub const fn new(default: T) -> Self {
128+
Self {
129+
value: SetOnce::new(),
130+
default,
131+
}
132+
}
133+
134+
/// Get a shared reference to the parameter value.
135+
// Note: When sysfs access to parameters are enabled, we have to pass in a
136+
// held lock guard here.
137+
pub fn value(&self) -> &T {
138+
self.value.as_ref().unwrap_or(&self.default)
139+
}
140+
141+
/// Get a mutable pointer to `self`.
142+
///
143+
/// NOTE: In most cases it is not safe deref the returned pointer.
144+
pub const fn as_void_ptr(&self) -> *mut c_void {
145+
core::ptr::from_ref(self).cast_mut().cast()
146+
}
147+
}
148+
149+
#[doc(hidden)]
150+
/// Generate a static [`kernel_param_ops`](srctree/include/linux/moduleparam.h) struct.
151+
///
152+
/// # Examples
153+
///
154+
/// ```ignore
155+
/// make_param_ops!(
156+
/// /// Documentation for new param ops.
157+
/// PARAM_OPS_MYTYPE, // Name for the static.
158+
/// MyType // A type which implements [`ModuleParam`].
159+
/// );
160+
/// ```
161+
macro_rules! make_param_ops {
162+
($ops:ident, $ty:ty) => {
163+
#[doc(hidden)]
164+
pub static $ops: $crate::bindings::kernel_param_ops = $crate::bindings::kernel_param_ops {
165+
flags: 0,
166+
set: Some(set_param::<$ty>),
167+
get: None,
168+
free: None,
169+
};
170+
};
171+
}
172+
173+
make_param_ops!(PARAM_OPS_I8, i8);
174+
make_param_ops!(PARAM_OPS_U8, u8);
175+
make_param_ops!(PARAM_OPS_I16, i16);
176+
make_param_ops!(PARAM_OPS_U16, u16);
177+
make_param_ops!(PARAM_OPS_I32, i32);
178+
make_param_ops!(PARAM_OPS_U32, u32);
179+
make_param_ops!(PARAM_OPS_I64, i64);
180+
make_param_ops!(PARAM_OPS_U64, u64);
181+
make_param_ops!(PARAM_OPS_ISIZE, isize);
182+
make_param_ops!(PARAM_OPS_USIZE, usize);

rust/kernel/str.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use core::{
1515

1616
pub use crate::prelude::CStr;
1717

18+
pub mod parse_int;
19+
1820
/// Byte string without UTF-8 validity guarantee.
1921
#[repr(transparent)]
2022
pub struct BStr([u8]);

0 commit comments

Comments
 (0)