@@ -16,6 +16,10 @@ use core::str::{self, Utf8Error};
16
16
///
17
17
/// The kernel defines a set of integer generic error codes based on C and
18
18
/// 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`).
19
23
#[ derive( Clone , Copy , PartialEq , Eq ) ]
20
24
pub struct Error ( c_types:: c_int ) ;
21
25
@@ -57,7 +61,32 @@ impl Error {
57
61
pub const EBADF : Self = Error ( -( bindings:: EBADF as i32 ) ) ;
58
62
59
63
/// 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.
61
90
Error ( errno)
62
91
}
63
92
@@ -227,7 +256,10 @@ pub(crate) fn from_kernel_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
227
256
// which always fits in an `i16`, as per the invariant above.
228
257
// And an `i16` always fits in an `i32`. So casting `err` to
229
258
// 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 ) } ) ;
231
263
}
232
264
Ok ( ptr)
233
265
}
0 commit comments