[PATCH] rust: dma: update safety comments for volatile memory access

Andreas Hindborg posted 1 patch 1 week ago
rust/kernel/dma.rs | 25 +++++++++----------------
1 file changed, 9 insertions(+), 16 deletions(-)
[PATCH] rust: dma: update safety comments for volatile memory access
Posted by Andreas Hindborg 1 week ago
At the time `CoherentAllocation::read_field` and
`CoherentAllocation::write_field` was merged, `ptr::{read,write}_volatile`
was under specified. The documentation for these functions have been
updated and we can now formulate a proper safety comment for the calls.

Update safety comments in `CoherentAllocation::{read,write}_field`.

Link: https://doc.rust-lang.org/stable/core/ptr/fn.read_volatile.html
Link: https://doc.rust-lang.org/stable/core/ptr/fn.write_volatile.html
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
 rust/kernel/dma.rs | 25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index acc65b1e0f245..0b55671a94faf 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -593,14 +593,12 @@ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
     pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
         // SAFETY:
         // - By the safety requirements field is valid.
-        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
-        // a special exception with the following notes in place. When dealing with a potential
-        // race from a hardware or code outside kernel (e.g. user-space program), we need that
-        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
-        // rationale behind is that it should generate the same code as READ_ONCE() which the
-        // kernel already relies on to avoid UB on data races. Note that the usage of
-        // read_volatile() is limited to this particular case, it cannot be used to prevent
-        // the UB caused by racing between two kernel functions nor do they provide atomicity.
+        // - `field` points to memory outside any Rust allocation.
+        // - As `field` points to readable memory:
+        //   - Reading `field` will not trap.
+        //   - Reading `field` will not change any memory inside a Rust allocation.
+        // - As `F: FromBytes` any bit pattern is valid for `F` and the read
+        //   will produce a properly initialized F.
         unsafe { field.read_volatile() }
     }
 
@@ -616,14 +614,9 @@ pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
     pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
         // SAFETY:
         // - By the safety requirements field is valid.
-        // - Using write_volatile() here is not sound as per the usual rules, the usage here is
-        // a special exception with the following notes in place. When dealing with a potential
-        // race from a hardware or code outside kernel (e.g. user-space program), we need that
-        // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
-        // rationale behind is that it should generate the same code as WRITE_ONCE() which the
-        // kernel already relies on to avoid UB on data races. Note that the usage of
-        // write_volatile() is limited to this particular case, it cannot be used to prevent
-        // the UB caused by racing between two kernel functions nor do they provide atomicity.
+        // - As `field` points to readable memory:
+        //   - Reading `field` will not trap.
+        //   - Reading `field` will not change any memory inside a Rust allocation.
         unsafe { field.write_volatile(val) }
     }
 }

---
base-commit: 63804fed149a6750ffd28610c5c1c98cce6bd377
change-id: 20260130-dma-doc-update-a8a0548045e2

Best regards,
-- 
Andreas Hindborg <a.hindborg@kernel.org>
Re: [PATCH] rust: dma: update safety comments for volatile memory access
Posted by Gary Guo 1 week ago
On Fri Jan 30, 2026 at 2:59 PM GMT, Andreas Hindborg wrote:
> At the time `CoherentAllocation::read_field` and
> `CoherentAllocation::write_field` was merged, `ptr::{read,write}_volatile`
> was under specified. The documentation for these functions have been
> updated and we can now formulate a proper safety comment for the calls.
>
> Update safety comments in `CoherentAllocation::{read,write}_field`.
>
> Link: https://doc.rust-lang.org/stable/core/ptr/fn.read_volatile.html
> Link: https://doc.rust-lang.org/stable/core/ptr/fn.write_volatile.html
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
> ---
>  rust/kernel/dma.rs | 25 +++++++++----------------
>  1 file changed, 9 insertions(+), 16 deletions(-)
>
> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> index acc65b1e0f245..0b55671a94faf 100644
> --- a/rust/kernel/dma.rs
> +++ b/rust/kernel/dma.rs
> @@ -593,14 +593,12 @@ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
>      pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
>          // SAFETY:
>          // - By the safety requirements field is valid.
> -        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
> -        // a special exception with the following notes in place. When dealing with a potential
> -        // race from a hardware or code outside kernel (e.g. user-space program), we need that
> -        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
> -        // rationale behind is that it should generate the same code as READ_ONCE() which the
> -        // kernel already relies on to avoid UB on data races. Note that the usage of
> -        // read_volatile() is limited to this particular case, it cannot be used to prevent
> -        // the UB caused by racing between two kernel functions nor do they provide atomicity.
> +        // - `field` points to memory outside any Rust allocation.

Hmm, this isn't actually correct, as the memory behind `CoherentAllocation`
isn't MMIO (they're just also accessible by device). We provide `as_slice()`
which exposes these memory directly to the Rust memory model.

Best,
Gary

> +        // - As `field` points to readable memory:
> +        //   - Reading `field` will not trap.
> +        //   - Reading `field` will not change any memory inside a Rust allocation.
> +        // - As `F: FromBytes` any bit pattern is valid for `F` and the read
> +        //   will produce a properly initialized F.
>          unsafe { field.read_volatile() }
>      }
>  
> @@ -616,14 +614,9 @@ pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
>      pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
>          // SAFETY:
>          // - By the safety requirements field is valid.
> -        // - Using write_volatile() here is not sound as per the usual rules, the usage here is
> -        // a special exception with the following notes in place. When dealing with a potential
> -        // race from a hardware or code outside kernel (e.g. user-space program), we need that
> -        // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
> -        // rationale behind is that it should generate the same code as WRITE_ONCE() which the
> -        // kernel already relies on to avoid UB on data races. Note that the usage of
> -        // write_volatile() is limited to this particular case, it cannot be used to prevent
> -        // the UB caused by racing between two kernel functions nor do they provide atomicity.
> +        // - As `field` points to readable memory:
> +        //   - Reading `field` will not trap.
> +        //   - Reading `field` will not change any memory inside a Rust allocation.
>          unsafe { field.write_volatile(val) }
>      }
>  }
>
> ---
> base-commit: 63804fed149a6750ffd28610c5c1c98cce6bd377
> change-id: 20260130-dma-doc-update-a8a0548045e2
>
> Best regards,
Re: [PATCH] rust: dma: update safety comments for volatile memory access
Posted by Andreas Hindborg 1 week ago
"Gary Guo" <gary@garyguo.net> writes:

> On Fri Jan 30, 2026 at 2:59 PM GMT, Andreas Hindborg wrote:
>> At the time `CoherentAllocation::read_field` and
>> `CoherentAllocation::write_field` was merged, `ptr::{read,write}_volatile`
>> was under specified. The documentation for these functions have been
>> updated and we can now formulate a proper safety comment for the calls.
>>
>> Update safety comments in `CoherentAllocation::{read,write}_field`.
>>
>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.read_volatile.html
>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.write_volatile.html
>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>> ---
>>  rust/kernel/dma.rs | 25 +++++++++----------------
>>  1 file changed, 9 insertions(+), 16 deletions(-)
>>
>> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
>> index acc65b1e0f245..0b55671a94faf 100644
>> --- a/rust/kernel/dma.rs
>> +++ b/rust/kernel/dma.rs
>> @@ -593,14 +593,12 @@ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
>>      pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
>>          // SAFETY:
>>          // - By the safety requirements field is valid.
>> -        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
>> -        // a special exception with the following notes in place. When dealing with a potential
>> -        // race from a hardware or code outside kernel (e.g. user-space program), we need that
>> -        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
>> -        // rationale behind is that it should generate the same code as READ_ONCE() which the
>> -        // kernel already relies on to avoid UB on data races. Note that the usage of
>> -        // read_volatile() is limited to this particular case, it cannot be used to prevent
>> -        // the UB caused by racing between two kernel functions nor do they provide atomicity.
>> +        // - `field` points to memory outside any Rust allocation.
>
> Hmm, this isn't actually correct, as the memory behind `CoherentAllocation`
> isn't MMIO (they're just also accessible by device). We provide `as_slice()`
> which exposes these memory directly to the Rust memory model.

I would not get too hung on the MMIO term. But if we provide `as_slice`,
this implementation of `read_field` and `write_field` is not sound at
all. We should fix that.


Best regards,
Andreas Hindborg
Re: [PATCH] rust: dma: update safety comments for volatile memory access
Posted by Danilo Krummrich 1 week ago
On Fri Jan 30, 2026 at 4:25 PM CET, Andreas Hindborg wrote:
> "Gary Guo" <gary@garyguo.net> writes:
>
>> On Fri Jan 30, 2026 at 2:59 PM GMT, Andreas Hindborg wrote:
>>> At the time `CoherentAllocation::read_field` and
>>> `CoherentAllocation::write_field` was merged, `ptr::{read,write}_volatile`
>>> was under specified. The documentation for these functions have been
>>> updated and we can now formulate a proper safety comment for the calls.
>>>
>>> Update safety comments in `CoherentAllocation::{read,write}_field`.
>>>
>>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.read_volatile.html
>>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.write_volatile.html
>>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>>> ---
>>>  rust/kernel/dma.rs | 25 +++++++++----------------
>>>  1 file changed, 9 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
>>> index acc65b1e0f245..0b55671a94faf 100644
>>> --- a/rust/kernel/dma.rs
>>> +++ b/rust/kernel/dma.rs
>>> @@ -593,14 +593,12 @@ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
>>>      pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
>>>          // SAFETY:
>>>          // - By the safety requirements field is valid.
>>> -        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
>>> -        // a special exception with the following notes in place. When dealing with a potential
>>> -        // race from a hardware or code outside kernel (e.g. user-space program), we need that
>>> -        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
>>> -        // rationale behind is that it should generate the same code as READ_ONCE() which the
>>> -        // kernel already relies on to avoid UB on data races. Note that the usage of
>>> -        // read_volatile() is limited to this particular case, it cannot be used to prevent
>>> -        // the UB caused by racing between two kernel functions nor do they provide atomicity.
>>> +        // - `field` points to memory outside any Rust allocation.
>>
>> Hmm, this isn't actually correct, as the memory behind `CoherentAllocation`
>> isn't MMIO (they're just also accessible by device). We provide `as_slice()`
>> which exposes these memory directly to the Rust memory model.
>
> I would not get too hung on the MMIO term. But if we provide `as_slice`,
> this implementation of `read_field` and `write_field` is not sound at
> all. We should fix that.

as_slice() is unsafe and the requirements do not allow you any concurrent reads
or writes as long as the slice is live.
Re: [PATCH] rust: dma: update safety comments for volatile memory access
Posted by Andreas Hindborg 1 week ago
"Danilo Krummrich" <dakr@kernel.org> writes:

> On Fri Jan 30, 2026 at 4:25 PM CET, Andreas Hindborg wrote:
>> "Gary Guo" <gary@garyguo.net> writes:
>>
>>> On Fri Jan 30, 2026 at 2:59 PM GMT, Andreas Hindborg wrote:
>>>> At the time `CoherentAllocation::read_field` and
>>>> `CoherentAllocation::write_field` was merged, `ptr::{read,write}_volatile`
>>>> was under specified. The documentation for these functions have been
>>>> updated and we can now formulate a proper safety comment for the calls.
>>>>
>>>> Update safety comments in `CoherentAllocation::{read,write}_field`.
>>>>
>>>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.read_volatile.html
>>>> Link: https://doc.rust-lang.org/stable/core/ptr/fn.write_volatile.html
>>>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>>>> ---
>>>>  rust/kernel/dma.rs | 25 +++++++++----------------
>>>>  1 file changed, 9 insertions(+), 16 deletions(-)
>>>>
>>>> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
>>>> index acc65b1e0f245..0b55671a94faf 100644
>>>> --- a/rust/kernel/dma.rs
>>>> +++ b/rust/kernel/dma.rs
>>>> @@ -593,14 +593,12 @@ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
>>>>      pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
>>>>          // SAFETY:
>>>>          // - By the safety requirements field is valid.
>>>> -        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
>>>> -        // a special exception with the following notes in place. When dealing with a potential
>>>> -        // race from a hardware or code outside kernel (e.g. user-space program), we need that
>>>> -        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
>>>> -        // rationale behind is that it should generate the same code as READ_ONCE() which the
>>>> -        // kernel already relies on to avoid UB on data races. Note that the usage of
>>>> -        // read_volatile() is limited to this particular case, it cannot be used to prevent
>>>> -        // the UB caused by racing between two kernel functions nor do they provide atomicity.
>>>> +        // - `field` points to memory outside any Rust allocation.
>>>
>>> Hmm, this isn't actually correct, as the memory behind `CoherentAllocation`
>>> isn't MMIO (they're just also accessible by device). We provide `as_slice()`
>>> which exposes these memory directly to the Rust memory model.
>>
>> I would not get too hung on the MMIO term. But if we provide `as_slice`,
>> this implementation of `read_field` and `write_field` is not sound at
>> all. We should fix that.
>
> as_slice() is unsafe and the requirements do not allow you any concurrent reads
> or writes as long as the slice is live.

As far as I understand, this does not matter for
ptr::volatile_{read,write}. Once you make a reference to a memory
region, it can no longer be considered to be outside of any Rust
allocation. But this is just what I picked up. Someone more compiler
savvy should chime in.


Best regards,
Andreas Hindborg