* [PATCH v2 1/2] firmware_loader: annotate doctests as `no_run`
@ 2024-07-08 20:07 Danilo Krummrich
2024-07-08 20:07 ` [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` Danilo Krummrich
0 siblings, 1 reply; 5+ messages in thread
From: Danilo Krummrich @ 2024-07-08 20:07 UTC (permalink / raw)
To: mcgrof, russ.weight, gregkh
Cc: chrisi.schrefl, linux-kernel, rust-for-linux, Danilo Krummrich
The doctests of `Firmware` are compile-time only tests, since they
require a proper `Device` and a valid path to a (firmware) blob in order
to do something sane on runtime - we can't satisfy both of those
requirements.
Hence, configure the example as `no_run`.
Unfortunately, the kernel's Rust build system can't consider the
`no_run` attribute yet. Hence, for the meantime, wrap the example code
into a new function and never actually call it.
Fixes: de6582833db0 ("rust: add firmware abstractions")
Signed-off-by: Danilo Krummrich <dakr@redhat.com>
---
v2: (no changes)
---
rust/kernel/firmware.rs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index 386c8fb44785..106a928a535e 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -26,14 +26,18 @@
///
/// # Examples
///
-/// ```
+/// ```no_run
/// # use kernel::{c_str, device::Device, firmware::Firmware};
///
+/// # fn no_run() -> Result<(), Error> {
/// # // SAFETY: *NOT* safe, just for the example to get an `ARef<Device>` instance
/// # let dev = unsafe { Device::from_raw(core::ptr::null_mut()) };
///
-/// let fw = Firmware::request(c_str!("path/to/firmware.bin"), &dev).unwrap();
+/// let fw = Firmware::request(c_str!("path/to/firmware.bin"), &dev)?;
/// let blob = fw.data();
+///
+/// # Ok(())
+/// # }
/// ```
pub struct Firmware(NonNull<bindings::firmware>);
base-commit: 997197b58bf6e22b8c6ef88a168d8292fa9acec9
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` 2024-07-08 20:07 [PATCH v2 1/2] firmware_loader: annotate doctests as `no_run` Danilo Krummrich @ 2024-07-08 20:07 ` Danilo Krummrich 2024-07-08 20:37 ` Luis Chamberlain 2024-07-08 22:16 ` Christian Schrefl 0 siblings, 2 replies; 5+ messages in thread From: Danilo Krummrich @ 2024-07-08 20:07 UTC (permalink / raw) To: mcgrof, russ.weight, gregkh Cc: chrisi.schrefl, linux-kernel, rust-for-linux, Danilo Krummrich, Gary Guo `request_internal` must be called with one of the following function pointers: request_firmware(), firmware_request_nowarn(), firmware_request_platform() or request_firmware_direct(). The previous `FwFunc` alias did not guarantee this, which is unsound. In order to fix this up, implement `FwFunc` as new type with a corresponding type invariant. Reported-by: Gary Guo <gary@garyguo.net> Closes: https://lore.kernel.org/lkml/20240620143611.7995e0bb@eugeo/ Signed-off-by: Danilo Krummrich <dakr@redhat.com> --- v2: - provide method for each wrapped `FwFunc` (Christian) --- rust/kernel/firmware.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 106a928a535e..2ba03af9f036 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -7,10 +7,23 @@ use crate::{bindings, device::Device, error::Error, error::Result, str::CStr}; use core::ptr::NonNull; -// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, -// `firmware_request_platform`, `bindings::request_firmware_direct` -type FwFunc = - unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32; +/// # Invariants +/// +/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, +/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`. +struct FwFunc( + unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32, +); + +impl FwFunc { + fn request() -> Self { + Self(bindings::request_firmware) + } + + fn request_nowarn() -> Self { + Self(bindings::firmware_request_nowarn) + } +} /// Abstraction around a C `struct firmware`. /// @@ -48,7 +61,7 @@ fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> { // SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer. // `name` and `dev` are valid as by their type invariants. - let ret = unsafe { func(pfw as _, name.as_char_ptr(), dev.as_raw()) }; + let ret = unsafe { func.0(pfw as _, name.as_char_ptr(), dev.as_raw()) }; if ret != 0 { return Err(Error::from_errno(ret)); } @@ -60,13 +73,13 @@ fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> { /// Send a firmware request and wait for it. See also `bindings::request_firmware`. pub fn request(name: &CStr, dev: &Device) -> Result<Self> { - Self::request_internal(name, dev, bindings::request_firmware) + Self::request_internal(name, dev, FwFunc::request()) } /// Send a request for an optional firmware module. See also /// `bindings::firmware_request_nowarn`. pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self> { - Self::request_internal(name, dev, bindings::firmware_request_nowarn) + Self::request_internal(name, dev, FwFunc::request_nowarn()) } fn as_raw(&self) -> *mut bindings::firmware { -- 2.45.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` 2024-07-08 20:07 ` [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` Danilo Krummrich @ 2024-07-08 20:37 ` Luis Chamberlain 2024-07-08 21:07 ` Danilo Krummrich 2024-07-08 22:16 ` Christian Schrefl 1 sibling, 1 reply; 5+ messages in thread From: Luis Chamberlain @ 2024-07-08 20:37 UTC (permalink / raw) To: Danilo Krummrich Cc: russ.weight, gregkh, chrisi.schrefl, linux-kernel, rust-for-linux, Gary Guo On Mon, Jul 08, 2024 at 10:07:21PM +0200, Danilo Krummrich wrote: > `request_internal` must be called with one of the following function > pointers: request_firmware(), firmware_request_nowarn(), > firmware_request_platform() or request_firmware_direct(). > > The previous `FwFunc` alias did not guarantee this, which is unsound. > > In order to fix this up, implement `FwFunc` as new type with a > corresponding type invariant. > > Reported-by: Gary Guo <gary@garyguo.net> > Closes: https://lore.kernel.org/lkml/20240620143611.7995e0bb@eugeo/ > Signed-off-by: Danilo Krummrich <dakr@redhat.com> While you're at it, can you go ahead and extend out selftest coverage for the firmware_loader so we can test Rust too? Could these issues have been caught with a selftest? If not why not? Luis ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` 2024-07-08 20:37 ` Luis Chamberlain @ 2024-07-08 21:07 ` Danilo Krummrich 0 siblings, 0 replies; 5+ messages in thread From: Danilo Krummrich @ 2024-07-08 21:07 UTC (permalink / raw) To: Luis Chamberlain Cc: russ.weight, gregkh, chrisi.schrefl, linux-kernel, rust-for-linux, Gary Guo On Mon, Jul 08, 2024 at 01:37:51PM -0700, Luis Chamberlain wrote: > On Mon, Jul 08, 2024 at 10:07:21PM +0200, Danilo Krummrich wrote: > > `request_internal` must be called with one of the following function > > pointers: request_firmware(), firmware_request_nowarn(), > > firmware_request_platform() or request_firmware_direct(). > > > > The previous `FwFunc` alias did not guarantee this, which is unsound. > > > > In order to fix this up, implement `FwFunc` as new type with a > > corresponding type invariant. > > > > Reported-by: Gary Guo <gary@garyguo.net> > > Closes: https://lore.kernel.org/lkml/20240620143611.7995e0bb@eugeo/ > > Signed-off-by: Danilo Krummrich <dakr@redhat.com> > > While you're at it, can you go ahead and extend out selftest coverage I think that'd be good and I thought about it. However, I think it makes more sense once we got a few more abstractions in place, such that we can come up with a Rust test module analogue to lib/test_firmware.c. What do you think? > for the firmware_loader so we can test Rust too? Could these issues > have been caught with a selftest? If not why not? This patch isn't actually fixing a real bug. Which is also why I didn't put a "Fixes" tag. It's more that without the `FwFunc` type indirection and the corresponding invariant the safety of `request_internal` isn't guranteed formally. - Danilo > > Luis > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` 2024-07-08 20:07 ` [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` Danilo Krummrich 2024-07-08 20:37 ` Luis Chamberlain @ 2024-07-08 22:16 ` Christian Schrefl 1 sibling, 0 replies; 5+ messages in thread From: Christian Schrefl @ 2024-07-08 22:16 UTC (permalink / raw) To: Danilo Krummrich, mcgrof, russ.weight, gregkh Cc: linux-kernel, rust-for-linux, Gary Guo Greetings On 08.07.24 10:07 PM, Danilo Krummrich wrote: > `request_internal` must be called with one of the following function > pointers: request_firmware(), firmware_request_nowarn(), > firmware_request_platform() or request_firmware_direct(). > > The previous `FwFunc` alias did not guarantee this, which is unsound. > > In order to fix this up, implement `FwFunc` as new type with a > corresponding type invariant. > > Reported-by: Gary Guo <gary@garyguo.net> > Closes: https://lore.kernel.org/lkml/20240620143611.7995e0bb@eugeo/ > Signed-off-by: Danilo Krummrich <dakr@redhat.com> > --- > v2: > - provide method for each wrapped `FwFunc` (Christian)> --- > rust/kernel/firmware.rs | 27 ++++++++++++++++++++------- > 1 file changed, 20 insertions(+), 7 deletions(-) > > diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs > index 106a928a535e..2ba03af9f036 100644 > --- a/rust/kernel/firmware.rs > +++ b/rust/kernel/firmware.rs > @@ -7,10 +7,23 @@ > use crate::{bindings, device::Device, error::Error, error::Result, str::CStr}; > use core::ptr::NonNull; > > -// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, > -// `firmware_request_platform`, `bindings::request_firmware_direct` > -type FwFunc = > - unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32; > +/// # Invariants > +/// > +/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, > +/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`. > +struct FwFunc( > + unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32, > +); > + > +impl FwFunc { > + fn request() -> Self { > + Self(bindings::request_firmware) > + } > + > + fn request_nowarn() -> Self { > + Self(bindings::firmware_request_nowarn) > + } I'm not sure if we should have a comment here that describes how the invariant is fulfilled. In this case its not too bad since the Invariants are described just a few lines above, so: Reviewed-by: Christian Schrefl <chrisi.schrefl@gmail.com> Cheers, Christian ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-07-08 22:16 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-07-08 20:07 [PATCH v2 1/2] firmware_loader: annotate doctests as `no_run` Danilo Krummrich 2024-07-08 20:07 ` [PATCH v2 2/2] firmware_loader: fix soundness issue in `request_internal` Danilo Krummrich 2024-07-08 20:37 ` Luis Chamberlain 2024-07-08 21:07 ` Danilo Krummrich 2024-07-08 22:16 ` Christian Schrefl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).