summaryrefslogtreecommitdiffstats
path: root/rust
diff options
context:
space:
mode:
authorBrendan Shephard <bshephar@bne-home.net>2025-12-23 15:56:47 +1000
committerDanilo Krummrich <dakr@kernel.org>2025-12-29 15:32:53 +0100
commitf91ffed95c06e94c835cd7deaea666d69948cde9 (patch)
tree071dbb153cf2f4baaf5e724afb4b1e780bf59c70 /rust
parent51293e589bafb4281a597986b3416471f67a79c2 (diff)
downloadlinux-f91ffed95c06e94c835cd7deaea666d69948cde9.tar.gz
linux-f91ffed95c06e94c835cd7deaea666d69948cde9.zip
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>
Diffstat (limited to 'rust')
-rw-r--r--rust/kernel/page.rs36
1 files changed, 29 insertions, 7 deletions
diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs
index 432fc0297d4a..adecb200c654 100644
--- a/rust/kernel/page.rs
+++ b/rust/kernel/page.rs
@@ -25,14 +25,36 @@ pub const PAGE_SIZE: usize = bindings::PAGE_SIZE;
/// 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`].