mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-30 07:13:58 -04:00
rust: Return Option from page_align and ensure no usize overflow
Change `page_align()` to return `Option<usize>` to allow validation of the provided `addr` value. This ensures that any value that is within one `PAGE_SIZE` of `usize::MAX` will not panic, and instead returns `None` to indicate overflow. Signed-off-by: Brendan Shephard <bshephar@bne-home.net> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://patch.msgid.link/20251223055647.9761-1-bshephar@bne-home.net [ Use kernel vertical style for imports; use markdown in comments. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
committed by
Danilo Krummrich
parent
51293e589b
commit
f91ffed95c
@@ -25,14 +25,36 @@
|
||||
/// A bitmask that gives the page containing a given address.
|
||||
pub const PAGE_MASK: usize = !(PAGE_SIZE - 1);
|
||||
|
||||
/// Round up the given number to the next multiple of [`PAGE_SIZE`].
|
||||
/// Rounds up to the next multiple of [`PAGE_SIZE`].
|
||||
///
|
||||
/// It is incorrect to pass an address where the next multiple of [`PAGE_SIZE`] doesn't fit in a
|
||||
/// [`usize`].
|
||||
pub const fn page_align(addr: usize) -> usize {
|
||||
// Parentheses around `PAGE_SIZE - 1` to avoid triggering overflow sanitizers in the wrong
|
||||
// cases.
|
||||
(addr + (PAGE_SIZE - 1)) & PAGE_MASK
|
||||
/// Returns [`None`] on integer overflow.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use kernel::page::{
|
||||
/// page_align,
|
||||
/// PAGE_SIZE,
|
||||
/// };
|
||||
///
|
||||
/// // Requested address is already aligned.
|
||||
/// assert_eq!(page_align(0x0), Some(0x0));
|
||||
/// assert_eq!(page_align(PAGE_SIZE), Some(PAGE_SIZE));
|
||||
///
|
||||
/// // Requested address needs alignment up.
|
||||
/// assert_eq!(page_align(0x1), Some(PAGE_SIZE));
|
||||
/// assert_eq!(page_align(PAGE_SIZE + 1), Some(2 * PAGE_SIZE));
|
||||
///
|
||||
/// // Requested address causes overflow (returns `None`).
|
||||
/// let overflow_addr = usize::MAX - (PAGE_SIZE / 2);
|
||||
/// assert_eq!(page_align(overflow_addr), None);
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub const fn page_align(addr: usize) -> Option<usize> {
|
||||
let Some(sum) = addr.checked_add(PAGE_SIZE - 1) else {
|
||||
return None;
|
||||
};
|
||||
Some(sum & PAGE_MASK)
|
||||
}
|
||||
|
||||
/// Representation of a non-owning reference to a [`Page`].
|
||||
|
||||
Reference in New Issue
Block a user