* Re: [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Sami Tolvanen @ 2026-05-19 21:23 UTC (permalink / raw)
To: Andrii Kuchmenko
Cc: linux-modules, chleroy, mcgrof, dmitry.torokhov, linux-kernel,
stable
In-Reply-To: <20260518143233.16091-1-capyenglishlite@gmail.com>
Hi Andrii,
On Mon, May 18, 2026 at 05:32:33PM +0300, Andrii Kuchmenko wrote:
> module_extend_max_pages() calls kvrealloc() internally and returns
> -ENOMEM on allocation failure. The return value is never checked.
We should definitely fix this, but I'm not sure the rest of the
commit message is entirely accurate.
> The decompression loop then continues calling module_get_next_page(),
> which writes struct page pointers into info->pages[]. When used_pages
> reaches the stale max_pages value (not updated due to the failed
> extend), a subsequent write to info->pages[used_pages++] goes out of
> bounds into adjacent heap memory.
>
> Adjacent slab objects in the same kmalloc cache (pipe_buffer,
> seq_operations, cred) can be corrupted, potentially leading to local
> privilege escalation on kernels without SLAB_VIRTUAL mitigation.
Looking at the code:
- struct load_info info is zero-initialized in init_module_from_file().
- If module_extend_max_pages() fails, info->pages remains NULL and
info->max_pages and info->used_pages both remain 0.
- module_get_next_page() sees info->max_pages == info->used_pages
immediately and calls module_extend_max_pages(info, 0).
- kvrealloc() is called with a size of 0 and it returns ZERO_SIZE_PTR.
- Because ZERO_SIZE_PTR != NULL, module_extend_max_pages() sets
info->pages to ZERO_SIZE_PTR and returns 0.
- module_get_next_page() writes to info->pages[info->used_pages++],
and the write to ZERO_SIZE_PTR results in an immediate oops.
This isn't great, but I do not see a potential for an out-of-bounds
write or slab corruption in this specific case. What am I missing?
Sami
^ permalink raw reply
* Re: [PATCH v5 00/14] module: Introduce hash-based integrity checking
From: Thomas Weißschuh @ 2026-05-19 18:19 UTC (permalink / raw)
To: Sami Tolvanen
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Paul Moore, James Morris, Serge E. Hallyn,
Jonathan Corbet, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Naveen N Rao, Mimi Zohar, Roberto Sassu,
Dmitry Kasatkin, Eric Snowberg, Nicolas Schier, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Martin KaFai Lau, Song Liu, Yonghong Song,
Jiri Olsa, bpf, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Eric Biggers, Sebastian Andrzej Siewior, linux-kbuild,
linux-kernel, linux-arch, linux-modules, linux-security-module,
linux-doc, linuxppc-dev, linux-integrity, debian-kernel
In-Reply-To: <20260518215543.GA1878854@google.com>
Hi Sami,
On 2026-05-18 21:55:43+0000, Sami Tolvanen wrote:
> On Tue, May 05, 2026 at 11:05:04AM +0200, Thomas Weißschuh wrote:
> > The current signature-based module integrity checking has some drawbacks
> > in combination with reproducible builds. Either the module signing key
> > is generated at build time, which makes the build unreproducible, or a
> > static signing key is used, which precludes rebuilds by third parties
> > and makes the whole build and packaging process much more complicated.
> >
> > The goal is to reach bit-for-bit reproducibility. Excluding certain
> > parts of the build output from the reproducibility analysis would be
> > error-prone and force each downstream consumer to introduce new tooling.
> >
> > Introduce a new mechanism to ensure only well-known modules are loaded
> > by embedding a merkle tree root of all modules built as part of the full
> > kernel build into vmlinux.
>
> I noticed Sashiko had a few concerns about the build changes. Would you
> mind taking a look to see if they're valid?
>
> https://sashiko.dev/#/patchset/20260505-module-hashes-v5-0-e174a5a49fce%40weissschuh.net
I definitively have these on my list. Unfortunately I am busy with
something else right now. But this series and the Sashiko comments
are next.
Thomas
^ permalink raw reply
* Re: [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Christophe Leroy (CS GROUP) @ 2026-05-19 14:56 UTC (permalink / raw)
To: Andrii Kuchmenko, linux-modules
Cc: mcgrof, dmitry.torokhov, linux-kernel, stable
In-Reply-To: <be6734b9-112e-4e71-9013-1c6dc5f750da@kernel.org>
Looks like something went wrong with that reponse, so let's try again:
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Le 18/05/2026 à 18:21, Christophe Leroy (CS GROUP) a écrit :
>
>
> Le 18/05/2026 à 16:32, Andrii Kuchmenko a écrit :
>> [Vous ne recevez pas souvent de courriers de
>> capyenglishlite@gmail.com. Découvrez pourquoi ceci est important à
>> https://aka.ms/LearnAboutSenderIdentification ]
>>
>> module_extend_max_pages() calls kvrealloc() internally and returns
>> -ENOMEM on allocation failure. The return value is never checked.
>> The decompression loop then continues calling module_get_next_page(),
>> which writes struct page pointers into info->pages[]. When used_pages
>> reaches the stale max_pages value (not updated due to the failed
>> extend), a subsequent write to info->pages[used_pages++] goes out of
>> bounds into adjacent heap memory.
>>
>> Adjacent slab objects in the same kmalloc cache (pipe_buffer,
>> seq_operations, cred) can be corrupted, potentially leading to local
>> privilege escalation on kernels without SLAB_VIRTUAL mitigation.
>>
>> The call order in finit_module() is:
>>
>> module_decompress() <- vulnerable, runs FIRST
>> load_module()
>> module_sig_check() <- signature check, runs SECOND
>>
>> Decompression happens before signature verification. A crafted
>> compressed module submitted via finit_module(MODULE_INIT_COMPRESSED_FILE)
>> reaches this code path before any signature gate is applied. On kernels
>> with module.sig_enforce=0 (default without SecureBoot) or with
>> unprivileged user namespaces (Ubuntu, Debian default), this is
>> reachable without CAP_SYS_MODULE.
>>
>> Confirmed present in mainline (tested on v6.14-rc3).
>>
>> Fix: add the missing error check after module_extend_max_pages() and
>> return immediately on failure. This matches the pattern used by every
>> other kvrealloc() caller in the module loading path.
>>
>> Fixes: 169a58ad824d ("module: add in-kernel support for decompressing")
>> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>> Cc: Luis Chamberlain <mcgrof@kernel.org>
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Andrii Kuchmenko <capyenglishlite@gmail.com>
>> ---
>> Changes in v2:
>> - Remove unnecessary initialization of 'error' to 0 (Christophe Leroy)
>> - Remove unrelated blank line after if (error) return error
>> (Christophe Leroy)
>>
>> kernel/module/decompress.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c
>> --- a/kernel/module/decompress.c
>> +++ b/kernel/module/decompress.c
>> @@ -XXX,9 +XXX,12 @@ int module_decompress(struct load_info *info,
>> const void *buf, size_t size)
>> {
>> unsigned int n_pages;
>> int error;
>> ssize_t data_size;
>>
>> n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2;
>> error = module_extend_max_pages(info, n_pages);
>> + if (error)
>> + return error;
>> data_size = MODULE_DECOMPRESS_FN(info, buf, size);
>> if (data_size < 0) {
>> error = data_size;
>> --
>> 2.39.0
>
>
^ permalink raw reply
* Re: [PATCH 3/8] rust: drm: add `ThisModule` associated type to `Driver` trait
From: Gary Guo @ 2026-05-19 11:58 UTC (permalink / raw)
To: Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu
In-Reply-To: <20260519-fix-fops-owner-v1-3-2ded9830da14@linux.dev>
On Tue May 19, 2026 at 7:26 AM BST, Alvin Sun wrote:
> Add a `ThisModule` associated type bound by `ModuleMetadata` to the
> `drm::Driver` trait, allowing DRM drivers to expose their module
> pointer for use in file operations.
FWIW, I was considering adding this automatically to the `#[vtable]` macro
(associated types/consts won't have any costs if they're unused anyway).
But requiring an explicit specification isn't too bad either.
Best,
Gary
>
> Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
> ---
> rust/kernel/drm/driver.rs | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
> index 5233bdebc9fcd..c798961650c1a 100644
> --- a/rust/kernel/drm/driver.rs
> +++ b/rust/kernel/drm/driver.rs
> @@ -115,6 +115,9 @@ pub trait Driver {
>
> /// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
> const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
> +
> + /// The module implementing this driver.
> + type ThisModule: crate::ModuleMetadata;
> }
>
> /// The registration type of a `drm::Device`.
^ permalink raw reply
* Re: [PATCH 1/8] rust: module: add `MODULE_PTR` const to `ModuleMetadata` trait
From: Gary Guo @ 2026-05-19 11:57 UTC (permalink / raw)
To: Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu
In-Reply-To: <20260519-fix-fops-owner-v1-1-2ded9830da14@linux.dev>
On Tue May 19, 2026 at 7:26 AM BST, Alvin Sun wrote:
> Add a `MODULE_PTR` const to the `ModuleMetadata` trait so that
> modules can provide a constant pointer to their `struct module`
> usable in const contexts such as static file_operations.
Please design a consistent API surface that integrates with the `THIS_MODULE`
that we have today, and avoid two ways of doing things.
Best,
Gary
>
> Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
> ---
> rust/kernel/lib.rs | 3 +++
> rust/macros/module.rs | 14 ++++++++++++++
> 2 files changed, 17 insertions(+)
>
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index b72b2fbe046d6..c7e809636e1a9 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -184,6 +184,9 @@ fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Erro
> pub trait ModuleMetadata {
> /// The name of the module as specified in the `module!` macro.
> const NAME: &'static crate::str::CStr;
> +
> + /// The pointer to the kernel `struct module` for this module.
> + const MODULE_PTR: *mut bindings::module;
> }
>
> /// Equivalent to `THIS_MODULE` in the C API.
> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
> index 06c18e2075083..7204fe604f24a 100644
> --- a/rust/macros/module.rs
> +++ b/rust/macros/module.rs
> @@ -519,6 +519,20 @@ pub(crate) fn module(info: ModuleInfo) -> Result<TokenStream> {
>
> impl ::kernel::ModuleMetadata for #type_ {
> const NAME: &'static ::kernel::str::CStr = #name_cstr;
> +
> + #[cfg(MODULE)]
> + const MODULE_PTR: *mut ::kernel::bindings::module = {
> + extern "C" {
> + static __this_module: ::kernel::types::Opaque<::kernel::bindings::module>;
> + }
> +
> + // SAFETY: `__this_module` is constructed by the kernel at load time
> + // and lives until the module is unloaded.
> + unsafe { __this_module.get() }
> + };
> +
> + #[cfg(not(MODULE))]
> + const MODULE_PTR: *mut ::kernel::bindings::module = ::core::ptr::null_mut();
> }
>
> // Double nested modules, since then nobody can access the public items inside.
^ permalink raw reply
* Re: [PATCH 2/8] rust: driver: make `DriverModule` struct pub(crate) in `module_driver!`
From: Gary Guo @ 2026-05-19 11:53 UTC (permalink / raw)
To: Alvin Sun, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu
In-Reply-To: <20260519-fix-fops-owner-v1-2-2ded9830da14@linux.dev>
On Tue May 19, 2026 at 7:26 AM BST, Alvin Sun wrote:
> Expose the generated `DriverModule` struct as `pub(crate)` so that
> driver implementations can reference it via `super::DriverModule`
> for the `ThisModule` associated type.
Why is this needed? Child modules can see items super modules.
Best,
Gary
>
> Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
> ---
> rust/kernel/driver.rs | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
> index 36de8098754d0..9c7c69c4d2af0 100644
> --- a/rust/kernel/driver.rs
> +++ b/rust/kernel/driver.rs
> @@ -253,7 +253,7 @@ macro_rules! module_driver {
> type Ops<$gen_type> = $driver_ops;
>
> #[$crate::prelude::pin_data]
> - struct DriverModule {
> + pub(crate) struct DriverModule {
> #[pin]
> _driver: $crate::driver::Registration<Ops<$type>>,
> }
^ permalink raw reply
* [PATCH 8/8] samples: rust: rust_misc_device: implement `ThisModule` for `RustMiscDevice`
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Set `ThisModule = RustMiscDeviceModule` to provide the correct module
pointer for file operations ownership.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
samples/rust/rust_misc_device.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index 41e26c825060b..a4b012a35b5ec 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -176,6 +176,7 @@ struct RustMiscDevice {
#[vtable]
impl MiscDevice for RustMiscDevice {
type Ptr = Pin<KBox<Self>>;
+ type ThisModule = RustMiscDeviceModule;
fn open(_file: &File, misc: &MiscDeviceRegistration<Self>) -> Result<Pin<KBox<Self>>> {
let dev = ARef::from(misc.device());
--
2.43.0
^ permalink raw reply related
* [PATCH 7/8] rust: miscdevice: add `ThisModule` associated type to `MiscDevice` trait
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Add a `ThisModule` associated type bound by `ModuleMetadata` to the
`MiscDevice` trait, and use it to set the miscdevice fops owner field
instead of defaulting to null.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/miscdevice.rs | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 05a6b6b9770f2..007caaae62697 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -38,6 +38,7 @@
ForeignOwnable,
Opaque, //
},
+ ModuleMetadata, //
};
use core::{
marker::PhantomData,
@@ -137,6 +138,9 @@ pub trait MiscDevice: Sized {
/// What kind of pointer should `Self` be wrapped in.
type Ptr: ForeignOwnable + Send + Sync;
+ /// The module implementing this driver.
+ type ThisModule: ModuleMetadata;
+
/// Called when the misc device is opened.
///
/// The returned pointer will be stored as the private data for the file.
@@ -441,6 +445,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
} else {
None
},
+ owner: <T::ThisModule as ModuleMetadata>::MODULE_PTR,
..pin_init::zeroed()
};
--
2.43.0
^ permalink raw reply related
* [PATCH 6/8] rust: drm: set fops.owner from driver module pointer
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Change `create_fops()` to accept an owner module pointer instead of
hardcoding `null_mut()`, ensuring the kernel correctly tracks the
module owning the DRM device's file operations.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/device.rs | 3 ++-
rust/kernel/drm/gem/mod.rs | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index 403fc35353c74..97bee53823346 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -111,7 +111,8 @@ impl<T: drm::Driver> Device<T> {
fops: &Self::GEM_FOPS,
};
- const GEM_FOPS: bindings::file_operations = drm::gem::create_fops();
+ const GEM_FOPS: bindings::file_operations =
+ drm::gem::create_fops(<T::ThisModule as crate::ModuleMetadata>::MODULE_PTR);
/// Create a new `drm::Device` for a `drm::Driver`.
pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> {
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index 01b5bd47a3332..9a203efc59116 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -357,10 +357,10 @@ impl<T: DriverObject> AllocImpl for Object<T> {
};
}
-pub(super) const fn create_fops() -> bindings::file_operations {
+pub(super) const fn create_fops(owner: *mut bindings::module) -> bindings::file_operations {
let mut fops: bindings::file_operations = pin_init::zeroed();
- fops.owner = core::ptr::null_mut();
+ fops.owner = owner;
fops.open = Some(bindings::drm_open);
fops.release = Some(bindings::drm_release);
fops.unlocked_ioctl = Some(bindings::drm_ioctl);
--
2.43.0
^ permalink raw reply related
* [PATCH 5/8] gpu: tyr: implement `ThisModule`
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Set `ThisModule = super::DriverModule` to provide the correct module
pointer for file operations ownership.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/tyr/driver.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 279710b36a104..9eb4561ab831d 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -176,6 +176,7 @@ impl drm::Driver for TyrDrmDriver {
type Data = TyrDrmDeviceData;
type File = TyrDrmFileData;
type Object = drm::gem::Object<TyrObject>;
+ type ThisModule = super::DriverModule;
const INFO: drm::DriverInfo = INFO;
--
2.43.0
^ permalink raw reply related
* [PATCH 4/8] gpu: nova: implement `ThisModule`
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Set `ThisModule = super::DriverModule` to provide the correct module
pointer for file operations ownership.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
drivers/gpu/drm/nova/driver.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs
index b1af0a099551d..6353c19d319c6 100644
--- a/drivers/gpu/drm/nova/driver.rs
+++ b/drivers/gpu/drm/nova/driver.rs
@@ -68,6 +68,7 @@ impl drm::Driver for NovaDriver {
type Data = NovaData;
type File = File;
type Object = gem::Object<NovaObject>;
+ type ThisModule = super::DriverModule;
const INFO: drm::DriverInfo = INFO;
--
2.43.0
^ permalink raw reply related
* [PATCH 1/8] rust: module: add `MODULE_PTR` const to `ModuleMetadata` trait
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Add a `MODULE_PTR` const to the `ModuleMetadata` trait so that
modules can provide a constant pointer to their `struct module`
usable in const contexts such as static file_operations.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/lib.rs | 3 +++
rust/macros/module.rs | 14 ++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index b72b2fbe046d6..c7e809636e1a9 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -184,6 +184,9 @@ fn init(module: &'static ThisModule) -> impl pin_init::PinInit<Self, error::Erro
pub trait ModuleMetadata {
/// The name of the module as specified in the `module!` macro.
const NAME: &'static crate::str::CStr;
+
+ /// The pointer to the kernel `struct module` for this module.
+ const MODULE_PTR: *mut bindings::module;
}
/// Equivalent to `THIS_MODULE` in the C API.
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 06c18e2075083..7204fe604f24a 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -519,6 +519,20 @@ pub(crate) fn module(info: ModuleInfo) -> Result<TokenStream> {
impl ::kernel::ModuleMetadata for #type_ {
const NAME: &'static ::kernel::str::CStr = #name_cstr;
+
+ #[cfg(MODULE)]
+ const MODULE_PTR: *mut ::kernel::bindings::module = {
+ extern "C" {
+ static __this_module: ::kernel::types::Opaque<::kernel::bindings::module>;
+ }
+
+ // SAFETY: `__this_module` is constructed by the kernel at load time
+ // and lives until the module is unloaded.
+ unsafe { __this_module.get() }
+ };
+
+ #[cfg(not(MODULE))]
+ const MODULE_PTR: *mut ::kernel::bindings::module = ::core::ptr::null_mut();
}
// Double nested modules, since then nobody can access the public items inside.
--
2.43.0
^ permalink raw reply related
* [PATCH 0/8] Fix missing fops.owner in Rust DRM/misc abstractions
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
During tyr debugfs development, a kernel NULL pointer dereference was
encountered after `rmmod tyr` while gnome-shell still held /dev/card1 open:
```
[158827.868132] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[158827.868918] Mem abort info:
[158827.869177] ESR = 0x0000000086000004
[158827.869519] EC = 0x21: IABT (current EL), IL = 32 bits
[158827.870000] SET = 0, FnV = 0
[158827.870281] EA = 0, S1PTW = 0
[158827.870571] FSC = 0x04: level 0 translation fault
[158827.871043] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000108dec000
[158827.871623] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000
[158827.872242] Internal error: Oops: 0000000086000004 [#1] SMP
[158827.872246] Modules linked in: tyr sunrpc snd_soc_simple_card rk805_pwrkey snd_soc_simple_card_utils rtw88_8822bu display_connector rtw88_usb rtw88_8822b snd_soc_rockchip_i2s_tdm snd_soc_hdmi_codec
rtw88_core]
[158827.872337] CPU: 4 UID: 1000 PID: 11276 Comm: gnome-s:disk$0 Tainted: G N 7.1.0-rc1+ #331 PREEMPT
[158827.880534] Tainted: [N]=TEST
[158827.880535] Hardware name: FriendlyElec NanoPi R6C/NanoPi R6C, BIOS v1.1 04/09/2025
[158827.880538] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[158827.880542] pc : 0x0
[158827.880547] lr : _RNvNtCs257m05FHVbX_3tyr2vm8pt_unmap+0x8c/0x12c [tyr]
[158827.880578] sp : ffff800083c236b0
[158827.880579] x29: ffff800083c236d0 x28: ffff00013f8a0000 x27: 0000000000000000
[158827.880585] x26: 000000000000007c x25: ffff000108e6ed80 x24: 0000000000401000
[158827.880590] x23: 0000000000000000 x22: 0000000040000000 x21: 0000000000001000
[158827.880595] x20: ffff00010f778138 x19: 0000000000400000 x18: 00000000ffffffff
[158827.880600] x17: 000000040044ffff x16: 045000f2b5503510 x15: 0720072007200720
[158827.880606] x14: 0720072007200720 x13: 0000000000401000 x12: 0000000000400000
[158827.880611] x11: ffff800083c239d0 x10: ffff000141e4fd88 x9 : 0000000000000000
[158827.880615] x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000400000
[158827.880620] x5 : ffff00013f8a0000 x4 : 0000000000000000 x3 : 0000000000000001
[158827.880625] x2 : 0000000000001000 x1 : 0000000000400000 x0 : ffff00010f778138
[158827.880630] Call trace:
[158827.880632] 0x0 (P)
[158827.880635] _RNvXs6_NtCs257m05FHVbX_3tyr2vmNtB5_9GpuVmDataNtNtNtCsgmSOfgXi5CZ_6kernel3drm5gpuvm11DriverGpuVm13sm_step_unmap+0x3c/0x120 [tyr]
[158827.891166] _RNvMs4_NtNtNtCsgmSOfgXi5CZ_6kernel3drm5gpuvm6sm_opsINtB7_5GpuVmNtNtCs257m05FHVbX_3tyr2vm9GpuVmDataE13sm_step_unmapB13_+0x18/0x34 [tyr]
[158827.891187] op_unmap_cb+0x78/0xb0
[158827.891196] __drm_gpuvm_sm_unmap+0x18c/0x1b4
[158827.891204] drm_gpuvm_sm_unmap+0x38/0x4c
[158827.891209] _RNvMs5_NtCs257m05FHVbX_3tyr2vmNtB5_2Vm7exec_op+0x1cc/0x254 [tyr]
[158827.894085] _RNvMs5_NtCs257m05FHVbX_3tyr2vmNtB5_2Vm11unmap_range+0x124/0x188 [tyr]
[158827.894105] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeNtNtCs257m05FHVbX_3tyr3gem8KernelBoEBK_+0x44/0xd8 [tyr]
[158827.894125] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeINtNtNtCsgmSOfgXi5CZ_6kernel5alloc4kvec3VecNtNtCs257m05FHVbX_3tyr2fw7SectionNtNtBL_9allocator7KmallocEEB1r_+0x3c/0x100 [tyr]
[158827.894147] _RINvNtCs5hGKnPbRUFW_4core3ptr13drop_in_placeINtNtNtCsgmSOfgXi5CZ_6kernel4sync3arc3ArcNtNtCs257m05FHVbX_3tyr2fw8FirmwareEEB1p_+0x94/0x190 [tyr]
[158827.894167] _RNvMs4_NtNtCsgmSOfgXi5CZ_6kernel3drm6deviceINtB5_6DeviceNtNtCs257m05FHVbX_3tyr6driver12TyrDrmDriverE7releaseBW_+0x30/0x98 [tyr]
[158827.899550] drm_dev_put.part.0+0x88/0xc0
[158827.899557] drm_minor_release+0x18/0x28
[158827.899562] drm_release+0x144/0x170
[158827.899567] __fput+0xe4/0x30c
[158827.899573] ____fput+0x14/0x20
[158827.899579] task_work_run+0x7c/0xe8
[158827.899586] do_exit+0x2a8/0xac4
[158827.899590] do_group_exit+0x34/0x90
[158827.899594] get_signal+0xaac/0xabc
[158827.899599] arch_do_signal_or_restart+0x90/0x3e8
[158827.899606] exit_to_user_mode_loop+0x140/0x1d0
[158827.899613] el0_svc+0x2f4/0x2f8
[158827.899620] el0t_64_sync_handler+0xa0/0xe4
[158827.899627] el0t_64_sync+0x198/0x19c
[158827.899632] ---[ end trace 0000000000000000 ]---
```
The root cause: fops.owner was NULL in Rust DRM drivers, so the kernel never
blocked module unloading while file descriptors were open. This leads to
use-after-free when drm_release (or other fops) is called on freed module code.
The series adds MODULE_PTR to ModuleMetadata, threads ThisModule through the
DRM Driver trait into create_fops(), and applies the same fix to miscdevice.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
Alvin Sun (8):
rust: module: add `MODULE_PTR` const to `ModuleMetadata` trait
rust: driver: make `DriverModule` struct pub(crate) in `module_driver!`
rust: drm: add `ThisModule` associated type to `Driver` trait
gpu: nova: implement `ThisModule`
gpu: tyr: implement `ThisModule`
rust: drm: set fops.owner from driver module pointer
rust: miscdevice: add `ThisModule` associated type to `MiscDevice` trait
samples: rust: rust_misc_device: implement `ThisModule` for `RustMiscDevice`
drivers/gpu/drm/nova/driver.rs | 1 +
drivers/gpu/drm/tyr/driver.rs | 1 +
rust/kernel/driver.rs | 2 +-
rust/kernel/drm/device.rs | 3 ++-
rust/kernel/drm/driver.rs | 3 +++
rust/kernel/drm/gem/mod.rs | 4 ++--
rust/kernel/lib.rs | 3 +++
rust/kernel/miscdevice.rs | 5 +++++
rust/macros/module.rs | 14 ++++++++++++++
samples/rust/rust_misc_device.rs | 1 +
10 files changed, 33 insertions(+), 4 deletions(-)
---
base-commit: aa61612ab641d7d62b0b6889f2c7c9251489f6e3
change-id: 20260519-fix-fops-owner-e3a77bb27c6c
prerequisite-change-id: 20260519-miscdev-use-format-9ab7e83b1c11:v1
prerequisite-patch-id: 405b334ff0d48ad350014f05a2321bdbaa025400
prerequisite-patch-id: 604b631c81d5423f4ebb2e12ba2d22e9ce371bfc
Best regards,
--
Alvin Sun <alvin.sun@linux.dev>
^ permalink raw reply
* [PATCH 3/8] rust: drm: add `ThisModule` associated type to `Driver` trait
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Add a `ThisModule` associated type bound by `ModuleMetadata` to the
`drm::Driver` trait, allowing DRM drivers to expose their module
pointer for use in file operations.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/drm/driver.rs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
index 5233bdebc9fcd..c798961650c1a 100644
--- a/rust/kernel/drm/driver.rs
+++ b/rust/kernel/drm/driver.rs
@@ -115,6 +115,9 @@ pub trait Driver {
/// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
+
+ /// The module implementing this driver.
+ type ThisModule: crate::ModuleMetadata;
}
/// The registration type of a `drm::Device`.
--
2.43.0
^ permalink raw reply related
* [PATCH 2/8] rust: driver: make `DriverModule` struct pub(crate) in `module_driver!`
From: Alvin Sun @ 2026-05-19 6:26 UTC (permalink / raw)
To: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Sami Tolvanen, Aaron Tomlin, Greg Kroah-Hartman,
Rafael J. Wysocki, David Airlie, Simona Vetter, Daniel Almeida,
Arnd Bergmann
Cc: rust-for-linux, linux-kernel, linux-modules, driver-core,
dri-devel, nova-gpu, Alvin Sun
In-Reply-To: <20260519-fix-fops-owner-v1-0-2ded9830da14@linux.dev>
Expose the generated `DriverModule` struct as `pub(crate)` so that
driver implementations can reference it via `super::DriverModule`
for the `ThisModule` associated type.
Signed-off-by: Alvin Sun <alvin.sun@linux.dev>
---
rust/kernel/driver.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
index 36de8098754d0..9c7c69c4d2af0 100644
--- a/rust/kernel/driver.rs
+++ b/rust/kernel/driver.rs
@@ -253,7 +253,7 @@ macro_rules! module_driver {
type Ops<$gen_type> = $driver_ops;
#[$crate::prelude::pin_data]
- struct DriverModule {
+ pub(crate) struct DriverModule {
#[pin]
_driver: $crate::driver::Registration<Ops<$type>>,
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v5 00/14] module: Introduce hash-based integrity checking
From: Sami Tolvanen @ 2026-05-18 21:55 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Nathan Chancellor,
Nicolas Schier, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Paul Moore, James Morris, Serge E. Hallyn,
Jonathan Corbet, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Naveen N Rao, Mimi Zohar, Roberto Sassu,
Dmitry Kasatkin, Eric Snowberg, Nicolas Schier, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Martin KaFai Lau, Song Liu, Yonghong Song,
Jiri Olsa, bpf, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Eric Biggers, Sebastian Andrzej Siewior, linux-kbuild,
linux-kernel, linux-arch, linux-modules, linux-security-module,
linux-doc, linuxppc-dev, linux-integrity, debian-kernel
In-Reply-To: <20260505-module-hashes-v5-0-e174a5a49fce@weissschuh.net>
Hi Thomas,
On Tue, May 05, 2026 at 11:05:04AM +0200, Thomas Weißschuh wrote:
> The current signature-based module integrity checking has some drawbacks
> in combination with reproducible builds. Either the module signing key
> is generated at build time, which makes the build unreproducible, or a
> static signing key is used, which precludes rebuilds by third parties
> and makes the whole build and packaging process much more complicated.
>
> The goal is to reach bit-for-bit reproducibility. Excluding certain
> parts of the build output from the reproducibility analysis would be
> error-prone and force each downstream consumer to introduce new tooling.
>
> Introduce a new mechanism to ensure only well-known modules are loaded
> by embedding a merkle tree root of all modules built as part of the full
> kernel build into vmlinux.
I noticed Sashiko had a few concerns about the build changes. Would you
mind taking a look to see if they're valid?
https://sashiko.dev/#/patchset/20260505-module-hashes-v5-0-e174a5a49fce%40weissschuh.net
Sami
^ permalink raw reply
* Re: [PATCH] rust: module_param: use `pr_warn_once!` for null pointer warning
From: Sami Tolvanen @ 2026-05-18 21:47 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Andreas Hindborg, Luis Chamberlain, Petr Pavlu, Daniel Gomez,
Aaron Tomlin, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
Danilo Krummrich, linux-modules, linux-kernel, rust-for-linux
In-Reply-To: <CANiq72kgM+ugZsRda=xfd=So1UteKVh=tSBxZAq5ETwk2zUOwA@mail.gmail.com>
Hi Miguel,
On Mon, May 18, 2026 at 10:43 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Mon, Apr 27, 2026 at 10:13 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >
> > Replace `pr_warn!` and the accompanying TODO with `pr_warn_once!`, now that
> > the macro is available.
> >
> > Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>
> This seems to be:
>
> https://lore.kernel.org/rust-for-linux/20260226120848.82891-3-adarshdas950@gmail.com/
>
> Another one was also sent a few moments ago:
>
> https://lore.kernel.org/rust-for-linux/20260518134107.4114-1-cppcoffee@gmail.com/
>
> Is modules going to pick the original one? Otherwise, I am happy to do so.
Yes, this is on my list for v7.2.
Sami
^ permalink raw reply
* Re: [PATCH] rust: module_param: use `pr_warn_once!` for null pointer warning
From: Miguel Ojeda @ 2026-05-18 17:43 UTC (permalink / raw)
To: Andreas Hindborg
Cc: Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Miguel Ojeda, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
Danilo Krummrich, linux-modules, linux-kernel, rust-for-linux
In-Reply-To: <20260427-params-pr-once-v1-1-3a8c64704cc4@kernel.org>
On Mon, Apr 27, 2026 at 10:13 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> Replace `pr_warn!` and the accompanying TODO with `pr_warn_once!`, now that
> the macro is available.
>
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
This seems to be:
https://lore.kernel.org/rust-for-linux/20260226120848.82891-3-adarshdas950@gmail.com/
Another one was also sent a few moments ago:
https://lore.kernel.org/rust-for-linux/20260518134107.4114-1-cppcoffee@gmail.com/
Is modules going to pick the original one? Otherwise, I am happy to do so.
I guess we can assume the reviews here to apply there.
Thanks!
Cheers,
Miguel
^ permalink raw reply
* Re: [PATCH] rust: kernel: module_param: replace pr_warn with pr_warn_once
From: Miguel Ojeda @ 2026-05-18 17:37 UTC (permalink / raw)
To: Xiaobo Liu, Adarsh Das, Andreas Hindborg
Cc: rust-for-linux, linux-modules, linux-kernel, mcgrof, petr.pavlu,
da.gomez, samitolvanen, atomlin, ojeda, boqun, gary, bjorn3_gh,
lossin, aliceryhl, tmgross, dakr
In-Reply-To: <20260518134107.4114-1-cppcoffee@gmail.com>
On Mon, May 18, 2026 at 3:41 PM Xiaobo Liu <cppcoffee@gmail.com> wrote:
>
> Replace pr_warn!() with pr_warn_once!() in module_param::set_param() to
> avoid flooding the kernel log when a null pointer is repeatedly passed.
>
> The original code had a TODO comment noting that pr_warn_once should be
> used once available. Since pr_warn_once!() is now available, switch to it
> and update the comment accordingly.
>
> Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
Isn't this
https://lore.kernel.org/rust-for-linux/20260226120848.82891-3-adarshdas950@gmail.com/
and this:
https://lore.kernel.org/rust-for-linux/20260427-params-pr-once-v1-1-3a8c64704cc4@kernel.org/
? Cc'ing the authors of both. I will reply in the second one too.
(Also, your email seems to have been sent twice to the list)
In any case, Sashiko is correct, this "time-based comment" is not very useful:
> + // `pr_warn_once` is already available, use it.
Cheers,
Miguel
^ permalink raw reply
* Re: [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Christophe Leroy (CS GROUP) @ 2026-05-18 16:21 UTC (permalink / raw)
To: Andrii Kuchmenko, linux-modules
Cc: mcgrof, dmitry.torokhov, linux-kernel, stable
In-Reply-To: <20260518143233.16091-1-capyenglishlite@gmail.com>
Le 18/05/2026 à 16:32, Andrii Kuchmenko a écrit :
> [Vous ne recevez pas souvent de courriers de capyenglishlite@gmail.com. Découvrez pourquoi ceci est important à https://aka.ms/LearnAboutSenderIdentification ]
>
> module_extend_max_pages() calls kvrealloc() internally and returns
> -ENOMEM on allocation failure. The return value is never checked.
> The decompression loop then continues calling module_get_next_page(),
> which writes struct page pointers into info->pages[]. When used_pages
> reaches the stale max_pages value (not updated due to the failed
> extend), a subsequent write to info->pages[used_pages++] goes out of
> bounds into adjacent heap memory.
>
> Adjacent slab objects in the same kmalloc cache (pipe_buffer,
> seq_operations, cred) can be corrupted, potentially leading to local
> privilege escalation on kernels without SLAB_VIRTUAL mitigation.
>
> The call order in finit_module() is:
>
> module_decompress() <- vulnerable, runs FIRST
> load_module()
> module_sig_check() <- signature check, runs SECOND
>
> Decompression happens before signature verification. A crafted
> compressed module submitted via finit_module(MODULE_INIT_COMPRESSED_FILE)
> reaches this code path before any signature gate is applied. On kernels
> with module.sig_enforce=0 (default without SecureBoot) or with
> unprivileged user namespaces (Ubuntu, Debian default), this is
> reachable without CAP_SYS_MODULE.
>
> Confirmed present in mainline (tested on v6.14-rc3).
>
> Fix: add the missing error check after module_extend_max_pages() and
> return immediately on failure. This matches the pattern used by every
> other kvrealloc() caller in the module loading path.
>
> Fixes: 169a58ad824d ("module: add in-kernel support for decompressing")
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Luis Chamberlain <mcgrof@kernel.org>
> Cc: stable@vger.kernel.org
> Signed-off-by: Andrii Kuchmenko <capyenglishlite@gmail.com>
> ---
> Changes in v2:
> - Remove unnecessary initialization of 'error' to 0 (Christophe Leroy)
> - Remove unrelated blank line after if (error) return error (Christophe Leroy)
>
> kernel/module/decompress.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c
> --- a/kernel/module/decompress.c
> +++ b/kernel/module/decompress.c
> @@ -XXX,9 +XXX,12 @@ int module_decompress(struct load_info *info,
> const void *buf, size_t size)
> {
> unsigned int n_pages;
> int error;
> ssize_t data_size;
>
> n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2;
> error = module_extend_max_pages(info, n_pages);
> + if (error)
> + return error;
> data_size = MODULE_DECOMPRESS_FN(info, buf, size);
> if (data_size < 0) {
> error = data_size;
> --
> 2.39.0
^ permalink raw reply
* [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Andrii Kuchmenko @ 2026-05-18 14:32 UTC (permalink / raw)
To: linux-modules
Cc: chleroy, mcgrof, dmitry.torokhov, linux-kernel, stable,
Andrii Kuchmenko
module_extend_max_pages() calls kvrealloc() internally and returns
-ENOMEM on allocation failure. The return value is never checked.
The decompression loop then continues calling module_get_next_page(),
which writes struct page pointers into info->pages[]. When used_pages
reaches the stale max_pages value (not updated due to the failed
extend), a subsequent write to info->pages[used_pages++] goes out of
bounds into adjacent heap memory.
Adjacent slab objects in the same kmalloc cache (pipe_buffer,
seq_operations, cred) can be corrupted, potentially leading to local
privilege escalation on kernels without SLAB_VIRTUAL mitigation.
The call order in finit_module() is:
module_decompress() <- vulnerable, runs FIRST
load_module()
module_sig_check() <- signature check, runs SECOND
Decompression happens before signature verification. A crafted
compressed module submitted via finit_module(MODULE_INIT_COMPRESSED_FILE)
reaches this code path before any signature gate is applied. On kernels
with module.sig_enforce=0 (default without SecureBoot) or with
unprivileged user namespaces (Ubuntu, Debian default), this is
reachable without CAP_SYS_MODULE.
Confirmed present in mainline (tested on v6.14-rc3).
Fix: add the missing error check after module_extend_max_pages() and
return immediately on failure. This matches the pattern used by every
other kvrealloc() caller in the module loading path.
Fixes: 169a58ad824d ("module: add in-kernel support for decompressing")
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Andrii Kuchmenko <capyenglishlite@gmail.com>
---
Changes in v2:
- Remove unnecessary initialization of 'error' to 0 (Christophe Leroy)
- Remove unrelated blank line after if (error) return error (Christophe Leroy)
kernel/module/decompress.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c
--- a/kernel/module/decompress.c
+++ b/kernel/module/decompress.c
@@ -XXX,9 +XXX,12 @@ int module_decompress(struct load_info *info,
const void *buf, size_t size)
{
unsigned int n_pages;
int error;
ssize_t data_size;
n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2;
error = module_extend_max_pages(info, n_pages);
+ if (error)
+ return error;
data_size = MODULE_DECOMPRESS_FN(info, buf, size);
if (data_size < 0) {
error = data_size;
--
2.39.0
^ permalink raw reply
* [PATCH] rust: kernel: module_param: replace pr_warn with pr_warn_once
From: Xiaobo Liu @ 2026-05-18 13:41 UTC (permalink / raw)
To: rust-for-linux, linux-modules
Cc: linux-kernel, mcgrof, petr.pavlu, da.gomez, samitolvanen, atomlin,
ojeda, boqun, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, Xiaobo Liu
Replace pr_warn!() with pr_warn_once!() in module_param::set_param() to
avoid flooding the kernel log when a null pointer is repeatedly passed.
The original code had a TODO comment noting that pr_warn_once should be
used once available. Since pr_warn_once!() is now available, switch to it
and update the comment accordingly.
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
---
rust/kernel/module_param.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs
index 6a8a7a875..fedb709fa 100644
--- a/rust/kernel/module_param.rs
+++ b/rust/kernel/module_param.rs
@@ -62,8 +62,8 @@ pub trait ModuleParam: Sized + Copy {
// NOTE: If we start supporting arguments without values, val _is_ allowed
// to be null here.
if val.is_null() {
- // TODO: Use pr_warn_once available.
- crate::pr_warn!("Null pointer passed to `module_param::set_param`");
+ // `pr_warn_once` is already available, use it.
+ crate::pr_warn_once!("Null pointer passed to `module_param::set_param`");
return EINVAL.to_errno();
}
--
2.34.1
^ permalink raw reply related
* [PATCH] rust: kernel: module_param: replace pr_warn with pr_warn_once
From: Xiaobo Liu @ 2026-05-18 13:40 UTC (permalink / raw)
To: rust-for-linux, linux-modules
Cc: linux-kernel, mcgrof, petr.pavlu, da.gomez, samitolvanen, atomlin,
ojeda, boqun, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, Xiaobo Liu
Replace pr_warn!() with pr_warn_once!() in module_param::set_param() to
avoid flooding the kernel log when a null pointer is repeatedly passed.
The original code had a TODO comment noting that pr_warn_once should be
used once available. Since pr_warn_once!() is now available, switch to it
and update the comment accordingly.
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
---
rust/kernel/module_param.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs
index 6a8a7a875..fedb709fa 100644
--- a/rust/kernel/module_param.rs
+++ b/rust/kernel/module_param.rs
@@ -62,8 +62,8 @@ pub trait ModuleParam: Sized + Copy {
// NOTE: If we start supporting arguments without values, val _is_ allowed
// to be null here.
if val.is_null() {
- // TODO: Use pr_warn_once available.
- crate::pr_warn!("Null pointer passed to `module_param::set_param`");
+ // `pr_warn_once` is already available, use it.
+ crate::pr_warn_once!("Null pointer passed to `module_param::set_param`");
return EINVAL.to_errno();
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Greg KH @ 2026-05-18 12:57 UTC (permalink / raw)
To: Andrii Kuchmenko
Cc: linux-modules, chleroy, mcgrof, dmitry.torokhov, linux-kernel,
stable
In-Reply-To: <20260518121858.3071-1-capyenglishlite@gmail.com>
On Mon, May 18, 2026 at 03:18:58PM +0300, Andrii Kuchmenko wrote:
> module_extend_max_pages() calls kvrealloc() internally and returns
> -ENOMEM on allocation failure. The return value is never checked.
> The decompression loop then continues calling module_get_next_page(),
> which writes struct page pointers into info->pages[]. When used_pages
> reaches the stale max_pages value (not updated due to the failed
> extend), a subsequent write to info->pages[used_pages++] goes out of
> bounds into adjacent heap memory.
>
> Adjacent slab objects in the same kmalloc cache (pipe_buffer,
> seq_operations, cred) can be corrupted, potentially leading to local
> privilege escalation on kernels without SLAB_VIRTUAL mitigation.
>
> The call order in finit_module() is:
>
> module_decompress() <- vulnerable, runs FIRST
> load_module()
> module_sig_check() <- signature check, runs SECOND
>
> Decompression happens before signature verification. A crafted
> compressed module submitted via finit_module(MODULE_INIT_COMPRESSED_FILE)
> reaches this code path before any signature gate is applied. On kernels
> with module.sig_enforce=0 (default without SecureBoot) or with
> unprivileged user namespaces (Ubuntu, Debian default), this is
> reachable without CAP_SYS_MODULE.
>
> Confirmed present in mainline (tested on v6.14-rc3).
>
> Fix: add the missing error check after module_extend_max_pages() and
> return immediately on failure. This matches the pattern used by every
> other kvrealloc() caller in the module loading path.
>
> Fixes: 169a58ad824d ("module: add in-kernel support for decompressing")
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Luis Chamberlain <mcgrof@kernel.org>
> Cc: stable@vger.kernel.org
> Signed-off-by: Andrii Kuchmenko <capyenglishlite@gmail.com>
> ---
> kernel/module/decompress.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c
> --- a/kernel/module/decompress.c
> +++ b/kernel/module/decompress.c
> @@ -XXX,9 +XXX,12 @@ int module_decompress(struct load_info *info,
> const void *buf, size_t size)
> {
> unsigned int n_pages;
> int error;
> ssize_t data_size;
>
> n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2;
> error = module_extend_max_pages(info, n_pages);
> + if (error)
> + return error;
> data_size = MODULE_DECOMPRESS_FN(info, buf, size);
> if (data_size < 0) {
> error = data_size;
> --
> 2.39.0
>
Hi,
This is the friendly patch-bot of Greg Kroah-Hartman. You have sent him
a patch that has triggered this response. He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created. Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.
You are receiving this message because of the following common error(s)
as indicated below:
- This looks like a new version of a previously submitted patch, but you
did not list below the --- line any changes from the previous version.
Please read the section entitled "The canonical patch format" in the
kernel file, Documentation/process/submitting-patches.rst for what
needs to be done here to properly describe this.
If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.
thanks,
greg k-h's patch email bot
^ permalink raw reply
* [PATCH v2] module: decompress: check return value of module_extend_max_pages()
From: Andrii Kuchmenko @ 2026-05-18 12:18 UTC (permalink / raw)
To: linux-modules
Cc: chleroy, mcgrof, dmitry.torokhov, linux-kernel, stable,
Andrii Kuchmenko
module_extend_max_pages() calls kvrealloc() internally and returns
-ENOMEM on allocation failure. The return value is never checked.
The decompression loop then continues calling module_get_next_page(),
which writes struct page pointers into info->pages[]. When used_pages
reaches the stale max_pages value (not updated due to the failed
extend), a subsequent write to info->pages[used_pages++] goes out of
bounds into adjacent heap memory.
Adjacent slab objects in the same kmalloc cache (pipe_buffer,
seq_operations, cred) can be corrupted, potentially leading to local
privilege escalation on kernels without SLAB_VIRTUAL mitigation.
The call order in finit_module() is:
module_decompress() <- vulnerable, runs FIRST
load_module()
module_sig_check() <- signature check, runs SECOND
Decompression happens before signature verification. A crafted
compressed module submitted via finit_module(MODULE_INIT_COMPRESSED_FILE)
reaches this code path before any signature gate is applied. On kernels
with module.sig_enforce=0 (default without SecureBoot) or with
unprivileged user namespaces (Ubuntu, Debian default), this is
reachable without CAP_SYS_MODULE.
Confirmed present in mainline (tested on v6.14-rc3).
Fix: add the missing error check after module_extend_max_pages() and
return immediately on failure. This matches the pattern used by every
other kvrealloc() caller in the module loading path.
Fixes: 169a58ad824d ("module: add in-kernel support for decompressing")
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Andrii Kuchmenko <capyenglishlite@gmail.com>
---
kernel/module/decompress.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c
--- a/kernel/module/decompress.c
+++ b/kernel/module/decompress.c
@@ -XXX,9 +XXX,12 @@ int module_decompress(struct load_info *info,
const void *buf, size_t size)
{
unsigned int n_pages;
int error;
ssize_t data_size;
n_pages = DIV_ROUND_UP(size, PAGE_SIZE) * 2;
error = module_extend_max_pages(info, n_pages);
+ if (error)
+ return error;
data_size = MODULE_DECOMPRESS_FN(info, buf, size);
if (data_size < 0) {
error = data_size;
--
2.39.0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox