Skip to content

Commit 5e8e061

Browse files
hoshinolinajannau
authored andcommitted
*RFL import: kernel::io_buffer
Commit reference: 3dfc5eb
1 parent 79a396e commit 5e8e061

2 files changed

Lines changed: 158 additions & 0 deletions

File tree

rust/kernel/io_buffer.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Buffers used in IO.
4+
5+
use crate::alloc::{flags::*, vec_ext::VecExt};
6+
use crate::error::Result;
7+
use alloc::vec::Vec;
8+
use core::mem::{size_of, MaybeUninit};
9+
10+
/// Represents a buffer to be read from during IO.
11+
pub trait IoBufferReader {
12+
/// Returns the number of bytes left to be read from the io buffer.
13+
///
14+
/// Note that even reading less than this number of bytes may fail.
15+
fn len(&self) -> usize;
16+
17+
/// Returns `true` if no data is available in the io buffer.
18+
fn is_empty(&self) -> bool {
19+
self.len() == 0
20+
}
21+
22+
/// Reads raw data from the io buffer into a raw kernel buffer.
23+
///
24+
/// # Safety
25+
///
26+
/// The output buffer must be valid.
27+
unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result;
28+
29+
/// Reads all data remaining in the io buffer.
30+
///
31+
/// Returns `EFAULT` if the address does not currently point to mapped, readable memory.
32+
fn read_all(&mut self) -> Result<Vec<u8>> {
33+
let mut data = Vec::<u8>::with_capacity(self.len(), GFP_KERNEL)?;
34+
// FIXME? data.resize(self.len(), 0);
35+
for _ in 0..self.len() {
36+
data.push(0, GFP_KERNEL)?
37+
}
38+
39+
// SAFETY: The output buffer is valid as we just allocated it.
40+
unsafe { self.read_raw(data.as_mut_ptr(), data.len())? };
41+
Ok(data)
42+
}
43+
44+
/// Reads a byte slice from the io buffer.
45+
///
46+
/// Returns `EFAULT` if the byte slice is bigger than the remaining size of the user slice or
47+
/// if the address does not currently point to mapped, readable memory.
48+
fn read_slice(&mut self, data: &mut [u8]) -> Result {
49+
// SAFETY: The output buffer is valid as it's coming from a live reference.
50+
unsafe { self.read_raw(data.as_mut_ptr(), data.len()) }
51+
}
52+
53+
/// Reads the contents of a plain old data (POD) type from the io buffer.
54+
fn read<T: ReadableFromBytes>(&mut self) -> Result<T> {
55+
let mut out = MaybeUninit::<T>::uninit();
56+
// SAFETY: The buffer is valid as it was just allocated.
57+
unsafe { self.read_raw(out.as_mut_ptr() as _, size_of::<T>()) }?;
58+
// SAFETY: We just initialised the data.
59+
Ok(unsafe { out.assume_init() })
60+
}
61+
}
62+
63+
/// Represents a buffer to be written to during IO.
64+
pub trait IoBufferWriter {
65+
/// Returns the number of bytes left to be written into the io buffer.
66+
///
67+
/// Note that even writing less than this number of bytes may fail.
68+
fn len(&self) -> usize;
69+
70+
/// Returns `true` if the io buffer cannot hold any additional data.
71+
fn is_empty(&self) -> bool {
72+
self.len() == 0
73+
}
74+
75+
/// Writes zeroes to the io buffer.
76+
///
77+
/// Differently from the other write functions, `clear` will zero as much as it can and update
78+
/// the writer internal state to reflect this. It will, however, return an error if it cannot
79+
/// clear `len` bytes.
80+
///
81+
/// For example, if a caller requests that 100 bytes be cleared but a segfault happens after
82+
/// 20 bytes, then EFAULT is returned and the writer is advanced by 20 bytes.
83+
fn clear(&mut self, len: usize) -> Result;
84+
85+
/// Writes a byte slice into the io buffer.
86+
///
87+
/// Returns `EFAULT` if the byte slice is bigger than the remaining size of the io buffer or if
88+
/// the address does not currently point to mapped, writable memory.
89+
fn write_slice(&mut self, data: &[u8]) -> Result {
90+
// SAFETY: The input buffer is valid as it's coming from a live reference.
91+
unsafe { self.write_raw(data.as_ptr(), data.len()) }
92+
}
93+
94+
/// Writes raw data to the io buffer from a raw kernel buffer.
95+
///
96+
/// # Safety
97+
///
98+
/// The input buffer must be valid.
99+
unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result;
100+
101+
/// Writes the contents of the given data into the io buffer.
102+
fn write<T: WritableToBytes>(&mut self, data: &T) -> Result {
103+
// SAFETY: The input buffer is valid as it's coming from a live
104+
// reference to a type that implements `WritableToBytes`.
105+
unsafe { self.write_raw(data as *const T as _, size_of::<T>()) }
106+
}
107+
}
108+
109+
/// Specifies that a type is safely readable from byte slices.
110+
///
111+
/// Not all types can be safely read from byte slices; examples from
112+
/// <https://doc.rust-lang.org/reference/behavior-considered-undefined.html> include `bool`
113+
/// that must be either `0` or `1`, and `char` that cannot be a surrogate or above `char::MAX`.
114+
///
115+
/// # Safety
116+
///
117+
/// Implementers must ensure that the type is made up only of types that can be safely read from
118+
/// arbitrary byte sequences (e.g., `u32`, `u64`, etc.).
119+
pub unsafe trait ReadableFromBytes {}
120+
121+
// SAFETY: All bit patterns are acceptable values of the types below.
122+
unsafe impl ReadableFromBytes for u8 {}
123+
unsafe impl ReadableFromBytes for u16 {}
124+
unsafe impl ReadableFromBytes for u32 {}
125+
unsafe impl ReadableFromBytes for u64 {}
126+
unsafe impl ReadableFromBytes for usize {}
127+
unsafe impl ReadableFromBytes for i8 {}
128+
unsafe impl ReadableFromBytes for i16 {}
129+
unsafe impl ReadableFromBytes for i32 {}
130+
unsafe impl ReadableFromBytes for i64 {}
131+
unsafe impl ReadableFromBytes for isize {}
132+
133+
/// Specifies that a type is safely writable to byte slices.
134+
///
135+
/// This means that we don't read undefined values (which leads to UB) in preparation for writing
136+
/// to the byte slice. It also ensures that no potentially sensitive information is leaked into the
137+
/// byte slices.
138+
///
139+
/// # Safety
140+
///
141+
/// A type must not include padding bytes and must be fully initialised to safely implement
142+
/// [`WritableToBytes`] (i.e., it doesn't contain [`MaybeUninit`] fields). A composition of
143+
/// writable types in a structure is not necessarily writable because it may result in padding
144+
/// bytes.
145+
pub unsafe trait WritableToBytes {}
146+
147+
// SAFETY: Initialised instances of the following types have no uninitialised portions.
148+
unsafe impl WritableToBytes for u8 {}
149+
unsafe impl WritableToBytes for u16 {}
150+
unsafe impl WritableToBytes for u32 {}
151+
unsafe impl WritableToBytes for u64 {}
152+
unsafe impl WritableToBytes for usize {}
153+
unsafe impl WritableToBytes for i8 {}
154+
unsafe impl WritableToBytes for i16 {}
155+
unsafe impl WritableToBytes for i32 {}
156+
unsafe impl WritableToBytes for i64 {}
157+
unsafe impl WritableToBytes for isize {}

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub mod error;
5151
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
5252
pub mod firmware;
5353
pub mod init;
54+
pub mod io_buffer;
5455
pub mod io_pgtable;
5556
pub mod ioctl;
5657
#[cfg(CONFIG_KUNIT)]

0 commit comments

Comments
 (0)