Skip to content

Commit a23b018

Browse files
dakrgregkh
authored andcommitted
firmware_loader: fix soundness issue in request_internal
`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 <[email protected]> Closes: https://lore.kernel.org/lkml/20240620143611.7995e0bb@eugeo/ Signed-off-by: Danilo Krummrich <[email protected]> Reviewed-by: Christian Schrefl <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2c61b8c commit a23b018

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

rust/kernel/firmware.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,23 @@
77
use crate::{bindings, device::Device, error::Error, error::Result, str::CStr};
88
use core::ptr::NonNull;
99

10-
// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
11-
// `firmware_request_platform`, `bindings::request_firmware_direct`
12-
type FwFunc =
13-
unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32;
10+
/// # Invariants
11+
///
12+
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
13+
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
14+
struct FwFunc(
15+
unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32,
16+
);
17+
18+
impl FwFunc {
19+
fn request() -> Self {
20+
Self(bindings::request_firmware)
21+
}
22+
23+
fn request_nowarn() -> Self {
24+
Self(bindings::firmware_request_nowarn)
25+
}
26+
}
1427

1528
/// Abstraction around a C `struct firmware`.
1629
///
@@ -48,7 +61,7 @@ impl Firmware {
4861

4962
// SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer.
5063
// `name` and `dev` are valid as by their type invariants.
51-
let ret = unsafe { func(pfw as _, name.as_char_ptr(), dev.as_raw()) };
64+
let ret = unsafe { func.0(pfw as _, name.as_char_ptr(), dev.as_raw()) };
5265
if ret != 0 {
5366
return Err(Error::from_errno(ret));
5467
}
@@ -60,13 +73,13 @@ impl Firmware {
6073

6174
/// Send a firmware request and wait for it. See also `bindings::request_firmware`.
6275
pub fn request(name: &CStr, dev: &Device) -> Result<Self> {
63-
Self::request_internal(name, dev, bindings::request_firmware)
76+
Self::request_internal(name, dev, FwFunc::request())
6477
}
6578

6679
/// Send a request for an optional firmware module. See also
6780
/// `bindings::firmware_request_nowarn`.
6881
pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self> {
69-
Self::request_internal(name, dev, bindings::firmware_request_nowarn)
82+
Self::request_internal(name, dev, FwFunc::request_nowarn())
7083
}
7184

7285
fn as_raw(&self) -> *mut bindings::firmware {

0 commit comments

Comments
 (0)