@@ -16,6 +16,10 @@ use core::str::{self, Utf8Error};
1616///
1717/// The kernel defines a set of integer generic error codes based on C and
1818/// POSIX ones. These codes may have a more specific meaning in some contexts.
19+ ///
20+ /// # Invariants
21+ ///
22+ /// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
1923#[ derive( Clone , Copy , PartialEq , Eq ) ]
2024pub struct Error ( c_types:: c_int ) ;
2125
@@ -57,7 +61,32 @@ impl Error {
5761 pub const EBADF : Self = Error ( -( bindings:: EBADF as i32 ) ) ;
5862
5963 /// Creates an [`Error`] from a kernel error code.
60- pub fn from_kernel_errno ( errno : c_types:: c_int ) -> Error {
64+ ///
65+ /// It is a bug to pass an out-of-range `errno`. `EINVAL` would
66+ /// be returned in such a case.
67+ pub ( crate ) fn from_kernel_errno ( errno : c_types:: c_int ) -> Error {
68+ if errno < -( bindings:: MAX_ERRNO as i32 ) || errno >= 0 {
69+ // TODO: make it a `WARN_ONCE` once available.
70+ crate :: pr_warn!(
71+ "attempted to create `Error` with out of range `errno`: {}" ,
72+ errno
73+ ) ;
74+ return Error :: EINVAL ;
75+ }
76+
77+ // INVARIANT: the check above ensures the type invariant
78+ // will hold.
79+ Error ( errno)
80+ }
81+
82+ /// Creates an [`Error`] from a kernel error code.
83+ ///
84+ /// # Safety
85+ ///
86+ /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
87+ pub ( crate ) unsafe fn from_kernel_errno_unchecked ( errno : c_types:: c_int ) -> Error {
88+ // INVARIANT: the contract ensures the type invariant
89+ // will hold.
6190 Error ( errno)
6291 }
6392
@@ -227,7 +256,10 @@ pub(crate) fn from_kernel_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
227256 // which always fits in an `i16`, as per the invariant above.
228257 // And an `i16` always fits in an `i32`. So casting `err` to
229258 // an `i32` can never overflow, and is always valid.
230- return Err ( Error :: from_kernel_errno ( err as i32 ) ) ;
259+ //
260+ // SAFETY: `rust_helper_is_err()` ensures `err` is a
261+ // negative value greater-or-equal to `-bindings::MAX_ERRNO`
262+ return Err ( unsafe { Error :: from_kernel_errno_unchecked ( err as i32 ) } ) ;
231263 }
232264 Ok ( ptr)
233265}
0 commit comments