Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: map `long` to `isize` and `char` to `u8`

The following FFI types are replaced compared to `core::ffi`:

1. `char` type is now always mapped to `u8`, since kernel uses
`-funsigned-char` on the C code. `core::ffi` maps it to platform
default ABI, which can be either signed or unsigned.

2. `long` is now always mapped to `isize`. It's very common in the
kernel to use `long` to represent a pointer-sized integer, and in
fact `intptr_t` is a typedef of `long` in the kernel. Enforce this
mapping rather than mapping to `i32/i64` depending on platform can
save us a lot of unnecessary casts.

Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20240913213041.395655-5-gary@garyguo.net
[ Moved `uaccess` changes from the next commit, since they were
irrefutable patterns that Rust >= 1.82.0 warns about. Reworded
slightly and reformatted a few documentation comments. Rebased on
top of `rust-next`. Added the removal of two casts to avoid Clippy
warnings. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Gary Guo and committed by
Miguel Ojeda
1bae8729 27c7518e

+47 -28
+36 -1
rust/ffi.rs
··· 10 10 11 11 #![no_std] 12 12 13 - pub use core::ffi::*; 13 + macro_rules! alias { 14 + ($($name:ident = $ty:ty;)*) => {$( 15 + #[allow(non_camel_case_types, missing_docs)] 16 + pub type $name = $ty; 17 + 18 + // Check size compatibility with `core`. 19 + const _: () = assert!( 20 + core::mem::size_of::<$name>() == core::mem::size_of::<core::ffi::$name>() 21 + ); 22 + )*} 23 + } 24 + 25 + alias! { 26 + // `core::ffi::c_char` is either `i8` or `u8` depending on architecture. In the kernel, we use 27 + // `-funsigned-char` so it's always mapped to `u8`. 28 + c_char = u8; 29 + 30 + c_schar = i8; 31 + c_uchar = u8; 32 + 33 + c_short = i16; 34 + c_ushort = u16; 35 + 36 + c_int = i32; 37 + c_uint = u32; 38 + 39 + // In the kernel, `intptr_t` is defined to be `long` in all platforms, so we can map the type to 40 + // `isize`. 41 + c_long = isize; 42 + c_ulong = usize; 43 + 44 + c_longlong = i64; 45 + c_ulonglong = u64; 46 + } 47 + 48 + pub use core::ffi::c_void;
+1 -4
rust/kernel/error.rs
··· 153 153 154 154 /// Returns the error encoded as a pointer. 155 155 pub fn to_ptr<T>(self) -> *mut T { 156 - #[cfg_attr(target_pointer_width = "32", allow(clippy::useless_conversion))] 157 156 // SAFETY: `self.0` is a valid error due to its invariant. 158 - unsafe { 159 - bindings::ERR_PTR(self.0.get().into()) as *mut _ 160 - } 157 + unsafe { bindings::ERR_PTR(self.0.get() as _) as *mut _ } 161 158 } 162 159 163 160 /// Returns a string representing the error, if one exists.
+1 -1
rust/kernel/firmware.rs
··· 12 12 /// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, 13 13 /// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`. 14 14 struct FwFunc( 15 - unsafe extern "C" fn(*mut *const bindings::firmware, *const i8, *mut bindings::device) -> i32, 15 + unsafe extern "C" fn(*mut *const bindings::firmware, *const u8, *mut bindings::device) -> i32, 16 16 ); 17 17 18 18 impl FwFunc {
+2 -2
rust/kernel/miscdevice.rs
··· 225 225 // SAFETY: Ioctl calls can borrow the private data of the file. 226 226 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; 227 227 228 - match T::ioctl(device, cmd, arg as usize) { 228 + match T::ioctl(device, cmd, arg) { 229 229 Ok(ret) => ret as c_long, 230 230 Err(err) => err.to_errno() as c_long, 231 231 } ··· 245 245 // SAFETY: Ioctl calls can borrow the private data of the file. 246 246 let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; 247 247 248 - match T::compat_ioctl(device, cmd, arg as usize) { 248 + match T::compat_ioctl(device, cmd, arg) { 249 249 Ok(ret) => ret as c_long, 250 250 Err(err) => err.to_errno() as c_long, 251 251 }
+7 -20
rust/kernel/uaccess.rs
··· 8 8 alloc::Flags, 9 9 bindings, 10 10 error::Result, 11 - ffi::{c_ulong, c_void}, 11 + ffi::c_void, 12 12 prelude::*, 13 13 transmute::{AsBytes, FromBytes}, 14 14 }; ··· 224 224 if len > self.length { 225 225 return Err(EFAULT); 226 226 } 227 - let Ok(len_ulong) = c_ulong::try_from(len) else { 228 - return Err(EFAULT); 229 - }; 230 - // SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write 227 + // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write 231 228 // that many bytes to it. 232 - let res = 233 - unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) }; 229 + let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) }; 234 230 if res != 0 { 235 231 return Err(EFAULT); 236 232 } ··· 255 259 if len > self.length { 256 260 return Err(EFAULT); 257 261 } 258 - let Ok(len_ulong) = c_ulong::try_from(len) else { 259 - return Err(EFAULT); 260 - }; 261 262 let mut out: MaybeUninit<T> = MaybeUninit::uninit(); 262 263 // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes. 263 264 // ··· 265 272 bindings::_copy_from_user( 266 273 out.as_mut_ptr().cast::<c_void>(), 267 274 self.ptr as *const c_void, 268 - len_ulong, 275 + len, 269 276 ) 270 277 }; 271 278 if res != 0 { ··· 328 335 if len > self.length { 329 336 return Err(EFAULT); 330 337 } 331 - let Ok(len_ulong) = c_ulong::try_from(len) else { 332 - return Err(EFAULT); 333 - }; 334 - // SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read 338 + // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read 335 339 // that many bytes from it. 336 - let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) }; 340 + let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) }; 337 341 if res != 0 { 338 342 return Err(EFAULT); 339 343 } ··· 349 359 if len > self.length { 350 360 return Err(EFAULT); 351 361 } 352 - let Ok(len_ulong) = c_ulong::try_from(len) else { 353 - return Err(EFAULT); 354 - }; 355 362 // SAFETY: The reference points to a value of type `T`, so it is valid for reading 356 363 // `size_of::<T>()` bytes. 357 364 // ··· 359 372 bindings::_copy_to_user( 360 373 self.ptr as *mut c_void, 361 374 (value as *const T).cast::<c_void>(), 362 - len_ulong, 375 + len, 363 376 ) 364 377 }; 365 378 if res != 0 {