Skip to content

Commit 5b4b7a4

Browse files
author
Sven Van Asbroeck
committed
rust/kernel: improve from_kernel_result! macro safety
`from_kernel_result!` could panic if the return integer type (`T`) is unable to hold the negative `errno`. Since `errno`s range from `0` to `4095`, functions returning integer types unable to hold values in the [-4095, 0] range could potentially panic. This includes all unsigned integers, and signed integers with insufficient bits, such as `c_char`. Fix by making sure that the return integer type is always suitable to hold the negative `errno`. Use the Rust type system to verify this at build time. Signed-off-by: Sven Van Asbroeck <[email protected]>
1 parent 2ce3372 commit 5b4b7a4

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

rust/kernel/error.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use crate::{bindings, c_types};
88
use alloc::{alloc::AllocError, collections::TryReserveError};
9-
use core::convert::TryFrom;
9+
use core::convert::From;
1010
use core::{num::TryFromIntError, str::Utf8Error};
1111

1212
/// Generic integer kernel error.
@@ -106,15 +106,20 @@ impl From<AllocError> for Error {
106106
}
107107
}
108108

109+
// # Invariant: `-bindings::MAX_ERRNO` fits in an `i16`.
110+
crate::static_assert!(bindings::MAX_ERRNO <= -(i16::MIN as i32) as u32);
111+
109112
#[doc(hidden)]
110113
pub fn from_kernel_result_helper<T>(r: Result<T>) -> T
111114
where
112-
T: TryFrom<c_types::c_int>,
113-
T::Error: core::fmt::Debug,
115+
T: From<i16>,
114116
{
115117
match r {
116118
Ok(v) => v,
117-
Err(e) => T::try_from(e.to_kernel_errno()).unwrap(),
119+
// NO-OVERFLOW: negative `errno`s are no smaller than `-bindings::MAX_ERRNO`,
120+
// `-bindings::MAX_ERRNO` fits in an `i16` as per invariant above,
121+
// therefore a negative `errno` always fits in an `i16` and will not overflow.
122+
Err(e) => T::from(e.to_kernel_errno() as i16),
118123
}
119124
}
120125

@@ -124,7 +129,7 @@ where
124129
/// from inside `extern "C"` functions that need to return an integer
125130
/// error result.
126131
///
127-
/// `T` should be convertible to an integer via `TryFrom<c_types::c_int>`.
132+
/// `T` should be convertible to an `i16` via `From<i16>`.
128133
///
129134
/// # Examples
130135
///

0 commit comments

Comments
 (0)