* [PATCH v8 0/4] rust: Add safe pointer formatting support
@ 2026-01-01 8:16 Ke Sun
2026-01-01 8:16 ` [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use Ke Sun
` (3 more replies)
0 siblings, 4 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-01 8:16 UTC (permalink / raw)
To: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux, Ke Sun
This patch series adds safe pointer formatting support for Rust kernel code,
providing two pointer wrapper types (HashedPtr, RawPtr) that correspond to
C kernel's printk format specifiers %p and %px.
The implementation ensures that raw pointers are automatically hashed when
formatted with {:p}, providing safe default behavior that prevents information
leaks about kernel memory layout. Users can also explicitly use wrapper types
when they need specific formatting behavior.
---
v8:
- Remove RestrictedPtr (%pK) support: only export ptr_to_hashval() with
EXPORT_SYMBOL_NS_GPL using "RUST_INTERNAL" namespace, provide only two
pointer wrapper types (HashedPtr, RawPtr) for %p and %px
- Change API from HashedPtr::from(ptr) to HashedPtr(ptr) for direct construction
v7: https://lore.kernel.org/rust-for-linux/20251229072157.3857053-1-sunke@kylinos.cn/
- Refactor kptr_restrict handling: extract kptr_restrict_value() from
restricted_pointer() in lib/vsprintf.c and export it for Rust use, and
improve RestrictedPtr::fmt() implementation to directly handle
kptr_restrict_value() return values (0, 1, 2, -1) for better code clarity
- Remove Debug derive from pointer wrapper types (HashedPtr, RestrictedPtr, RawPtr)
v6: https://lore.kernel.org/rust-for-linux/20251227033958.3713232-1-sunke@kylinos.cn/
- Fix placeholder formatting to use `f.pad()` instead of `f.write_str()` in
format_hashed_ptr(), ensuring width, alignment, and padding options are
correctly applied to PTR_PLACEHOLDER
v5: https://lore.kernel.org/rust-for-linux/20251226140751.2215563-1-sunke@kylinos.cn/
- Format use statements in rust/kernel/ptr.rs and rust/kernel/fmt.rs using kernel
vertical style with alphabetical ordering
- Remove unnecessary SAFETY comment in rust/kernel/ptr.rs (addressed Clippy warning)
- Update type ordering to alphabetical (HashedPtr, RawPtr, RestrictedPtr) in
fmt.rs macro invocation
v4: https://lore.kernel.org/rust-for-linux/20251225225709.3944255-1-sunke@kylinos.cn/
- Use Pointer::fmt() instead of write!(f, "{:p}", ...) to preserve formatting
options (width, alignment, padding characters)
- Improve code structure: reduce unsafe block scope, use early return pattern
- Add doctests with formatting option tests for all pointer wrapper types
- Enhance documentation with detailed formatting options section, including
examples for width, alignment, and padding
- Fix RestrictedPtr example to use pr_info! instead of seq_print! in docs
v3: https://lore.kernel.org/rust-for-linux/20251224081315.729684-1-sunke@kylinos.cn/
- Export ptr_to_hashval() from lib/vsprintf.c for Rust pointer hashing
- Add three pointer wrapper types (HashedPtr, RestrictedPtr, RawPtr) in
rust/kernel/ptr.rs corresponding to %p, %pK, and %px
- Make raw pointers automatically use HashedPtr when formatted with {:p}
- Add documentation for pointer wrapper types
v2: https://lore.kernel.org/rust-for-linux/20251223033018.2814732-1-sunke@kylinos.cn/
- Disabled {:p} raw pointer printing by default to prevent accidental
information leaks
v1: https://lore.kernel.org/rust-for-linux/20251218032709.2184890-1-sunke@kylinos.cn/
- Initial implementation that directly printed raw pointers
---
Ke Sun (4):
lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use
rust: kernel: Add pointer wrapper types for safe pointer formatting
rust: fmt: Default raw pointer formatting to HashedPtr
docs: rust: Add pointer formatting documentation
Documentation/rust/index.rst | 1 +
Documentation/rust/pointer-formatting.rst | 90 +++++++++++++++
lib/vsprintf.c | 1 +
rust/kernel/fmt.rs | 64 ++++++++++-
rust/kernel/ptr.rs | 133 +++++++++++++++++++++-
5 files changed, 285 insertions(+), 4 deletions(-)
create mode 100644 Documentation/rust/pointer-formatting.rst
base-commit: 7839932417dd53bb09eb5a585a7a92781dfd7cb2
--
2.43.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use
2026-01-01 8:16 [PATCH v8 0/4] rust: Add safe pointer formatting support Ke Sun
@ 2026-01-01 8:16 ` Ke Sun
2026-01-02 12:15 ` Andy Shevchenko
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
` (2 subsequent siblings)
3 siblings, 1 reply; 20+ messages in thread
From: Ke Sun @ 2026-01-01 8:16 UTC (permalink / raw)
To: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux, Ke Sun
Export ptr_to_hashval() with EXPORT_SYMBOL_NS_GPL using the "RUST_INTERNAL"
namespace. This function is used to hash kernel pointers before printing
them, preventing information leaks about kernel memory layout.
Signed-off-by: Ke Sun <sunke@kylinos.cn>
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
lib/vsprintf.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a3790c43a0aba..7311550f6064a 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -811,6 +811,7 @@ int ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
{
return __ptr_to_hashval(ptr, hashval_out);
}
+EXPORT_SYMBOL_NS_GPL(ptr_to_hashval, "RUST_INTERNAL");
static char *ptr_to_id(char *buf, char *end, const void *ptr,
struct printf_spec spec)
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-01 8:16 [PATCH v8 0/4] rust: Add safe pointer formatting support Ke Sun
2026-01-01 8:16 ` [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use Ke Sun
@ 2026-01-01 8:16 ` Ke Sun
2026-01-02 7:57 ` Dirk Behme
` (2 more replies)
2026-01-01 8:16 ` [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr Ke Sun
2026-01-01 8:16 ` [PATCH v8 4/4] docs: rust: Add pointer formatting documentation Ke Sun
3 siblings, 3 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-01 8:16 UTC (permalink / raw)
To: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux, Ke Sun
Add two pointer wrapper types (HashedPtr, RawPtr) to rust/kernel/ptr.rs
that correspond to C kernel's printk format specifiers %p and %px. These
types provide type-safe pointer formatting that matches C kernel patterns.
These wrapper types implement core::fmt::Pointer and delegate to the
corresponding kernel formatting functions, enabling safe pointer
formatting in Rust code that prevents information leaks about kernel
memory layout.
Users can explicitly use these types:
pr_info!("{:p}\n", HashedPtr(ptr));
pr_info!("{:p}\n", RawPtr(ptr));
HashedPtr uses ptr_to_hashval() to hash pointers before printing,
providing the default safe behavior for kernel pointers. RawPtr prints
the raw address and should only be used for debugging purposes.
Signed-off-by: Ke Sun <sunke@kylinos.cn>
Suggested-by: Dirk Behme <dirk.behme@gmail.com>
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
rust/kernel/ptr.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 130 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index e3893ed04049d..77132eaaef73b 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -1,11 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
//! Types and functions to work with pointers and addresses.
+//!
+//! This module provides wrapper types for formatting kernel pointers that correspond to the
+//! C kernel's printk format specifiers `%p` and `%px`.
-use core::mem::align_of;
-use core::num::NonZero;
+use core::{
+ fmt,
+ fmt::Pointer,
+ mem::align_of,
+ num::NonZero, //
+};
-use crate::build_assert;
+use crate::{
+ bindings,
+ build_assert,
+ prelude::*, //
+};
/// Type representing an alignment, which is always a power of two.
///
@@ -225,3 +236,119 @@ fn align_up(self, alignment: Alignment) -> Option<Self> {
}
impl_alignable_uint!(u8, u16, u32, u64, usize);
+
+/// Placeholder string used when pointer hashing is not ready yet.
+const PTR_PLACEHOLDER: &str = if size_of::<*const c_void>() == 8 {
+ "(____ptrval____)"
+} else {
+ "(ptrval)"
+};
+
+/// Helper function to hash a pointer and format it.
+///
+/// Returns `Ok(())` if the hash was successfully computed and formatted,
+/// or the placeholder string if hashing is not ready yet.
+fn format_hashed_ptr(ptr: *const c_void, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut hashval: crate::ffi::c_ulong = 0;
+ // SAFETY: We're calling the kernel's ptr_to_hashval function which handles
+ // hashing. This is safe as long as ptr is a valid pointer value.
+ let ret = unsafe { bindings::ptr_to_hashval(ptr, &mut hashval) };
+
+ if ret != 0 {
+ // Hash not ready yet, print placeholder with formatting options applied
+ // Using `pad()` ensures width, alignment, and padding options are respected
+ return f.pad(PTR_PLACEHOLDER);
+ }
+
+ // Successfully got hash value, format it using Pointer::fmt to preserve
+ // formatting options (width, alignment, padding, etc.)
+ Pointer::fmt(&(hashval as *const c_void), f)
+}
+
+/// A pointer that will be hashed when printed (corresponds to `%p`).
+///
+/// This is the default behavior for kernel pointers - they are hashed to prevent
+/// leaking information about the kernel memory layout.
+///
+/// # Example
+///
+/// ```
+/// use kernel::{
+/// prelude::fmt,
+/// ptr::HashedPtr,
+/// str::CString, //
+/// };
+///
+/// let ptr = HashedPtr(0x12345678 as *const u8);
+/// pr_info!("Hashed pointer: {:016p}\n", ptr);
+///
+/// // Width option test
+/// let cstr = CString::try_from_fmt(fmt!("{:30p}", ptr))?;
+/// let width_30 = cstr.to_str()?;
+/// assert_eq!(width_30.len(), 30);
+/// # Ok::<(), kernel::error::Error>(())
+/// ```
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+pub struct HashedPtr<T>(pub *const T);
+
+impl<T> fmt::Pointer for HashedPtr<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Handle NULL pointers - print them directly
+ let ptr = self.0.cast::<c_void>();
+ if ptr.is_null() {
+ return Pointer::fmt(&ptr, f);
+ }
+
+ format_hashed_ptr(ptr, f)
+ }
+}
+
+/// A pointer that will be printed as its raw address (corresponds to `%px`).
+///
+/// **Warning**: This exposes the real kernel address and should only be used
+/// for debugging purposes. Consider using [`HashedPtr`] instead for production code.
+///
+/// # Example
+///
+/// ```
+/// use kernel::{
+/// prelude::fmt,
+/// ptr::RawPtr,
+/// str::CString, //
+/// };
+///
+/// let ptr = RawPtr(0x12345678 as *const u8);
+///
+/// // Basic formatting
+/// let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
+/// let formatted = cstr.to_str()?;
+/// assert_eq!(formatted, "0x12345678");
+///
+/// // Right align with zero padding, width 30
+/// let cstr = CString::try_from_fmt(fmt!("{:0>30p}", ptr))?;
+/// let right_zero = cstr.to_str()?;
+/// assert_eq!(right_zero, "000000000000000000000x12345678");
+///
+/// // Left align with zero padding, width 30
+/// let cstr = CString::try_from_fmt(fmt!("{:0<30p}", ptr))?;
+/// let left_zero = cstr.to_str()?;
+/// assert_eq!(left_zero, "0x1234567800000000000000000000");
+///
+/// // Center align with zero padding, width 30
+/// let cstr = CString::try_from_fmt(fmt!("{:0^30p}", ptr))?;
+/// let center_zero = cstr.to_str()?;
+/// assert_eq!(center_zero, "00000000000x123456780000000000");
+/// # Ok::<(), kernel::error::Error>(())
+/// ```
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+pub struct RawPtr<T>(pub *const T);
+
+impl<T> fmt::Pointer for RawPtr<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Directly format the raw address - no hashing or restriction.
+ // This corresponds to %px behavior.
+ Pointer::fmt(&self.0.cast::<c_void>(), f)
+ }
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-01 8:16 [PATCH v8 0/4] rust: Add safe pointer formatting support Ke Sun
2026-01-01 8:16 ` [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use Ke Sun
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
@ 2026-01-01 8:16 ` Ke Sun
2026-01-02 11:17 ` Gary Guo
2026-01-02 17:39 ` Petr Mladek
2026-01-01 8:16 ` [PATCH v8 4/4] docs: rust: Add pointer formatting documentation Ke Sun
3 siblings, 2 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-01 8:16 UTC (permalink / raw)
To: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux, Ke Sun
Make raw pointers (*const T, *mut T) automatically use HashedPtr when
formatted with {:p}, providing safe default behavior for kernel pointers.
This allows users to format raw pointers directly:
pr_info!("{:p}\n", ptr); // Automatically hashed
While still allowing explicit use of wrapper types when needed:
pr_info!("{:p}\n", RawPtr(ptr));
Signed-off-by: Ke Sun <sunke@kylinos.cn>
---
rust/kernel/fmt.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs
index 84d634201d90a..8be185d522c01 100644
--- a/rust/kernel/fmt.rs
+++ b/rust/kernel/fmt.rs
@@ -6,6 +6,11 @@
pub use core::fmt::{Arguments, Debug, Error, Formatter, Result, Write};
+use crate::ptr::{
+ HashedPtr,
+ RawPtr, //
+};
+
/// Internal adapter used to route allow implementations of formatting traits for foreign types.
///
/// It is inserted automatically by the [`fmt!`] macro and is not meant to be used directly.
@@ -28,7 +33,64 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
}
use core::fmt::{Binary, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex};
-impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, Pointer, LowerExp, UpperExp);
+impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, LowerExp, UpperExp);
+
+// Special handling for Pointer: default to HashedPtr for raw pointers.
+// This overrides the default Pointer implementation for raw pointers to use hashing,
+// which is the safe default behavior for kernel pointers.
+impl<T> Pointer for Adapter<*const T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(ptr) = self;
+ Pointer::fmt(&HashedPtr(*ptr), f)
+ }
+}
+
+impl<T> Pointer for Adapter<*mut T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(ptr) = self;
+ Pointer::fmt(&HashedPtr(*ptr), f)
+ }
+}
+
+// Handle references to raw pointers (needed when pointers are passed by reference in macros).
+impl<T> Pointer for Adapter<&*const T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(ptr) = self;
+ Pointer::fmt(&HashedPtr(**ptr), f)
+ }
+}
+
+impl<T> Pointer for Adapter<&*mut T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(ptr) = self;
+ Pointer::fmt(&HashedPtr(**ptr), f)
+ }
+}
+
+// For wrapper types that implement Pointer (like HashedPtr, RawPtr),
+// forward to their implementation. This allows explicit wrapper types to use their
+// own formatting logic instead of being converted to HashedPtr.
+macro_rules! impl_pointer_adapter_forward {
+ ($($ty:ident),* $(,)?) => {
+ $(
+ impl<T> Pointer for Adapter<$ty<T>> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(t) = self;
+ Pointer::fmt(t, f)
+ }
+ }
+
+ impl<T> Pointer for Adapter<&$ty<T>> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ let Self(t) = self;
+ Pointer::fmt(*t, f)
+ }
+ }
+ )*
+ };
+}
+
+impl_pointer_adapter_forward!(HashedPtr, RawPtr);
/// A copy of [`core::fmt::Display`] that allows us to implement it for foreign types.
///
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v8 4/4] docs: rust: Add pointer formatting documentation
2026-01-01 8:16 [PATCH v8 0/4] rust: Add safe pointer formatting support Ke Sun
` (2 preceding siblings ...)
2026-01-01 8:16 ` [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr Ke Sun
@ 2026-01-01 8:16 ` Ke Sun
3 siblings, 0 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-01 8:16 UTC (permalink / raw)
To: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux, Ke Sun
Add documentation for Rust pointer wrapper types (HashedPtr, RawPtr)
that correspond to C kernel's printk format specifiers %p and %px.
The documentation provides:
- Overview of the two wrapper types
- Usage examples for each type
- When to use each type
- Security considerations
- Formatting options
This complements the general pointer formatting documentation in
Documentation/core-api/printk-formats.rst.
Signed-off-by: Ke Sun <sunke@kylinos.cn>
---
Documentation/rust/index.rst | 1 +
Documentation/rust/pointer-formatting.rst | 90 +++++++++++++++++++++++
2 files changed, 91 insertions(+)
create mode 100644 Documentation/rust/pointer-formatting.rst
diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst
index ec62001c7d8c7..4f4f8b393031e 100644
--- a/Documentation/rust/index.rst
+++ b/Documentation/rust/index.rst
@@ -55,6 +55,7 @@ more details.
coding-guidelines
arch-support
testing
+ pointer-formatting
You can also find learning materials for Rust in its section in
:doc:`../process/kernel-docs`.
diff --git a/Documentation/rust/pointer-formatting.rst b/Documentation/rust/pointer-formatting.rst
new file mode 100644
index 0000000000000..5928987f21bb0
--- /dev/null
+++ b/Documentation/rust/pointer-formatting.rst
@@ -0,0 +1,90 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Pointer Formatting in Rust
+===========================
+
+This document describes how to format kernel pointers safely in Rust code,
+corresponding to the C kernel's printk format specifiers ``%p`` and ``%px``.
+
+For general information about pointer formatting in the kernel, please refer to
+:doc:`../core-api/printk-formats`.
+
+Overview
+--------
+
+The Rust kernel provides two wrapper types for formatting kernel pointers:
+
+- **``HashedPtr``** → ``%p`` (hashed, default)
+- **``RawPtr``** → ``%px`` (raw address, debug only)
+
+When formatting raw pointers (``*const T`` or ``*mut T``) with ``{:p}``,
+they are automatically wrapped with ``HashedPtr``, providing safe default behavior.
+
+HashedPtr (%p)
+--------------
+
+Use ``HashedPtr`` for general kernel logging. Pointers are hashed before printing
+to prevent leaking information about the kernel memory layout. This is the default
+behavior when formatting raw pointers directly.
+
+**Example**::
+
+ use kernel::ptr::HashedPtr;
+
+ // Explicit use of HashedPtr
+ pr_info!("Pointer: {:p}\n", HashedPtr(ptr));
+
+ // Automatic hashing for raw pointers (default behavior)
+ pr_info!("Pointer: {:p}\n", ptr);
+
+RawPtr (%px)
+------------
+
+**Warning**: This exposes the real kernel address and should **only** be used
+for debugging purposes. Consider using ``HashedPtr`` instead for production code.
+
+**Example**::
+
+ use kernel::ptr::RawPtr;
+
+ pr_info!("Debug pointer: {:p}\n", RawPtr(ptr));
+
+Formatting Options
+------------------
+
+All pointer wrapper types support standard Rust formatting options including
+width, alignment, and padding characters. These options are preserved through
+the formatting system.
+
+The following examples demonstrate formatting options using ``RawPtr`` for
+predictable output. The same options work with ``HashedPtr``, though the exact
+output may vary due to pointer hashing::
+
+ use kernel::ptr::RawPtr;
+
+ // Basic formatting
+ pr_info!("Pointer: {:p}\n", RawPtr(ptr));
+
+ // Minimum width
+ pr_info!("Pointer: {:30p}\n", RawPtr(ptr));
+
+ // Right align with zero padding
+ pr_info!("Pointer: {:0>30p}\n", RawPtr(ptr));
+
+ // Left align with zero padding
+ pr_info!("Pointer: {:0<30p}\n", RawPtr(ptr));
+
+ // Center align with zero padding
+ pr_info!("Pointer: {:0^30p}\n", RawPtr(ptr));
+
+ // Right align with space padding (default)
+ pr_info!("Pointer: {:>30p}\n", RawPtr(ptr));
+
+ // Center align with custom padding character
+ pr_info!("Pointer: {:*^30p}\n", RawPtr(ptr));
+
+See Also
+--------
+
+- :doc:`../core-api/printk-formats` - General pointer formatting documentation
+- `rust/kernel/ptr.rs <srctree/rust/kernel/ptr.rs>`_ - Implementation
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
@ 2026-01-02 7:57 ` Dirk Behme
2026-01-02 11:06 ` Gary Guo
2026-01-02 11:13 ` Gary Guo
2026-01-02 12:17 ` Andy Shevchenko
2 siblings, 1 reply; 20+ messages in thread
From: Dirk Behme @ 2026-01-02 7:57 UTC (permalink / raw)
To: Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek,
Steven Rostedt, Timur Tabi, Danilo Krummrich, Benno Lossin,
Alice Ryhl
Cc: John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On 01/01/2026 09:16, Ke Sun wrote:
> Add two pointer wrapper types (HashedPtr, RawPtr) to rust/kernel/ptr.rs
> that correspond to C kernel's printk format specifiers %p and %px. These
> types provide type-safe pointer formatting that matches C kernel patterns.
>
> These wrapper types implement core::fmt::Pointer and delegate to the
> corresponding kernel formatting functions, enabling safe pointer
> formatting in Rust code that prevents information leaks about kernel
> memory layout.
>
> Users can explicitly use these types:
> pr_info!("{:p}\n", HashedPtr(ptr));
> pr_info!("{:p}\n", RawPtr(ptr));
>
> HashedPtr uses ptr_to_hashval() to hash pointers before printing,
> providing the default safe behavior for kernel pointers. RawPtr prints
> the raw address and should only be used for debugging purposes.
>
> Signed-off-by: Ke Sun <sunke@kylinos.cn>
> Suggested-by: Dirk Behme <dirk.behme@gmail.com>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
> rust/kernel/ptr.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 130 insertions(+), 3 deletions(-)
>
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index e3893ed04049d..77132eaaef73b 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -1,11 +1,22 @@
> // SPDX-License-Identifier: GPL-2.0
>
> //! Types and functions to work with pointers and addresses.
> +//!
> +//! This module provides wrapper types for formatting kernel pointers that correspond to the
> +//! C kernel's printk format specifiers `%p` and `%px`.
>
> -use core::mem::align_of;
> -use core::num::NonZero;
> +use core::{
> + fmt,
> + fmt::Pointer,
> + mem::align_of,
> + num::NonZero, //
> +};
>
> -use crate::build_assert;
> +use crate::{
> + bindings,
> + build_assert,
> + prelude::*, //
> +};
>
> /// Type representing an alignment, which is always a power of two.
> ///
> @@ -225,3 +236,119 @@ fn align_up(self, alignment: Alignment) -> Option<Self> {
> }
>
> impl_alignable_uint!(u8, u16, u32, u64, usize);
> +
> +/// Placeholder string used when pointer hashing is not ready yet.
> +const PTR_PLACEHOLDER: &str = if size_of::<*const c_void>() == 8 {
> + "(____ptrval____)"
> +} else {
> + "(ptrval)"
> +};
> +
> +/// Helper function to hash a pointer and format it.
> +///
> +/// Returns `Ok(())` if the hash was successfully computed and formatted,
> +/// or the placeholder string if hashing is not ready yet.
> +fn format_hashed_ptr(ptr: *const c_void, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + let mut hashval: crate::ffi::c_ulong = 0;
> + // SAFETY: We're calling the kernel's ptr_to_hashval function which handles
> + // hashing. This is safe as long as ptr is a valid pointer value.
> + let ret = unsafe { bindings::ptr_to_hashval(ptr, &mut hashval) };
> +
> + if ret != 0 {
> + // Hash not ready yet, print placeholder with formatting options applied
> + // Using `pad()` ensures width, alignment, and padding options are respected
> + return f.pad(PTR_PLACEHOLDER);
> + }
> +
> + // Successfully got hash value, format it using Pointer::fmt to preserve
> + // formatting options (width, alignment, padding, etc.)
> + Pointer::fmt(&(hashval as *const c_void), f)
> +}
> +
> +/// A pointer that will be hashed when printed (corresponds to `%p`).
> +///
> +/// This is the default behavior for kernel pointers - they are hashed to prevent
> +/// leaking information about the kernel memory layout.
> +///
> +/// # Example
> +///
> +/// ```
> +/// use kernel::{
> +/// prelude::fmt,
> +/// ptr::HashedPtr,
> +/// str::CString, //
> +/// };
> +///
> +/// let ptr = HashedPtr(0x12345678 as *const u8);
> +/// pr_info!("Hashed pointer: {:016p}\n", ptr);
> +///
> +/// // Width option test
> +/// let cstr = CString::try_from_fmt(fmt!("{:30p}", ptr))?;
> +/// let width_30 = cstr.to_str()?;
> +/// assert_eq!(width_30.len(), 30);
> +/// # Ok::<(), kernel::error::Error>(())
> +/// ```
> +#[repr(transparent)]
> +#[derive(Copy, Clone)]
> +pub struct HashedPtr<T>(pub *const T);
> +
> +impl<T> fmt::Pointer for HashedPtr<T> {
> + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + // Handle NULL pointers - print them directly
> + let ptr = self.0.cast::<c_void>();
> + if ptr.is_null() {
> + return Pointer::fmt(&ptr, f);
> + }
> +
> + format_hashed_ptr(ptr, f)
> + }
> +}
> +
> +/// A pointer that will be printed as its raw address (corresponds to `%px`).
> +///
> +/// **Warning**: This exposes the real kernel address and should only be used
> +/// for debugging purposes. Consider using [`HashedPtr`] instead for production code.
> +///
> +/// # Example
> +///
> +/// ```
> +/// use kernel::{
> +/// prelude::fmt,
> +/// ptr::RawPtr,
> +/// str::CString, //
> +/// };
> +///
> +/// let ptr = RawPtr(0x12345678 as *const u8);
> +///
> +/// // Basic formatting
> +/// let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
> +/// let formatted = cstr.to_str()?;
> +/// assert_eq!(formatted, "0x12345678");
> +///
> +/// // Right align with zero padding, width 30
> +/// let cstr = CString::try_from_fmt(fmt!("{:0>30p}", ptr))?;
> +/// let right_zero = cstr.to_str()?;
> +/// assert_eq!(right_zero, "000000000000000000000x12345678");
> +///
> +/// // Left align with zero padding, width 30
> +/// let cstr = CString::try_from_fmt(fmt!("{:0<30p}", ptr))?;
> +/// let left_zero = cstr.to_str()?;
> +/// assert_eq!(left_zero, "0x1234567800000000000000000000");
> +///
> +/// // Center align with zero padding, width 30
> +/// let cstr = CString::try_from_fmt(fmt!("{:0^30p}", ptr))?;
> +/// let center_zero = cstr.to_str()?;
> +/// assert_eq!(center_zero, "00000000000x123456780000000000");
> +/// # Ok::<(), kernel::error::Error>(())
> +/// ```
> +#[repr(transparent)]
> +#[derive(Copy, Clone)]
> +pub struct RawPtr<T>(pub *const T);
In the thread "[PATCH] gpu: nova-core: bitfield: use &mut self setters
instead of builder pattern" [1] Gary proposed to add `#[must_use]`.
Would that be an option here as well?
Thanks
Dirk
[1]
https://lore.kernel.org/rust-for-linux/20260101042851.08576bdb.gary@garyguo.net/
> +
> +impl<T> fmt::Pointer for RawPtr<T> {
> + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + // Directly format the raw address - no hashing or restriction.
> + // This corresponds to %px behavior.
> + Pointer::fmt(&self.0.cast::<c_void>(), f)
> + }
> +}
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-02 7:57 ` Dirk Behme
@ 2026-01-02 11:06 ` Gary Guo
0 siblings, 0 replies; 20+ messages in thread
From: Gary Guo @ 2026-01-02 11:06 UTC (permalink / raw)
To: Dirk Behme
Cc: Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek,
Steven Rostedt, Timur Tabi, Danilo Krummrich, Benno Lossin,
Alice Ryhl, John Ogness, Andy Shevchenko, Rasmus Villemoes,
Andrew Morton, Björn Roy Baron, Andreas Hindborg,
Trevor Gross, Tamir Duberstein, Ke Sun, rust-for-linux
On Fri, 2 Jan 2026 08:57:16 +0100
Dirk Behme <dirk.behme@de.bosch.com> wrote:
> On 01/01/2026 09:16, Ke Sun wrote:
> > Add two pointer wrapper types (HashedPtr, RawPtr) to rust/kernel/ptr.rs
> > that correspond to C kernel's printk format specifiers %p and %px. These
> > types provide type-safe pointer formatting that matches C kernel patterns.
> >
> > These wrapper types implement core::fmt::Pointer and delegate to the
> > corresponding kernel formatting functions, enabling safe pointer
> > formatting in Rust code that prevents information leaks about kernel
> > memory layout.
> >
> > Users can explicitly use these types:
> > pr_info!("{:p}\n", HashedPtr(ptr));
> > pr_info!("{:p}\n", RawPtr(ptr));
> >
> > HashedPtr uses ptr_to_hashval() to hash pointers before printing,
> > providing the default safe behavior for kernel pointers. RawPtr prints
> > the raw address and should only be used for debugging purposes.
> >
> > Signed-off-by: Ke Sun <sunke@kylinos.cn>
> > Suggested-by: Dirk Behme <dirk.behme@gmail.com>
> > Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > ---
> > rust/kernel/ptr.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 130 insertions(+), 3 deletions(-)
> >
> > diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> > index e3893ed04049d..77132eaaef73b 100644
> > --- a/rust/kernel/ptr.rs
> > +++ b/rust/kernel/ptr.rs
> > @@ -1,11 +1,22 @@
> > // SPDX-License-Identifier: GPL-2.0
> >
> > //! Types and functions to work with pointers and addresses.
> > +//!
> > +//! This module provides wrapper types for formatting kernel pointers that correspond to the
> > +//! C kernel's printk format specifiers `%p` and `%px`.
> >
> > -use core::mem::align_of;
> > -use core::num::NonZero;
> > +use core::{
> > + fmt,
> > + fmt::Pointer,
> > + mem::align_of,
> > + num::NonZero, //
> > +};
> >
> > -use crate::build_assert;
> > +use crate::{
> > + bindings,
> > + build_assert,
> > + prelude::*, //
> > +};
> >
> > /// Type representing an alignment, which is always a power of two.
> > ///
> > @@ -225,3 +236,119 @@ fn align_up(self, alignment: Alignment) -> Option<Self> {
> > }
> >
> > impl_alignable_uint!(u8, u16, u32, u64, usize);
> > +
> > +/// Placeholder string used when pointer hashing is not ready yet.
> > +const PTR_PLACEHOLDER: &str = if size_of::<*const c_void>() == 8 {
> > + "(____ptrval____)"
> > +} else {
> > + "(ptrval)"
> > +};
> > +
> > +/// Helper function to hash a pointer and format it.
> > +///
> > +/// Returns `Ok(())` if the hash was successfully computed and formatted,
> > +/// or the placeholder string if hashing is not ready yet.
> > +fn format_hashed_ptr(ptr: *const c_void, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> > + let mut hashval: crate::ffi::c_ulong = 0;
> > + // SAFETY: We're calling the kernel's ptr_to_hashval function which handles
> > + // hashing. This is safe as long as ptr is a valid pointer value.
> > + let ret = unsafe { bindings::ptr_to_hashval(ptr, &mut hashval) };
> > +
> > + if ret != 0 {
> > + // Hash not ready yet, print placeholder with formatting options applied
> > + // Using `pad()` ensures width, alignment, and padding options are respected
> > + return f.pad(PTR_PLACEHOLDER);
> > + }
> > +
> > + // Successfully got hash value, format it using Pointer::fmt to preserve
> > + // formatting options (width, alignment, padding, etc.)
> > + Pointer::fmt(&(hashval as *const c_void), f)
> > +}
> > +
> > +/// A pointer that will be hashed when printed (corresponds to `%p`).
> > +///
> > +/// This is the default behavior for kernel pointers - they are hashed to prevent
> > +/// leaking information about the kernel memory layout.
> > +///
> > +/// # Example
> > +///
> > +/// ```
> > +/// use kernel::{
> > +/// prelude::fmt,
> > +/// ptr::HashedPtr,
> > +/// str::CString, //
> > +/// };
> > +///
> > +/// let ptr = HashedPtr(0x12345678 as *const u8);
> > +/// pr_info!("Hashed pointer: {:016p}\n", ptr);
> > +///
> > +/// // Width option test
> > +/// let cstr = CString::try_from_fmt(fmt!("{:30p}", ptr))?;
> > +/// let width_30 = cstr.to_str()?;
> > +/// assert_eq!(width_30.len(), 30);
> > +/// # Ok::<(), kernel::error::Error>(())
> > +/// ```
> > +#[repr(transparent)]
> > +#[derive(Copy, Clone)]
> > +pub struct HashedPtr<T>(pub *const T);
> > +
> > +impl<T> fmt::Pointer for HashedPtr<T> {
> > + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> > + // Handle NULL pointers - print them directly
> > + let ptr = self.0.cast::<c_void>();
> > + if ptr.is_null() {
> > + return Pointer::fmt(&ptr, f);
> > + }
> > +
> > + format_hashed_ptr(ptr, f)
> > + }
> > +}
> > +
> > +/// A pointer that will be printed as its raw address (corresponds to `%px`).
> > +///
> > +/// **Warning**: This exposes the real kernel address and should only be used
> > +/// for debugging purposes. Consider using [`HashedPtr`] instead for production code.
> > +///
> > +/// # Example
> > +///
> > +/// ```
> > +/// use kernel::{
> > +/// prelude::fmt,
> > +/// ptr::RawPtr,
> > +/// str::CString, //
> > +/// };
> > +///
> > +/// let ptr = RawPtr(0x12345678 as *const u8);
> > +///
> > +/// // Basic formatting
> > +/// let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
> > +/// let formatted = cstr.to_str()?;
> > +/// assert_eq!(formatted, "0x12345678");
> > +///
> > +/// // Right align with zero padding, width 30
> > +/// let cstr = CString::try_from_fmt(fmt!("{:0>30p}", ptr))?;
> > +/// let right_zero = cstr.to_str()?;
> > +/// assert_eq!(right_zero, "000000000000000000000x12345678");
> > +///
> > +/// // Left align with zero padding, width 30
> > +/// let cstr = CString::try_from_fmt(fmt!("{:0<30p}", ptr))?;
> > +/// let left_zero = cstr.to_str()?;
> > +/// assert_eq!(left_zero, "0x1234567800000000000000000000");
> > +///
> > +/// // Center align with zero padding, width 30
> > +/// let cstr = CString::try_from_fmt(fmt!("{:0^30p}", ptr))?;
> > +/// let center_zero = cstr.to_str()?;
> > +/// assert_eq!(center_zero, "00000000000x123456780000000000");
> > +/// # Ok::<(), kernel::error::Error>(())
> > +/// ```
> > +#[repr(transparent)]
> > +#[derive(Copy, Clone)]
> > +pub struct RawPtr<T>(pub *const T);
>
>
> In the thread "[PATCH] gpu: nova-core: bitfield: use &mut self setters
> instead of builder pattern" [1] Gary proposed to add `#[must_use]`.
> Would that be an option here as well?
>
> Thanks
>
> Dirk
Hi Dirk,
I don't think that's necessary here. Adding `#[must_use]` on a type means
that any function returning it becomes automatically `#[must_use]`, but I
find it hard to find a case where misuse can happen without such
attributes, let alone I don't think people would return `RawPtr` from
function in the first place?
Best,
Gary
>
> [1]
> https://lore.kernel.org/rust-for-linux/20260101042851.08576bdb.gary@garyguo.net/
>
> > +
> > +impl<T> fmt::Pointer for RawPtr<T> {
> > + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> > + // Directly format the raw address - no hashing or restriction.
> > + // This corresponds to %px behavior.
> > + Pointer::fmt(&self.0.cast::<c_void>(), f)
> > + }
> > +}
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
2026-01-02 7:57 ` Dirk Behme
@ 2026-01-02 11:13 ` Gary Guo
2026-01-02 12:17 ` Andy Shevchenko
2 siblings, 0 replies; 20+ messages in thread
From: Gary Guo @ 2026-01-02 11:13 UTC (permalink / raw)
To: Ke Sun
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl,
John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Thu, 1 Jan 2026 16:16:02 +0800
Ke Sun <sunke@kylinos.cn> wrote:
> Add two pointer wrapper types (HashedPtr, RawPtr) to rust/kernel/ptr.rs
> that correspond to C kernel's printk format specifiers %p and %px. These
> types provide type-safe pointer formatting that matches C kernel patterns.
>
> These wrapper types implement core::fmt::Pointer and delegate to the
> corresponding kernel formatting functions, enabling safe pointer
> formatting in Rust code that prevents information leaks about kernel
> memory layout.
>
> Users can explicitly use these types:
> pr_info!("{:p}\n", HashedPtr(ptr));
> pr_info!("{:p}\n", RawPtr(ptr));
>
> HashedPtr uses ptr_to_hashval() to hash pointers before printing,
> providing the default safe behavior for kernel pointers. RawPtr prints
> the raw address and should only be used for debugging purposes.
>
> Signed-off-by: Ke Sun <sunke@kylinos.cn>
> Suggested-by: Dirk Behme <dirk.behme@gmail.com>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
> rust/kernel/ptr.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 130 insertions(+), 3 deletions(-)
>
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index e3893ed04049d..77132eaaef73b 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -1,11 +1,22 @@
> // SPDX-License-Identifier: GPL-2.0
>
> //! Types and functions to work with pointers and addresses.
> +//!
> +//! This module provides wrapper types for formatting kernel pointers that correspond to the
> +//! C kernel's printk format specifiers `%p` and `%px`.
>
> -use core::mem::align_of;
> -use core::num::NonZero;
> +use core::{
> + fmt,
> + fmt::Pointer,
> + mem::align_of,
> + num::NonZero, //
> +};
>
> -use crate::build_assert;
> +use crate::{
> + bindings,
> + build_assert,
> + prelude::*, //
> +};
>
> /// Type representing an alignment, which is always a power of two.
> ///
> @@ -225,3 +236,119 @@ fn align_up(self, alignment: Alignment) -> Option<Self> {
> }
>
> impl_alignable_uint!(u8, u16, u32, u64, usize);
> +
> +/// Placeholder string used when pointer hashing is not ready yet.
> +const PTR_PLACEHOLDER: &str = if size_of::<*const c_void>() == 8 {
> + "(____ptrval____)"
> +} else {
> + "(ptrval)"
> +};
> +
> +/// Helper function to hash a pointer and format it.
> +///
> +/// Returns `Ok(())` if the hash was successfully computed and formatted,
> +/// or the placeholder string if hashing is not ready yet.
> +fn format_hashed_ptr(ptr: *const c_void, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + let mut hashval: crate::ffi::c_ulong = 0;
> + // SAFETY: We're calling the kernel's ptr_to_hashval function which handles
> + // hashing. This is safe as long as ptr is a valid pointer value.
> + let ret = unsafe { bindings::ptr_to_hashval(ptr, &mut hashval) };
> +
> + if ret != 0 {
> + // Hash not ready yet, print placeholder with formatting options applied
> + // Using `pad()` ensures width, alignment, and padding options are respected
> + return f.pad(PTR_PLACEHOLDER);
> + }
> +
> + // Successfully got hash value, format it using Pointer::fmt to preserve
> + // formatting options (width, alignment, padding, etc.)
> + Pointer::fmt(&(hashval as *const c_void), f)
Can you use `core::ptr::without_provenance` here?
> +}
> +
> +#[repr(transparent)]
> +#[derive(Copy, Clone)]
> +pub struct HashedPtr<T>(pub *const T);
> +
> +impl<T> fmt::Pointer for HashedPtr<T> {
> + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + // Handle NULL pointers - print them directly
> + let ptr = self.0.cast::<c_void>();
> + if ptr.is_null() {
> + return Pointer::fmt(&ptr, f);
> + }
> +
> + format_hashed_ptr(ptr, f)
> + }
> +}
>
> ...
>
> +#[repr(transparent)]
> +#[derive(Copy, Clone)]
> +pub struct RawPtr<T>(pub *const T);
> +
> +impl<T> fmt::Pointer for RawPtr<T> {
> + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
> + // Directly format the raw address - no hashing or restriction.
> + // This corresponds to %px behavior.
> + Pointer::fmt(&self.0.cast::<c_void>(), f)
> + }
> +}
Given these types are only for printing (and not applicable to general
operation on pointers, I feel that these should go into `kerne::fmt` to
stay with other formatting specific utility.
Best,
Gary
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-01 8:16 ` [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr Ke Sun
@ 2026-01-02 11:17 ` Gary Guo
2026-01-02 17:39 ` Petr Mladek
1 sibling, 0 replies; 20+ messages in thread
From: Gary Guo @ 2026-01-02 11:17 UTC (permalink / raw)
To: Ke Sun
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl,
John Ogness, Andy Shevchenko, Rasmus Villemoes, Andrew Morton,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Thu, 1 Jan 2026 16:16:03 +0800
Ke Sun <sunke@kylinos.cn> wrote:
> Make raw pointers (*const T, *mut T) automatically use HashedPtr when
> formatted with {:p}, providing safe default behavior for kernel pointers.
>
> This allows users to format raw pointers directly:
> pr_info!("{:p}\n", ptr); // Automatically hashed
>
> While still allowing explicit use of wrapper types when needed:
> pr_info!("{:p}\n", RawPtr(ptr));
>
> Signed-off-by: Ke Sun <sunke@kylinos.cn>
> ---
> rust/kernel/fmt.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs
> index 84d634201d90a..8be185d522c01 100644
> --- a/rust/kernel/fmt.rs
> +++ b/rust/kernel/fmt.rs
> @@ -6,6 +6,11 @@
>
> pub use core::fmt::{Arguments, Debug, Error, Formatter, Result, Write};
>
> +use crate::ptr::{
> + HashedPtr,
> + RawPtr, //
> +};
> +
> /// Internal adapter used to route allow implementations of formatting traits for foreign types.
> ///
> /// It is inserted automatically by the [`fmt!`] macro and is not meant to be used directly.
> @@ -28,7 +33,64 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> }
>
> use core::fmt::{Binary, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex};
> -impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, Pointer, LowerExp, UpperExp);
> +impl_fmt_adapter_forward!(Debug, LowerHex, UpperHex, Octal, Binary, LowerExp, UpperExp);
> +
> +// Special handling for Pointer: default to HashedPtr for raw pointers.
> +// This overrides the default Pointer implementation for raw pointers to use hashing,
> +// which is the safe default behavior for kernel pointers.
> +impl<T> Pointer for Adapter<*const T> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(ptr) = self;
> + Pointer::fmt(&HashedPtr(*ptr), f)
> + }
> +}
> +
> +impl<T> Pointer for Adapter<*mut T> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(ptr) = self;
> + Pointer::fmt(&HashedPtr(*ptr), f)
> + }
> +}
> +
> +// Handle references to raw pointers (needed when pointers are passed by reference in macros).
> +impl<T> Pointer for Adapter<&*const T> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(ptr) = self;
> + Pointer::fmt(&HashedPtr(**ptr), f)
> + }
> +}
> +
> +impl<T> Pointer for Adapter<&*mut T> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(ptr) = self;
> + Pointer::fmt(&HashedPtr(**ptr), f)
> + }
> +}
> +
> +// For wrapper types that implement Pointer (like HashedPtr, RawPtr),
> +// forward to their implementation. This allows explicit wrapper types to use their
> +// own formatting logic instead of being converted to HashedPtr.
> +macro_rules! impl_pointer_adapter_forward {
> + ($($ty:ident),* $(,)?) => {
> + $(
> + impl<T> Pointer for Adapter<$ty<T>> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(t) = self;
> + Pointer::fmt(t, f)
> + }
> + }
> +
> + impl<T> Pointer for Adapter<&$ty<T>> {
> + fn fmt(&self, f: &mut Formatter<'_>) -> Result {
> + let Self(t) = self;
> + Pointer::fmt(*t, f)
> + }
> + }
> + )*
> + };
> +}
> +
> +impl_pointer_adapter_forward!(HashedPtr, RawPtr);
This implementation means that nobody can implement the `Pointer` trait
outside the kernel crate.
Should we do something similar to `Display` trait and have a kernel copy
so people can still have their custom `Pointer` implementation?
Best,
Gary
>
> /// A copy of [`core::fmt::Display`] that allows us to implement it for foreign types.
> ///
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use
2026-01-01 8:16 ` [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use Ke Sun
@ 2026-01-02 12:15 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-01-02 12:15 UTC (permalink / raw)
To: Ke Sun
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl,
John Ogness, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Thu, Jan 01, 2026 at 04:16:01PM +0800, Ke Sun wrote:
> Export ptr_to_hashval() with EXPORT_SYMBOL_NS_GPL using the "RUST_INTERNAL"
> namespace. This function is used to hash kernel pointers before printing
> them, preventing information leaks about kernel memory layout.
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
I haven't suggested this change. I suggested to make the export be
Rust specific.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
2026-01-02 7:57 ` Dirk Behme
2026-01-02 11:13 ` Gary Guo
@ 2026-01-02 12:17 ` Andy Shevchenko
2026-01-02 12:33 ` Danilo Krummrich
2 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-01-02 12:17 UTC (permalink / raw)
To: Ke Sun
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, Alice Ryhl,
John Ogness, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Thu, Jan 01, 2026 at 04:16:02PM +0800, Ke Sun wrote:
> Add two pointer wrapper types (HashedPtr, RawPtr) to rust/kernel/ptr.rs
> that correspond to C kernel's printk format specifiers %p and %px. These
> types provide type-safe pointer formatting that matches C kernel patterns.
>
> These wrapper types implement core::fmt::Pointer and delegate to the
> corresponding kernel formatting functions, enabling safe pointer
> formatting in Rust code that prevents information leaks about kernel
> memory layout.
>
> Users can explicitly use these types:
> pr_info!("{:p}\n", HashedPtr(ptr));
> pr_info!("{:p}\n", RawPtr(ptr));
>
> HashedPtr uses ptr_to_hashval() to hash pointers before printing,
> providing the default safe behavior for kernel pointers. RawPtr prints
> the raw address and should only be used for debugging purposes.
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Definitely wrong tag here. Please, do not apply random tags on behalf of
others. You must get it explicitly.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-02 12:17 ` Andy Shevchenko
@ 2026-01-02 12:33 ` Danilo Krummrich
2026-01-02 12:43 ` Ke Sun
0 siblings, 1 reply; 20+ messages in thread
From: Danilo Krummrich @ 2026-01-02 12:33 UTC (permalink / raw)
To: Ke Sun, Andy Shevchenko
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Petr Mladek, Steven Rostedt,
Timur Tabi, Benno Lossin, Alice Ryhl, John Ogness,
Rasmus Villemoes, Andrew Morton, Gary Guo, Björn Roy Baron,
Andreas Hindborg, Trevor Gross, Tamir Duberstein, Ke Sun,
rust-for-linux
On Fri Jan 2, 2026 at 1:17 PM CET, Andy Shevchenko wrote:
> On Thu, Jan 01, 2026 at 04:16:02PM +0800, Ke Sun wrote:
>> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> Definitely wrong tag here. Please, do not apply random tags on behalf of
> others. You must get it explicitly.
Ke, just to avoid any confusion, it also strongly depends on the situation.
There are tags that are commonly used without getting it explicitly;
'Reported-by:' for instance.
For the 'Suggested-by:' tag it depends, if the situation is 100% clear it is not
uncommon to just add the tag, but in general - but especially if in doubt - it
is usually better to ask.
It also sometimes happens that maintainers convert a "LGTM" or "I agree with
this patch.", etc. to an 'Acked-by:'. This sometimes happens with new
contributors, but in general 'Acked-by:' is (and should be) given explicitly.
For things like 'Suggested-by:' I also recommend to add a 'Link:' tag with the
source of the suggestion.
Please also have a look at [1], which explains which tags require permission.
I hope this helps!
- Danilo
[1] https://docs.kernel.org/process/submitting-patches.html#tagging-people-requires-permission
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting
2026-01-02 12:33 ` Danilo Krummrich
@ 2026-01-02 12:43 ` Ke Sun
0 siblings, 0 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-02 12:43 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Andy Shevchenko, Dirk Behme, Boqun Feng, Miguel Ojeda,
Petr Mladek, Steven Rostedt, Timur Tabi, Benno Lossin, Alice Ryhl,
John Ogness, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, rust-for-linux
Danilo Krummrich <dakr@kernel.org> 于2026年1月2日周五 20:34写道:
>
> On Fri Jan 2, 2026 at 1:17 PM CET, Andy Shevchenko wrote:
> > On Thu, Jan 01, 2026 at 04:16:02PM +0800, Ke Sun wrote:
> >> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
> > Definitely wrong tag here. Please, do not apply random tags on behalf of
> > others. You must get it explicitly.
>
> Ke, just to avoid any confusion, it also strongly depends on the situation.
>
> There are tags that are commonly used without getting it explicitly;
> 'Reported-by:' for instance.
>
> For the 'Suggested-by:' tag it depends, if the situation is 100% clear it is not
> uncommon to just add the tag, but in general - but especially if in doubt - it
> is usually better to ask.
>
> It also sometimes happens that maintainers convert a "LGTM" or "I agree with
> this patch.", etc. to an 'Acked-by:'. This sometimes happens with new
> contributors, but in general 'Acked-by:' is (and should be) given explicitly.
>
> For things like 'Suggested-by:' I also recommend to add a 'Link:' tag with the
> source of the suggestion.
>
> Please also have a look at [1], which explains which tags require permission.
Thank you, I'll read through these rules carefully.
>
> I hope this helps!
>
> - Danilo
>
> [1] https://docs.kernel.org/process/submitting-patches.html#tagging-people-requires-permission
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-01 8:16 ` [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr Ke Sun
2026-01-02 11:17 ` Gary Guo
@ 2026-01-02 17:39 ` Petr Mladek
2026-01-05 8:19 ` Alice Ryhl
1 sibling, 1 reply; 20+ messages in thread
From: Petr Mladek @ 2026-01-02 17:39 UTC (permalink / raw)
To: Ke Sun
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Steven Rostedt, Timur Tabi,
Danilo Krummrich, Benno Lossin, Alice Ryhl, John Ogness,
Andy Shevchenko, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Thu 2026-01-01 16:16:03, Ke Sun wrote:
> Make raw pointers (*const T, *mut T) automatically use HashedPtr when
> formatted with {:p}, providing safe default behavior for kernel pointers.
>
> This allows users to format raw pointers directly:
> pr_info!("{:p}\n", ptr); // Automatically hashed
It should check no_hash_pointers variable, see default_pointer() in
lib/vsprintf.c. See also "no_hash_pointers" and "hash_pointers=never"
kernel command line options.
Hashed pointers prevent leaking information but are not good for
debugging. The "no_hash_pointers" variable allows to print
raw pointers without changing the code.
I am not sure how this should be implemented in Rust. If you need
to keep HashPtr then it should become an implementation detail
and should not get exported. Nobody wants always hashed pointers.
I hope that we could find a better solution which would allow
to reduce the code duplication.
For example, I wonder what would be needed to allow calling
snprintf() from Rust code. The fn fmt() might call
it with "%p" format... It would make it easier to get
also other "%p?" formats.
It seems that something similar has been discussed at
https://lore.kernel.org/rust-for-linux/CALpAb9MoT20Ch4pe-oMz8kpqaZsvmgNwPk1XSC+faZi7huwQKg@mail.gmail.com/
And it was said that it would need bigger changes.
Maybe, we could create C wrappers which would allow to call
snprintf() with some specific format, e.g.
int scnprintf_p(char *buf, int size, const void *p)
{
return scnprintf(buf, size, "%p", p);
}
EXPORT_SYMBOL_NS_GPL(scnprintf_p, "RUST_INTERNAL");
And use the same approach for any other %p? format, e.g. for %pU:
int scnprintf_pU(char *buf, int size, const u8 *addr)
{
return scnprintf(buf, size, "%pU", addr);
}
EXPORT_SYMBOL_NS_GPL(scnprintf_pU, "RUST_INTERNAL");
Best Regards,
Petr
PS: I suggest to wait longer before sending a new version. It would
allow to get feedback from more people who might see it from
different angles.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-02 17:39 ` Petr Mladek
@ 2026-01-05 8:19 ` Alice Ryhl
2026-01-06 3:06 ` Ke Sun
2026-01-06 16:45 ` Petr Mladek
0 siblings, 2 replies; 20+ messages in thread
From: Alice Ryhl @ 2026-01-05 8:19 UTC (permalink / raw)
To: Petr Mladek
Cc: Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, John Ogness,
Andy Shevchenko, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Fri, Jan 02, 2026 at 06:39:34PM +0100, Petr Mladek wrote:
> On Thu 2026-01-01 16:16:03, Ke Sun wrote:
> > Make raw pointers (*const T, *mut T) automatically use HashedPtr when
> > formatted with {:p}, providing safe default behavior for kernel pointers.
> >
> > This allows users to format raw pointers directly:
> > pr_info!("{:p}\n", ptr); // Automatically hashed
>
> It should check no_hash_pointers variable, see default_pointer() in
> lib/vsprintf.c. See also "no_hash_pointers" and "hash_pointers=never"
> kernel command line options.
>
> Hashed pointers prevent leaking information but are not good for
> debugging. The "no_hash_pointers" variable allows to print
> raw pointers without changing the code.
>
> I am not sure how this should be implemented in Rust. If you need
> to keep HashPtr then it should become an implementation detail
> and should not get exported. Nobody wants always hashed pointers.
>
> I hope that we could find a better solution which would allow
> to reduce the code duplication.
>
> For example, I wonder what would be needed to allow calling
> snprintf() from Rust code. The fn fmt() might call
> it with "%p" format... It would make it easier to get
> also other "%p?" formats.
>
> It seems that something similar has been discussed at
> https://lore.kernel.org/rust-for-linux/CALpAb9MoT20Ch4pe-oMz8kpqaZsvmgNwPk1XSC+faZi7huwQKg@mail.gmail.com/
> And it was said that it would need bigger changes.
>
> Maybe, we could create C wrappers which would allow to call
> snprintf() with some specific format, e.g.
>
> int scnprintf_p(char *buf, int size, const void *p)
> {
> return scnprintf(buf, size, "%p", p);
> }
> EXPORT_SYMBOL_NS_GPL(scnprintf_p, "RUST_INTERNAL");
>
> And use the same approach for any other %p? format, e.g. for %pU:
>
> int scnprintf_pU(char *buf, int size, const u8 *addr)
> {
> return scnprintf(buf, size, "%pU", addr);
> }
> EXPORT_SYMBOL_NS_GPL(scnprintf_pU, "RUST_INTERNAL");
>
> Best Regards,
> Petr
>
> PS: I suggest to wait longer before sending a new version. It would
> allow to get feedback from more people who might see it from
> different angles.
I think there are two approaches we could take:
1. Have the C side provide a method that returns the correct integer
address to print.
2. Have the C side provide a method that returns the correct string
to print.
In general, for cases where the output is an integer formatted in some
standard way (e.g. hex), I think the first option is stronger because
the Rust formatting machinery lets you specify different modifiers such
as "prefix with zeroes or spaces" or "how many zeroes/spaces to prefix
with" or "hex uppercase or lowercase" or "hex vs octal vs base10" etc.
By having the C side pass an integer back to Rust, these modifiers are
taken into account automatically.
Now, just using scnprintf to write the resulting string to a buffer and
passing that string into the Rust formatting machinery is also an option
of course. Especially for modifiers such as %pF that prints something
like versatile_init+0x0/0x110.
Alice
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-05 8:19 ` Alice Ryhl
@ 2026-01-06 3:06 ` Ke Sun
2026-01-06 16:45 ` Petr Mladek
1 sibling, 0 replies; 20+ messages in thread
From: Ke Sun @ 2026-01-06 3:06 UTC (permalink / raw)
To: Alice Ryhl, Petr Mladek
Cc: Dirk Behme, Boqun Feng, Miguel Ojeda, Steven Rostedt, Timur Tabi,
Danilo Krummrich, Benno Lossin, John Ogness, Andy Shevchenko,
Rasmus Villemoes, Andrew Morton, Gary Guo, Björn Roy Baron,
Andreas Hindborg, Trevor Gross, Tamir Duberstein, rust-for-linux
On 1/5/26 16:19, Alice Ryhl wrote:
> On Fri, Jan 02, 2026 at 06:39:34PM +0100, Petr Mladek wrote:
>> On Thu 2026-01-01 16:16:03, Ke Sun wrote:
>>> Make raw pointers (*const T, *mut T) automatically use HashedPtr when
>>> formatted with {:p}, providing safe default behavior for kernel pointers.
>>>
>>> This allows users to format raw pointers directly:
>>> pr_info!("{:p}\n", ptr); // Automatically hashed
>> It should check no_hash_pointers variable, see default_pointer() in
>> lib/vsprintf.c. See also "no_hash_pointers" and "hash_pointers=never"
>> kernel command line options.
>>
>> Hashed pointers prevent leaking information but are not good for
>> debugging. The "no_hash_pointers" variable allows to print
>> raw pointers without changing the code.
>>
>> I am not sure how this should be implemented in Rust. If you need
>> to keep HashPtr then it should become an implementation detail
>> and should not get exported. Nobody wants always hashed pointers.
>>
>> I hope that we could find a better solution which would allow
>> to reduce the code duplication.
>>
>> For example, I wonder what would be needed to allow calling
>> snprintf() from Rust code. The fn fmt() might call
>> it with "%p" format... It would make it easier to get
>> also other "%p?" formats.
>>
>> It seems that something similar has been discussed at
>> https://lore.kernel.org/rust-for-linux/CALpAb9MoT20Ch4pe-oMz8kpqaZsvmgNwPk1XSC+faZi7huwQKg@mail.gmail.com/
>> And it was said that it would need bigger changes.
>>
>> Maybe, we could create C wrappers which would allow to call
>> snprintf() with some specific format, e.g.
>>
>> int scnprintf_p(char *buf, int size, const void *p)
>> {
>> return scnprintf(buf, size, "%p", p);
>> }
>> EXPORT_SYMBOL_NS_GPL(scnprintf_p, "RUST_INTERNAL");
>>
>> And use the same approach for any other %p? format, e.g. for %pU:
>>
>> int scnprintf_pU(char *buf, int size, const u8 *addr)
>> {
>> return scnprintf(buf, size, "%pU", addr);
>> }
>> EXPORT_SYMBOL_NS_GPL(scnprintf_pU, "RUST_INTERNAL");
>>
>> Best Regards,
>> Petr
>>
>> PS: I suggest to wait longer before sending a new version. It would
>> allow to get feedback from more people who might see it from
>> different angles.
> I think there are two approaches we could take:
>
> 1. Have the C side provide a method that returns the correct integer
> address to print.
> 2. Have the C side provide a method that returns the correct string
> to print.
>
> In general, for cases where the output is an integer formatted in some
> standard way (e.g. hex), I think the first option is stronger because
> the Rust formatting machinery lets you specify different modifiers such
> as "prefix with zeroes or spaces" or "how many zeroes/spaces to prefix
> with" or "hex uppercase or lowercase" or "hex vs octal vs base10" etc.
> By having the C side pass an integer back to Rust, these modifiers are
> taken into account automatically.
>
> Now, just using scnprintf to write the resulting string to a buffer and
> passing that string into the Rust formatting machinery is also an option
> of course. Especially for modifiers such as %pF that prints something
> like versatile_init+0x0/0x110.
Thank you for the suggestion. I'm exploring this approach.
I previously implemented a version using snprintf, but found that C's %p
format specifier
doesn't integrate well with Rust's formatting infrastructure.
Best Regards,
Ke Sun
> Alice
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-05 8:19 ` Alice Ryhl
2026-01-06 3:06 ` Ke Sun
@ 2026-01-06 16:45 ` Petr Mladek
2026-01-06 17:18 ` Alice Ryhl
1 sibling, 1 reply; 20+ messages in thread
From: Petr Mladek @ 2026-01-06 16:45 UTC (permalink / raw)
To: Alice Ryhl
Cc: Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, John Ogness,
Andy Shevchenko, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Mon 2026-01-05 08:19:49, Alice Ryhl wrote:
> On Fri, Jan 02, 2026 at 06:39:34PM +0100, Petr Mladek wrote:
> > On Thu 2026-01-01 16:16:03, Ke Sun wrote:
> > > Make raw pointers (*const T, *mut T) automatically use HashedPtr when
> > > formatted with {:p}, providing safe default behavior for kernel pointers.
> > >
> > > This allows users to format raw pointers directly:
> > > pr_info!("{:p}\n", ptr); // Automatically hashed
> >
> > It should check no_hash_pointers variable, see default_pointer() in
> > lib/vsprintf.c. See also "no_hash_pointers" and "hash_pointers=never"
> > kernel command line options.
> >
> > Hashed pointers prevent leaking information but are not good for
> > debugging. The "no_hash_pointers" variable allows to print
> > raw pointers without changing the code.
> >
> > I am not sure how this should be implemented in Rust. If you need
> > to keep HashPtr then it should become an implementation detail
> > and should not get exported. Nobody wants always hashed pointers.
> >
> > I hope that we could find a better solution which would allow
> > to reduce the code duplication.
> >
> > For example, I wonder what would be needed to allow calling
> > snprintf() from Rust code. The fn fmt() might call
> > it with "%p" format... It would make it easier to get
> > also other "%p?" formats.
> >
> > It seems that something similar has been discussed at
> > https://lore.kernel.org/rust-for-linux/CALpAb9MoT20Ch4pe-oMz8kpqaZsvmgNwPk1XSC+faZi7huwQKg@mail.gmail.com/
> > And it was said that it would need bigger changes.
> >
> > Maybe, we could create C wrappers which would allow to call
> > snprintf() with some specific format, e.g.
> >
> > int scnprintf_p(char *buf, int size, const void *p)
> > {
> > return scnprintf(buf, size, "%p", p);
> > }
> > EXPORT_SYMBOL_NS_GPL(scnprintf_p, "RUST_INTERNAL");
> >
> > And use the same approach for any other %p? format, e.g. for %pU:
> >
> > int scnprintf_pU(char *buf, int size, const u8 *addr)
> > {
> > return scnprintf(buf, size, "%pU", addr);
> > }
> > EXPORT_SYMBOL_NS_GPL(scnprintf_pU, "RUST_INTERNAL");
> >
> > Best Regards,
> > Petr
> >
> > PS: I suggest to wait longer before sending a new version. It would
> > allow to get feedback from more people who might see it from
> > different angles.
>
> I think there are two approaches we could take:
>
> 1. Have the C side provide a method that returns the correct integer
> address to print.
> 2. Have the C side provide a method that returns the correct string
> to print.
>
> In general, for cases where the output is an integer formatted in some
> standard way (e.g. hex), I think the first option is stronger because
> the Rust formatting machinery lets you specify different modifiers such
> as "prefix with zeroes or spaces" or "how many zeroes/spaces to prefix
> with" or "hex uppercase or lowercase" or "hex vs octal vs base10" etc.
> By having the C side pass an integer back to Rust, these modifiers are
> taken into account automatically.
Just to be sure that we are talking about the same things.
1. C Code
According to "man 3 printf", the C printf() allows to define the
format using the syntax:
%[argument$][flags][width][.precision][length modifier]conversion
, where for example:
printf("%016llx\n", val);
would printf zero padded hex value with a field width 16.
2. Rust code
According to https://doc.rust-lang.org/std/fmt/ , Rust allows
the define the format using the syntax:
format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
It is actually more complicated. There are also traits, ...
Now, I think that we are talking about three categories:
a) Number and string formatting, in C, for example, %d, %x, %u, %s
b) Classic pointer value formatting, in C, %p
c) Kernel specific pointer formatting, in C, for example, %pK, %pe, %pS, %pI6
My view:
Ad a) IMHO, we do not need anything special for the number and string
formatting. Rust code should use the native Rust formatting.
Ad b) %p is handled quite special way in kernel:
+ hashed by default
+ hashing disabled with "no_hash_pointers"
+ special hashing of early code when "debug_boot_weak_hash"
+ no hashing for IS_ERR_OR_NULL(ptr) values
+ fallback to "(____ptrval____)" : "(ptrval)" before
random numbers are initialized enough
I would try to avoid as much duplicity as possible.
IMHO, the current approach duplicates too much.
This is why I suggested to add a wrapper for
scnprintf(buf, size, "%p", ptr) and call it from Rust.
By other words, I think that this is close to the c) category
with all the kernel-specific pointer format modifiers. They
print the data at the pointer address a special way.
Ad c) I am not sure how to handle all the kernel-specific %p?
modifiers in Rust.
I guess that it will be done by implementing "fn fmt"
in a crate for the related pointer type. Or something like
this.
Note that I have almost zero knowledge about Rust at the
moment :-/
> Now, just using scnprintf to write the resulting string to a buffer and
> passing that string into the Rust formatting machinery is also an option
> of course. Especially for modifiers such as %pF that prints something
> like versatile_init+0x0/0x110.
Yeah, I think that this might be a good option how to export
the kernel-specific handling of the various %p?, formats,
including plain %p, on the C side.
Best Regards,
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-06 16:45 ` Petr Mladek
@ 2026-01-06 17:18 ` Alice Ryhl
2026-01-06 21:00 ` Andy Shevchenko
0 siblings, 1 reply; 20+ messages in thread
From: Alice Ryhl @ 2026-01-06 17:18 UTC (permalink / raw)
To: Petr Mladek
Cc: Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda, Steven Rostedt,
Timur Tabi, Danilo Krummrich, Benno Lossin, John Ogness,
Andy Shevchenko, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Tue, Jan 06, 2026 at 05:45:37PM +0100, Petr Mladek wrote:
> On Mon 2026-01-05 08:19:49, Alice Ryhl wrote:
> > On Fri, Jan 02, 2026 at 06:39:34PM +0100, Petr Mladek wrote:
> > > On Thu 2026-01-01 16:16:03, Ke Sun wrote:
> > > > Make raw pointers (*const T, *mut T) automatically use HashedPtr when
> > > > formatted with {:p}, providing safe default behavior for kernel pointers.
> > > >
> > > > This allows users to format raw pointers directly:
> > > > pr_info!("{:p}\n", ptr); // Automatically hashed
> > >
> > > It should check no_hash_pointers variable, see default_pointer() in
> > > lib/vsprintf.c. See also "no_hash_pointers" and "hash_pointers=never"
> > > kernel command line options.
> > >
> > > Hashed pointers prevent leaking information but are not good for
> > > debugging. The "no_hash_pointers" variable allows to print
> > > raw pointers without changing the code.
> > >
> > > I am not sure how this should be implemented in Rust. If you need
> > > to keep HashPtr then it should become an implementation detail
> > > and should not get exported. Nobody wants always hashed pointers.
> > >
> > > I hope that we could find a better solution which would allow
> > > to reduce the code duplication.
> > >
> > > For example, I wonder what would be needed to allow calling
> > > snprintf() from Rust code. The fn fmt() might call
> > > it with "%p" format... It would make it easier to get
> > > also other "%p?" formats.
> > >
> > > It seems that something similar has been discussed at
> > > https://lore.kernel.org/rust-for-linux/CALpAb9MoT20Ch4pe-oMz8kpqaZsvmgNwPk1XSC+faZi7huwQKg@mail.gmail.com/
> > > And it was said that it would need bigger changes.
> > >
> > > Maybe, we could create C wrappers which would allow to call
> > > snprintf() with some specific format, e.g.
> > >
> > > int scnprintf_p(char *buf, int size, const void *p)
> > > {
> > > return scnprintf(buf, size, "%p", p);
> > > }
> > > EXPORT_SYMBOL_NS_GPL(scnprintf_p, "RUST_INTERNAL");
> > >
> > > And use the same approach for any other %p? format, e.g. for %pU:
> > >
> > > int scnprintf_pU(char *buf, int size, const u8 *addr)
> > > {
> > > return scnprintf(buf, size, "%pU", addr);
> > > }
> > > EXPORT_SYMBOL_NS_GPL(scnprintf_pU, "RUST_INTERNAL");
> > >
> > > Best Regards,
> > > Petr
> > >
> > > PS: I suggest to wait longer before sending a new version. It would
> > > allow to get feedback from more people who might see it from
> > > different angles.
> >
> > I think there are two approaches we could take:
> >
> > 1. Have the C side provide a method that returns the correct integer
> > address to print.
> > 2. Have the C side provide a method that returns the correct string
> > to print.
> >
> > In general, for cases where the output is an integer formatted in some
> > standard way (e.g. hex), I think the first option is stronger because
> > the Rust formatting machinery lets you specify different modifiers such
> > as "prefix with zeroes or spaces" or "how many zeroes/spaces to prefix
> > with" or "hex uppercase or lowercase" or "hex vs octal vs base10" etc.
> > By having the C side pass an integer back to Rust, these modifiers are
> > taken into account automatically.
>
> Just to be sure that we are talking about the same things.
>
> 1. C Code
>
> According to "man 3 printf", the C printf() allows to define the
> format using the syntax:
>
> %[argument$][flags][width][.precision][length modifier]conversion
>
> , where for example:
>
> printf("%016llx\n", val);
>
> would printf zero padded hex value with a field width 16.
>
>
> 2. Rust code
>
> According to https://doc.rust-lang.org/std/fmt/ , Rust allows
> the define the format using the syntax:
>
> format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
>
> It is actually more complicated. There are also traits, ...
>
>
> Now, I think that we are talking about three categories:
>
> a) Number and string formatting, in C, for example, %d, %x, %u, %s
> b) Classic pointer value formatting, in C, %p
> c) Kernel specific pointer formatting, in C, for example, %pK, %pe, %pS, %pI6
>
>
> My view:
>
> Ad a) IMHO, we do not need anything special for the number and string
> formatting. Rust code should use the native Rust formatting.
>
> Ad b) %p is handled quite special way in kernel:
>
> + hashed by default
> + hashing disabled with "no_hash_pointers"
> + special hashing of early code when "debug_boot_weak_hash"
> + no hashing for IS_ERR_OR_NULL(ptr) values
> + fallback to "(____ptrval____)" : "(ptrval)" before
> random numbers are initialized enough
>
> I would try to avoid as much duplicity as possible.
> IMHO, the current approach duplicates too much.
>
> This is why I suggested to add a wrapper for
> scnprintf(buf, size, "%p", ptr) and call it from Rust.
>
> By other words, I think that this is close to the c) category
> with all the kernel-specific pointer format modifiers. They
> print the data at the pointer address a special way.
If I write this code in normal Rust:
let ptr = &3 as *const i32;
println!("{:?}", ptr);
println!("{:017?}", ptr);
println!("{:17?}", ptr);
it prints:
0x602ae0ec95d8
0x000602ae0ec95d8
0x602ae0ec95d8
If we implement {:?} on a raw pointer type (and {:p} on reference type)
to use scnprintf with a stack buffer for the string representation, then
we lose this flexibility. (Or we need additional effort to pass through
the various ways you can configure it to scnprintf.)
> Ad c) I am not sure how to handle all the kernel-specific %p?
> modifiers in Rust.
>
> I guess that it will be done by implementing "fn fmt"
> in a crate for the related pointer type. Or something like
> this.
>
> Note that I have almost zero knowledge about Rust at the
> moment :-/
I mean, if we take the Mac address example, you would just have a Mac
address type, and when you print it, you get a Mac address. So I'm not
worried about that.
As for %pa and %pad we do not need special logic. The Rust formatting
machinery does not require specifying the type being printed in the fmt
string, so it doesn't matter if the integer is sometimes u32 and
sometimes u64. It will work in both cases.
Alice
> > Now, just using scnprintf to write the resulting string to a buffer and
> > passing that string into the Rust formatting machinery is also an option
> > of course. Especially for modifiers such as %pF that prints something
> > like versatile_init+0x0/0x110.
>
> Yeah, I think that this might be a good option how to export
> the kernel-specific handling of the various %p?, formats,
> including plain %p, on the C side.
>
> Best Regards,
> Petr
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-06 17:18 ` Alice Ryhl
@ 2026-01-06 21:00 ` Andy Shevchenko
2026-01-06 21:06 ` Alice Ryhl
0 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-01-06 21:00 UTC (permalink / raw)
To: Alice Ryhl
Cc: Petr Mladek, Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda,
Steven Rostedt, Timur Tabi, Danilo Krummrich, Benno Lossin,
John Ogness, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Tue, Jan 06, 2026 at 05:18:41PM +0000, Alice Ryhl wrote:
> On Tue, Jan 06, 2026 at 05:45:37PM +0100, Petr Mladek wrote:
> > On Mon 2026-01-05 08:19:49, Alice Ryhl wrote:
...
> If I write this code in normal Rust:
>
> let ptr = &3 as *const i32;
> println!("{:?}", ptr);
> println!("{:017?}", ptr);
> println!("{:17?}", ptr);
>
> it prints:
>
> 0x602ae0ec95d8
> 0x000602ae0ec95d8
> 0x602ae0ec95d8
>
> If we implement {:?} on a raw pointer type (and {:p} on reference type)
> to use scnprintf with a stack buffer for the string representation, then
> we lose this flexibility. (Or we need additional effort to pass through
> the various ways you can configure it to scnprintf.)
I think the field width or variations make a little sense on pointers. AFAIR
printf() in kernel ignores field width and padding modifications to a pointer.
Only size of the end buffer may cut the string in the middle.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr
2026-01-06 21:00 ` Andy Shevchenko
@ 2026-01-06 21:06 ` Alice Ryhl
0 siblings, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2026-01-06 21:06 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Petr Mladek, Ke Sun, Dirk Behme, Boqun Feng, Miguel Ojeda,
Steven Rostedt, Timur Tabi, Danilo Krummrich, Benno Lossin,
John Ogness, Rasmus Villemoes, Andrew Morton, Gary Guo,
Björn Roy Baron, Andreas Hindborg, Trevor Gross,
Tamir Duberstein, Ke Sun, rust-for-linux
On Tue, Jan 6, 2026 at 10:00 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>
> On Tue, Jan 06, 2026 at 05:18:41PM +0000, Alice Ryhl wrote:
> > On Tue, Jan 06, 2026 at 05:45:37PM +0100, Petr Mladek wrote:
> > > On Mon 2026-01-05 08:19:49, Alice Ryhl wrote:
>
> ...
>
> > If I write this code in normal Rust:
> >
> > let ptr = &3 as *const i32;
> > println!("{:?}", ptr);
> > println!("{:017?}", ptr);
> > println!("{:17?}", ptr);
> >
> > it prints:
> >
> > 0x602ae0ec95d8
> > 0x000602ae0ec95d8
> > 0x602ae0ec95d8
> >
> > If we implement {:?} on a raw pointer type (and {:p} on reference type)
> > to use scnprintf with a stack buffer for the string representation, then
> > we lose this flexibility. (Or we need additional effort to pass through
> > the various ways you can configure it to scnprintf.)
>
> I think the field width or variations make a little sense on pointers. AFAIR
> printf() in kernel ignores field width and padding modifications to a pointer.
> Only size of the end buffer may cut the string in the middle.
I think that's a fair take, and I'm ok with the decision that Rust's
%p equivalent does not support customizing the width and similar.
In that case, we may implement `fn fmt` for pointer types by:
1. Creating a buffer on the stack large enough for a hex-formatted pointer.
2. Formatting the pointer with scnprintf or similar.
3. Passing the resulting string to the Rust machinery.
Alice
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-01-06 21:06 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-01 8:16 [PATCH v8 0/4] rust: Add safe pointer formatting support Ke Sun
2026-01-01 8:16 ` [PATCH v8 1/4] lib/vsprintf: Export ptr_to_hashval() for Rust kernel crate use Ke Sun
2026-01-02 12:15 ` Andy Shevchenko
2026-01-01 8:16 ` [PATCH v8 2/4] rust: kernel: Add pointer wrapper types for safe pointer formatting Ke Sun
2026-01-02 7:57 ` Dirk Behme
2026-01-02 11:06 ` Gary Guo
2026-01-02 11:13 ` Gary Guo
2026-01-02 12:17 ` Andy Shevchenko
2026-01-02 12:33 ` Danilo Krummrich
2026-01-02 12:43 ` Ke Sun
2026-01-01 8:16 ` [PATCH v8 3/4] rust: fmt: Default raw pointer formatting to HashedPtr Ke Sun
2026-01-02 11:17 ` Gary Guo
2026-01-02 17:39 ` Petr Mladek
2026-01-05 8:19 ` Alice Ryhl
2026-01-06 3:06 ` Ke Sun
2026-01-06 16:45 ` Petr Mladek
2026-01-06 17:18 ` Alice Ryhl
2026-01-06 21:00 ` Andy Shevchenko
2026-01-06 21:06 ` Alice Ryhl
2026-01-01 8:16 ` [PATCH v8 4/4] docs: rust: Add pointer formatting documentation Ke Sun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox