Currently, Rust code uses a typedef for unsigned long to represent
userspace addresses. This is unfortunate because it means that userspace
addresses could accidentally be mixed up with other integers. To
alleviate that, we introduce a new UserPtr struct that wraps a raw
pointer to represent a userspace address. By using a struct, type
checking enforces that userspace addresses cannot be mixed up with
anything else.
This is similar to the __user annotation in C that detects cases where
user pointers are mixed with non-user pointers.
Note that unlike __user pointers in C, this type is just a pointer
without a target type. This means that it can't detect cases such as
mixing up which struct this user pointer references. However, that is
okay due to the way this is intended to be used - generally, you create
a UserPtr in your ioctl callback from the provided usize *before*
dispatching on which ioctl is in use, and then after dispatching on the
ioctl you pass the UserPtr into a UserSliceReader or UserSliceWriter;
selecting the target type does not happen until you have obtained the
UserSliceReader/Writer.
The UserPtr type is not marked with #[derive(Debug)], which means that
it's not possible to print values of this type. This avoids ASLR
leakage.
The type is added to the prelude as it is a fairly fundamental type
similar to c_int. The wrapping_add() method is renamed to
wrapping_byte_add() for consistency with the method name found on raw
pointers.
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Danilo Krummrich <[email protected]>
Reviewed-by: Christian Schrefl <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Reworded title. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
This patch adds a more convenient method for reading C strings from
userspace. Logic is added to NUL-terminate the buffer when necessary so
that a &CStr can be returned.
Note that we treat attempts to read past `self.length` as a fault, so
this returns EFAULT if that limit is exceeded before `buf.len()` is
reached.
Reviewed-by: Danilo Krummrich <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Use `from_mut` to clean `clippy::ref_as_ptr` lint. Reworded
title. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
This patch adds a direct wrapper around the C function of the same name.
It's not really intended for direct use by Rust code since
strncpy_from_user has a somewhat unfortunate API where it only
nul-terminates the buffer if there's space for the nul-terminator. This
means that a direct Rust wrapper around it could not return a &CStr
since the buffer may not be a cstring. However, we still add the method
to build more convenient APIs on top of it, which will happen in
subsequent patches.
Reviewed-by: Danilo Krummrich <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Reworded title. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
The `kernel` prelude brings `Result` and the error codes; and the prelude
itself is already available in the examples automatically.
In addition, `Result` already defaults to `T = ()`.
Thus simplify.
Reviewed-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Miguel Ojeda <[email protected]>
The UserSliceReader::read_all function is currently restricted to use
only Vec with the kmalloc allocator. However, there is no reason for
this limitation.
This patch generalizes the function to accept any Vec regardless of the
allocator used.
There's a use-case for a KVVec in Binder to avoid maximum sizes for a
certain array.
Link: https://github.com/Rust-for-Linux/linux/issues/1136
Signed-off-by: Filipe Xavier <[email protected]>
Reviewed-by: Alice Ryhl <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Reflowed and slightly reworded title. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
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 <[email protected]>
Reviewed-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ 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 <[email protected]>
Currently FFI integer types are defined in libcore. This commit creates
the `ffi` crate and asks bindgen to use that crate for FFI integer types
instead of `core::ffi`.
This commit is preparatory and no type changes are made in this commit
yet.
Signed-off-by: Gary Guo <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Added `rustdoc`, `rusttest` and KUnit tests support. Rebased on top of
`rust-next` (e.g. migrated more `core::ffi` cases). Reworded crate
docs slightly and formatted. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
Refactor the `FromBytes` and `AsBytes` traits from `types.rs` into a new
`transmute.rs` module:
- Add `rust/kernel/transmute.rs` with the definitions of `FromBytes`
and `AsBytes`.
- Remove the same trait definitions from `rust/kernel/types.rs`.
- Update `rust/kernel/uaccess.rs` to import `AsBytes` and `FromBytes`
from `transmute.rs`.
The traits and their implementations remain unchanged.
Suggested-by: Benno Lossin <[email protected]>
Link: https://github.com/Rust-for-Linux/linux/issues/1117
Signed-off-by: Aliet Exposito Garcia <[email protected]>
Reviewed-by: Fiona Behrens <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Rebased on top of the lints series and slightly reworded. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
Add safe methods for reading and writing Rust values to and from
userspace pointers.
The C methods for copying to/from userspace use a function called
`check_object_size` to verify that the kernel pointer is not dangling.
However, this check is skipped when the length is a compile-time
constant, with the assumption that such cases trivially have a correct
kernel pointer.
In this patch, we apply the same optimization to the typed accessors.
For both methods, the size of the operation is known at compile time to
be size_of of the type being read or written. Since the C side doesn't
provide a variant that skips only this check, we create custom helpers
for this purpose.
The majority of reads and writes to userspace pointers in the Rust
Binder driver uses these accessor methods. Benchmarking has found that
skipping the `check_object_size` check makes a big difference for the
cases being skipped here. (And that the check doesn't make a difference
for the cases that use the raw read/write methods.)
This code is based on something that was originally written by Wedson on
the old rust branch. It was modified by Alice to skip the
`check_object_size` check, and to update various comments, including the
notes about kernel pointers in `WritableToBytes`.
Co-developed-by: Wedson Almeida Filho <[email protected]>
Signed-off-by: Wedson Almeida Filho <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Reviewed-by: Trevor Gross <[email protected]>
Reviewed-by: Gary Guo <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Wrapped docs to 100 and added a few intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
A pointer to an area in userspace memory, which can be either read-only
or read-write.
All methods on this struct are safe: attempting to read or write on bad
addresses (either out of the bound of the slice or unmapped addresses)
will return `EFAULT`. Concurrent access, *including data races to/from
userspace memory*, is permitted, because fundamentally another userspace
thread/process could always be modifying memory at the same time (in the
same way that userspace Rust's `std::io` permits data races with the
contents of files on disk). In the presence of a race, the exact byte
values read/written are unspecified but the operation is well-defined.
Kernelspace code should validate its copy of data after completing a
read, and not expect that multiple reads of the same address will return
the same value.
These APIs are designed to make it difficult to accidentally write
TOCTOU bugs. Every time you read from a memory location, the pointer is
advanced by the length so that you cannot use that reader to read the
same memory location twice. Preventing double-fetches avoids TOCTOU
bugs. This is accomplished by taking `self` by value to prevent
obtaining multiple readers on a given `UserSlice`, and the readers only
permitting forward reads. If double-fetching a memory location is
necessary for some reason, then that is done by creating multiple
readers to the same memory location.
Constructing a `UserSlice` performs no checks on the provided address
and length, it can safely be constructed inside a kernel thread with no
current userspace process. Reads and writes wrap the kernel APIs
`copy_from_user` and `copy_to_user`, which check the memory map of the
current process and enforce that the address range is within the user
range (no additional calls to `access_ok` are needed).
This code is based on something that was originally written by Wedson on
the old rust branch. It was modified by Alice by removing the
`IoBufferReader` and `IoBufferWriter` traits, and various other changes.
Signed-off-by: Wedson Almeida Filho <[email protected]>
Reviewed-by: Benno Lossin <[email protected]>
Reviewed-by: Trevor Gross <[email protected]>
Reviewed-by: Boqun Feng <[email protected]>
Co-developed-by: Alice Ryhl <[email protected]>
Signed-off-by: Alice Ryhl <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Wrapped docs to 100 and added a few intra-doc links. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>