* [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq`
@ 2026-09-14 21:47 ` Priya Bala Govindasamy
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
2026-09-16 9:50 ` [PATCH 0/1] " Andreas Hindborg
0 siblings, 2 replies; 9+ messages in thread
From: Priya Bala Govindasamy @ 2026-09-14 21:47 UTC (permalink / raw)
To: a.hindborg, boqun, ojeda, rust-for-linux
Cc: ardalan, zhiyunq, dzueck, pgovind2
Dear Linux kernel maintainers,
We are developing a tool called FerroLens to detect potential
unsound behavior in Rust code in the Linux kernel. The tool
internally uses an LLM to detect bugs.
We then perform manual analysis to verify these reports.
FerroLens reported the following bug in rust/kernel/block/mq/operations.rs:
A safe `Operations` implementation of `queue_rq` can retain a clone
of the provided `ARef<Request>` and return an error. This should not be
valid under the intended blk-mq ownership semantics, as an error
means the driver returns ownership of the `Request` to the block layer
which may requeue or end the request.
The refcount of the `ARef` is expected to be dropped to 0.
If the driver retains a clone of the `ARef<Request>` while
returning an error, it leads to a mismatch in the ownership state of the
request. The refcount of the `ARef` will remain 2 or greater.
But the refcount alone does not prevent the underlying C allocation
of the `Request` from being freed.
A driver with such an incorrect implementation of `queue_rq`
can lead to use-after-free.
The Rust `Operations::queue_rq` documentation and type signature do
not currently state or enforce the restriction that it is invalid to
retain a clone of the `ARef<Request>` while returning an error.
Operations is also a safe trait. Stating the restriction in
the documentation may not be enough as soundness depends on the
implementation.
Here is a PoC demonstrating this issue:
// SPDX-License-Identifier: GPL-2.0
use kernel::{
block::{
self,
mq::{gen_disk::GenDiskBuilder, Operations, Request, TagSet},
},
error::code::EIO,
prelude::*,
sync::{
aref::ARef,
atomic::{Atomic, Relaxed},
Arc,
global_lock,
},
};
module! {
type: QueueRqPoc,
name: "queue_rq_poc",
authors: ["Priya Govindasamy"],
description: "blk-mq queue_rq callback example",
license: "GPL",
}
static QUEUE_RQ_CALLS: Atomic<i32> = Atomic::new(0);
struct QueueRqDevice;
global_lock! {
// SAFETY: Initialized in module initializer before first use.
unsafe(uninit) static SAVED_RQ: SpinLock<Option<ARef<Request<QueueRqDevice>>>> = None;
}
#[vtable]
impl Operations for QueueRqDevice {
type QueueData = ();
fn queue_rq(_queue_data: (), rq: ARef<Request<Self>>, is_last: bool) -> Result {
let call = QUEUE_RQ_CALLS.fetch_add(1, Relaxed) + 1;
pr_info!("queue_rq_poc: queue_rq call {call}, is_last={is_last}\n");
let mut guard = SAVED_RQ.lock();
*guard = Some(rq.clone());
Err(EIO)
}
fn commit_rqs(_queue_data: ()) {}
fn complete(rq: ARef<Request<Self>>) {
// Required by `Operations`; this path is unused because `queue_rq`
// returns an error instead of calling `Request::complete`.
Request::end_ok(rq)
.map_err(|_rq| EIO)
.expect("queue_rq_poc: complete unexpectedly retained a request reference");
}
}
struct QueueRqPoc;
impl kernel::Module for QueueRqPoc {
fn init(_module: &'static ThisModule) -> Result<Self> {
let tagset: Arc<TagSet<QueueRqDevice>> =
Arc::pin_init(TagSet::new(1, 16, 1), GFP_KERNEL)?;
// SAFETY: called exactly once
unsafe {SAVED_RQ.init()};
// A nonzero-capacity disk is scanned for partitions synchronously by
// `device_add_disk`, which submits at least one real request through
// this disk's blk-mq queue before `build` returns.
let disk = GenDiskBuilder::new()
.capacity_sectors(1_u64 << block::PAGE_SECTORS_SHIFT)
.build(fmt!("queue_rq_poc"), tagset, ())?;
let calls = QUEUE_RQ_CALLS.load(Relaxed);
if calls == 0 {
pr_err!("queue_rq_poc: expected at least one queue_rq call\n");
return Err(EIO);
}
// The partition scan has completed, so the temporary registered disk
// is no longer needed. `GenDisk` safely unregisters it on drop.
drop(disk);
if let Some(rq) = SAVED_RQ.lock().take() {
pr_info!("using the cloned request later\n");
}
pr_info!("queue_rq_poc: init observed {calls} queue_rq call(s)\n");
Ok(Self)
}
}
Output:
[526592.634392] queue_rq_poc: queue_rq_poc: queue_rq call 1, is_last=true
[526592.634825] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.634938] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.635868] queue_rq_poc: queue_rq_poc: queue_rq call 2, is_last=true
[526592.635877] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.635890] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.635975] queue_rq_poc: queue_rq_poc: queue_rq call 3, is_last=true
[526592.635981] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.635992] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636051] ldm_validate_partition_table(): Disk read failed.
[526592.636137] queue_rq_poc: queue_rq_poc: queue_rq call 4, is_last=true
[526592.636143] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636154] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636239] queue_rq_poc: queue_rq_poc: queue_rq call 5, is_last=true
[526592.636246] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636256] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636326] queue_rq_poc: queue_rq_poc: queue_rq call 6, is_last=true
[526592.636331] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636340] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636409] queue_rq_poc: queue_rq_poc: queue_rq call 7, is_last=true
[526592.636415] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636424] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636441] Dev queue_rq_poc: unable to read RDB block 0
[526592.636495] queue_rq_poc: queue_rq_poc: queue_rq call 8, is_last=true
[526592.636500] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636509] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636590] queue_rq_poc: queue_rq_poc: queue_rq call 9, is_last=true
[526592.636596] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636606] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636681] queue_rq_poc: queue_rq_poc: queue_rq call 10, is_last=true
[526592.636687] I/O error, dev queue_rq_poc, sector 0 op 0x0:(READ) flags 0x800000 phys_seg 1 prio class 2
[526592.636697] Buffer I/O error on dev queue_rq_poc, logical block 0, async page read
[526592.636715] queue_rq_poc: unable to read partition table
[526592.636788] queue_rq_poc: partition table beyond EOD, truncated
[526592.707488] queue_rq_poc: using the cloned request later
[526592.707550] ==================================================================
[526592.707560] BUG: KASAN: use-after-free in rust_helper_refcount_dec_and_test+0x18/0x50
[526592.707638] Write of size 4 at addr ffff888347c6cc50 by task insmod/81905
[526592.707674] CPU: 15 UID: 0 PID: 81905 Comm: insmod Tainted: G OE 7.3.0-rc1+ #45 PREEMPT(lazy)
[526592.707683] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[526592.707685] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
[526592.707687] Call Trace:
[526592.707694] <TASK>
[526592.707703] dump_stack_lvl+0x97/0xe0
[526592.707734] print_report+0x175/0x6f0
[526592.707753] ? __virt_addr_valid+0x18d/0x3b0
[526592.707771] ? __virt_addr_valid+0x344/0x3b0
[526592.707774] ? rust_helper_refcount_dec_and_test+0x18/0x50
[526592.707778] ? kasan_addr_to_slab+0x11/0x90
[526592.707782] ? rust_helper_refcount_dec_and_test+0x18/0x50
[526592.707786] kasan_report+0xe4/0x120
[526592.707790] ? rust_helper_refcount_dec_and_test+0x18/0x50
[526592.707795] ? vprintk+0x59/0xe0
[526592.707819] kasan_check_range+0x2bc/0x2d0
[526592.707824] __kasan_check_write+0x18/0x20
[526592.707828] rust_helper_refcount_dec_and_test+0x18/0x50
[526592.707833] _RNvXCs5tE4rEXLlPW_12queue_rq_pocNtB2_10QueueRqPocNtNtCsbuTvttuFvbr_6kernel6module6Module4init+0x3b0/0x590 [queue_rq_poc]
[526592.707849] do_one_initcall+0x119/0x4f0
[526592.707852] ? do_init_module+0x63/0x740
[526592.707860] ? __pfx_init_module+0x10/0x10 [queue_rq_poc]
[526592.707865] ? __se_sys_finit_module+0x39d/0x5f0
[526592.707888] ? __x64_sys_finit_module+0x7f/0x90
[526592.707891] ? x64_sys_call+0xa66/0x2600
[526592.707898] ? do_syscall_64+0x11c/0x3f0
[526592.707923] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[526592.707927] ? kvm_sched_clock_read+0x15/0x40
[526592.707939] ? __lock_acquire+0xe84/0xfe0
[526592.707951] ? kvm_sched_clock_read+0x15/0x40
[526592.707956] ? debug_smp_processor_id+0x1b/0x30
[526592.707961] ? _raw_spin_unlock_irqrestore+0x38/0x90
[526592.707984] ? __this_cpu_preempt_check+0x17/0x20
[526592.707988] ? lockdep_hardirqs_on+0xdc/0x160
[526592.707991] ? debug_smp_processor_id+0x1b/0x30
[526592.707995] ? kasan_save_alloc_info+0x3a/0x50
[526592.707999] ? __kasan_kmalloc+0x94/0xb0
[526592.708003] ? __kmalloc_cache_noprof+0x350/0x6a0
[526592.708012] ? do_init_module+0x63/0x740
[526592.708014] ? __kmalloc_cache_noprof+0x158/0x6a0
[526592.708017] ? kasan_unpoison+0x4c/0x70
[526592.708022] ? kasan_poison+0x44/0x60
[526592.708027] do_init_module+0x23f/0x740
[526592.708035] load_module+0x32dc/0x3f20
[526592.708045] __se_sys_finit_module+0x39d/0x5f0
[526592.708076] __x64_sys_finit_module+0x7f/0x90
[526592.708080] x64_sys_call+0xa66/0x2600
[526592.708083] do_syscall_64+0x11c/0x3f0
[526592.708091] ? __x64_sys_newfstatat+0xc8/0x100
[526592.708104] ? debug_smp_processor_id+0x1b/0x30
[526592.708108] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[526592.708111] ? __this_cpu_preempt_check+0x17/0x20
[526592.708114] ? lockdep_hardirqs_on+0xdc/0x160
[526592.708117] ? do_syscall_64+0x217/0x3f0
[526592.708119] ? debug_smp_processor_id+0x1b/0x30
[526592.708123] ? debug_smp_processor_id+0x1b/0x30
[526592.708126] ? rcu_is_watching+0x1a/0xc0
[526592.708135] ? trace_irq_disable+0x3c/0x130
[526592.708153] ? do_syscall_64+0x6d/0x3f0
[526592.708155] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[526592.708159] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[526592.708162] RIP: 0033:0x7ffa9b71e9dd
[526592.708174] Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 23 b4 0f 00 f7 d8 64 89 01 48
[526592.708180] RSP: 002b:00007fff05d31c38 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[526592.708191] RAX: ffffffffffffffda RBX: 000055cafaff07d0 RCX: 00007ffa9b71e9dd
[526592.708194] RDX: 0000000000000000 RSI: 000055cade371cd2 RDI: 0000000000000003
[526592.708196] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[526592.708198] R10: 0000000000000003 R11: 0000000000000246 R12: 000055cade371cd2
[526592.708199] R13: 000055cafaff0790 R14: 000055cade370888 R15: 000055cafaff08e0
[526592.708207] </TASK>
[526592.708210] The buggy address belongs to the physical page:
[526592.708216] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x7f873e235 pfn:0x347c6c
[526592.708227] flags: 0x17ffffc0000000(node=0|zone=2|lastcpupid=0x1fffff)
[526592.708232] raw: 0017ffffc0000000 ffffea000ccd8e08 ffff8883ab21e0c8 0000000000000000
[526592.708235] raw: 00000007f873e235 0000000000000000 00000000ffffffff 0000000000000000
[526592.708236] page dumped because: kasan: bad access detected
[526592.708242] Memory state around the buggy address:
[526592.708247] ffff888347c6cb00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[526592.708249] ffff888347c6cb80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[526592.708250] >ffff888347c6cc00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[526592.708252] ^
[526592.708254] ffff888347c6cc80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[526592.708255] ffff888347c6cd00: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[526592.708257] ==================================================================
[526592.708283] Disabling lock debugging due to kernel taint
[526592.708285] queue_rq_poc: queue_rq_poc: init observed 10 queue_rq call(s)
Priya Bala Govindasamy (1):
rust: block: Fix unsoundness in `Operations::queue_rq`
rust/kernel/block/mq/operations.rs | 35 +++++++++++++++++++++---------
1 file changed, 25 insertions(+), 10 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-14 21:47 ` [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq` Priya Bala Govindasamy
@ 2026-09-14 21:47 ` Priya Bala Govindasamy
2026-09-15 5:39 ` Miguel Ojeda
` (2 more replies)
2026-09-16 9:50 ` [PATCH 0/1] " Andreas Hindborg
1 sibling, 3 replies; 9+ messages in thread
From: Priya Bala Govindasamy @ 2026-09-14 21:47 UTC (permalink / raw)
To: a.hindborg, boqun, ojeda, rust-for-linux
Cc: ardalan, zhiyunq, dzueck, pgovind2
A safe `Operations` implementation of `queue_rq` can retain a clone
of the provided request and return an error. This should not be
valid under the intended blk-mq ownership semantics, as an error
means the driver did not accept ownership. Therefore, if the driver
retains a request while returning an error, it leads to an ownership
mismatch and incorrect reference counting of the request. A driver
with such an incorrect implementation can lead to use-after-free.
The Rust `Operations::queue_rq` documentation and type signature do
not currently state or enforce the restriction that it is invalid
to retain a request while returning an error. Operations is also a
safe trait. Stating the restriction in the documentation may not be
enough as soundness depends on the implementation.
Fix this by making `Operations` an unsafe trait, adding appropriate
safety documentation and ensuring error path maintains the expected
refcount.
Fixes: 3253aba3408a ("rust: block: introduce `kernel::block::mq` module")
Reported-by: Dylan Zueck<dzueck@uci.edu>
Assisted-by: ChatGPT:gpt-5.6-sol
Signed-off-by: Priya Bala Govindasamy<pgovind2@uci.edu>
---
rust/kernel/block/mq/operations.rs | 35 +++++++++++++++++++++---------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 861903e18fbf..562c19a242f4 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -9,7 +9,7 @@
block::mq::{request::RequestDataWrapper, Request},
error::{from_result, Result},
prelude::*,
- sync::{aref::ARef, Refcount},
+ sync::{aref::ARef, Refcount, atomic::Relaxed},
types::ForeignOwnable,
};
use core::marker::PhantomData;
@@ -27,14 +27,21 @@
///
/// [module level documentation]: kernel::block::mq
#[macros::vtable]
-pub trait Operations: Sized {
+pub unsafe trait Operations: Sized {
/// Data associated with the `struct request_queue` that is allocated for
/// the `GenDisk` associated with this `Operations` implementation.
type QueueData: ForeignOwnable;
/// Called by the kernel to queue a request with the driver. If `is_last` is
/// `false`, the driver is allowed to defer committing the request.
- fn queue_rq(
+ ///
+ /// # Safety
+ ///
+ /// The implementor of this method must ensure that if Err is returned:
+ /// - The request has not already been completed.
+ /// - No ARef derived from the request remains anywhere.
+ /// - No reference was converted to raw or transferred to another thread.
+ unsafe fn queue_rq(
queue_data: ForeignBorrowed<'_, Self::QueueData>,
rq: ARef<Request<Self>>,
is_last: bool,
@@ -113,15 +120,23 @@ impl<T: Operations> OperationsVTable<T> {
// SAFETY: We have exclusive access and we just set the refcount above.
unsafe { Request::start_unchecked(&rq) };
- let ret = T::queue_rq(
- queue_data,
- rq,
- // SAFETY: `bd` is valid as required by the safety requirement for
- // this function.
- unsafe { (*bd).last },
- );
+ // SAFETY: `bd` is valid as required by the safety requirement for this function.
+ // `queue_rq` is correctly implemented to not retain or complete the request
+ // if it returns an error.
+ let ret = unsafe { T::queue_rq(
+ queue_data,
+ rq,
+ (*bd).last,
+ )
+ };
if let Err(e) = ret {
+ request
+ .wrapper_ref()
+ .refcount()
+ .as_atomic()
+ .cmpxchg(1, 0, Relaxed)
+ .expect("queue_rq returned an error while retaining or completing the request");
e.to_blk_status()
} else {
bindings::BLK_STS_OK as bindings::blk_status_t
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
@ 2026-09-15 5:39 ` Miguel Ojeda
2026-09-15 6:55 ` Miguel Ojeda
2026-09-15 9:42 ` kernel test robot
2026-09-15 13:45 ` kernel test robot
2 siblings, 1 reply; 9+ messages in thread
From: Miguel Ojeda @ 2026-09-15 5:39 UTC (permalink / raw)
To: Priya Bala Govindasamy
Cc: a.hindborg, boqun, ojeda, rust-for-linux, ardalan, zhiyunq,
dzueck, linux-block @ vger . kernel . org
On Mon, Sep 14, 2026 at 10:47 PM Priya Bala Govindasamy
<pgovind2@uci.edu> wrote:
>
> Fixes: 3253aba3408a ("rust: block: introduce `kernel::block::mq` module")
Should this have Cc: stable?
> Assisted-by: ChatGPT:gpt-5.6-sol
Nowadays, it is enough to say "Assisted-by: LLM" (the rules recently changed).
> Signed-off-by: Priya Bala Govindasamy<pgovind2@uci.edu>
The tags seem to be missing a space before `<`.
Cc'ing the linux-block list too (please see the `MAINTAINERS` file).
Finally, it is usually nice to provide a simple example when possible
of the safe code that triggers the issue.
> + /// # Safety
> + ///
> + /// The implementor of this method must ensure that if Err is returned:
> + /// - The request has not already been completed.
> + /// - No ARef derived from the request remains anywhere.
> + /// - No reference was converted to raw or transferred to another thread.
> + unsafe fn queue_rq(
The `# Safety` section is about the preconditions for callers, not for
implementers of the trait -- this should likely be on the trait.
Should this method be `unsafe fn` then? Did you build with `CLIPPY=1`?
Also, please add intra-doc links where possible, and please see
Sashiko's output too.
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-15 5:39 ` Miguel Ojeda
@ 2026-09-15 6:55 ` Miguel Ojeda
2026-09-15 17:28 ` Priya Bala Govindasamy
0 siblings, 1 reply; 9+ messages in thread
From: Miguel Ojeda @ 2026-09-15 6:55 UTC (permalink / raw)
To: Priya Bala Govindasamy
Cc: a.hindborg, boqun, ojeda, rust-for-linux, ardalan, zhiyunq,
dzueck, linux-block @ vger . kernel . org
On Tue, Sep 15, 2026 at 6:39 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> Finally, it is usually nice to provide a simple example when possible
> of the safe code that triggers the issue.
Ah, in case it helps: the cover letter was on my spam folder -- I see
you provided a full example there, thanks (it may still be nice to
show the key bits in the commit message, e.g. the part of the impl
that goes wrong), since that is what will be kept in the Git log.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
2026-09-15 5:39 ` Miguel Ojeda
@ 2026-09-15 9:42 ` kernel test robot
2026-09-15 13:45 ` kernel test robot
2 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2026-09-15 9:42 UTC (permalink / raw)
To: Priya Bala Govindasamy, a.hindborg, boqun, ojeda, rust-for-linux
Cc: llvm, oe-kbuild-all, ardalan, zhiyunq, dzueck, pgovind2
Hi Priya,
kernel test robot noticed the following build errors:
[auto build test ERROR on ah-configfs/configfs-next]
[also build test ERROR on rust/rust-next linus/master v7.3-rc3 next-20260911]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Priya-Bala-Govindasamy/rust-block-Fix-unsoundness-in-Operations-queue_rq/20260914-214701
base: https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git configfs-next
patch link: https://lore.kernel.org/r/f515b62bb05e7b6bf0bb06c8fdb362486fea25a8.1789420324.git.pgovind2%40uci.edu
patch subject: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
config: loongarch-randconfig-001-20260915 (https://download.01.org/0day-ci/archive/20260915/202609151724.qbLBSoTM-lkp@intel.com/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 148ee2b266b73a49f1f31d0bd17d4818b91bee9f)
rustc: rustc 1.96.0 (ac68faa20 2026-05-25)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260915/202609151724.qbLBSoTM-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609151724.qbLBSoTM-lkp@intel.com/
All errors (new ones prefixed by >>):
>> error[E0200]: the trait `rust_doctest_kernel_alloc_allocator_rs_0::kernel::block::mq::Operations` requires an `unsafe impl` declaration
--> rust/doctests_kernel_generated.rs:4101:1
|
4101 | impl Operations for MyBlkDevice {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `rust_doctest_kernel_alloc_allocator_rs_0::kernel::block::mq::Operations` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
4101 | unsafe impl Operations for MyBlkDevice {
| ++++++
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
2026-09-15 5:39 ` Miguel Ojeda
2026-09-15 9:42 ` kernel test robot
@ 2026-09-15 13:45 ` kernel test robot
2 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2026-09-15 13:45 UTC (permalink / raw)
To: Priya Bala Govindasamy, a.hindborg, boqun, ojeda, rust-for-linux
Cc: llvm, oe-kbuild-all, ardalan, zhiyunq, dzueck, pgovind2
Hi Priya,
kernel test robot noticed the following build errors:
[auto build test ERROR on ah-configfs/configfs-next]
[also build test ERROR on rust/rust-next linus/master v7.3-rc3 next-20260914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Priya-Bala-Govindasamy/rust-block-Fix-unsoundness-in-Operations-queue_rq/20260914-214701
base: https://git.kernel.org/pub/scm/linux/kernel/git/a.hindborg/configfs.git configfs-next
patch link: https://lore.kernel.org/r/f515b62bb05e7b6bf0bb06c8fdb362486fea25a8.1789420324.git.pgovind2%40uci.edu
patch subject: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
config: x86_64-randconfig-072-20260915 (https://download.01.org/0day-ci/archive/20260915/202609152118.xAc2Dsw9-lkp@intel.com/config)
compiler: clang version 22.1.3 (https://github.com/llvm/llvm-project e9846648fd6183ee6d8cbdb4502213fcf902a211)
rustc: rustc 1.96.0 (ac68faa20 2026-05-25)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260915/202609152118.xAc2Dsw9-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609152118.xAc2Dsw9-lkp@intel.com/
All errors (new ones prefixed by >>):
>> error[E0200]: the trait `Operations` requires an `unsafe impl` declaration
--> drivers/block/rnull/rnull.rs:73:1
|
73 | impl Operations for NullBlkDevice {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Operations` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
73 | unsafe impl Operations for NullBlkDevice {
| ++++++
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-15 6:55 ` Miguel Ojeda
@ 2026-09-15 17:28 ` Priya Bala Govindasamy
0 siblings, 0 replies; 9+ messages in thread
From: Priya Bala Govindasamy @ 2026-09-15 17:28 UTC (permalink / raw)
To: Miguel Ojeda
Cc: a.hindborg, boqun, ojeda, rust-for-linux, ardalan, zhiyunq,
dzueck, linux-block @ vger . kernel . org
Thanks for your response. I will send a v2 patch addressing the feedback.
Best regards,
Priya
On Mon, Sep 14, 2026 at 11:55 PM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Tue, Sep 15, 2026 at 6:39 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
> >
> > Finally, it is usually nice to provide a simple example when possible
> > of the safe code that triggers the issue.
>
> Ah, in case it helps: the cover letter was on my spam folder -- I see
> you provided a full example there, thanks (it may still be nice to
> show the key bits in the commit message, e.g. the part of the impl
> that goes wrong), since that is what will be kept in the Git log.
>
> Cheers,
> Miguel
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-14 21:47 ` [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq` Priya Bala Govindasamy
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
@ 2026-09-16 9:50 ` Andreas Hindborg
2026-09-16 20:13 ` Priya Bala Govindasamy
1 sibling, 1 reply; 9+ messages in thread
From: Andreas Hindborg @ 2026-09-16 9:50 UTC (permalink / raw)
To: Priya Bala Govindasamy, boqun, ojeda, rust-for-linux
Cc: ardalan, zhiyunq, dzueck, pgovind2
Hi Priva,
"Priya Bala Govindasamy" <pgovind2@uci.edu> writes:
> Dear Linux kernel maintainers,
>
> We are developing a tool called FerroLens to detect potential
> unsound behavior in Rust code in the Linux kernel. The tool
> internally uses an LLM to detect bugs.
> We then perform manual analysis to verify these reports.
> FerroLens reported the following bug in rust/kernel/block/mq/operations.rs:
>
> A safe `Operations` implementation of `queue_rq` can retain a clone
> of the provided `ARef<Request>` and return an error. This should not be
> valid under the intended blk-mq ownership semantics, as an error
> means the driver returns ownership of the `Request` to the block layer
> which may requeue or end the request.
> The refcount of the `ARef` is expected to be dropped to 0.
>
> If the driver retains a clone of the `ARef<Request>` while
> returning an error, it leads to a mismatch in the ownership state of the
> request. The refcount of the `ARef` will remain 2 or greater.
> But the refcount alone does not prevent the underlying C allocation
> of the `Request` from being freed.
> A driver with such an incorrect implementation of `queue_rq`
> can lead to use-after-free.
>
> The Rust `Operations::queue_rq` documentation and type signature do
> not currently state or enforce the restriction that it is invalid to
> retain a clone of the `ARef<Request>` while returning an error.
> Operations is also a safe trait. Stating the restriction in
> the documentation may not be enough as soundness depends on the
> implementation.
I am aware of the issue. We have are fixing it by reworking the
reference count on the request structure and introducing a typestate for
the request [1].
I would appreciate review tags on the change.
The change is depending on the `Ownable` series being merged, which
hopefully is not that far into the future [2].
I do not think your solution of making the `Operations` trait unsafe is
viable.
Best regards,
Andreas Hindborg
[1] https://lore.kernel.org/r/20260609-rnull-v6-19-rc5-send-v2-38-82c7404542e2@kernel.org
[2] https://lore.kernel.org/r/20260910-unique-ref-v21-0-e83257373062@kernel.org
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq`
2026-09-16 9:50 ` [PATCH 0/1] " Andreas Hindborg
@ 2026-09-16 20:13 ` Priya Bala Govindasamy
0 siblings, 0 replies; 9+ messages in thread
From: Priya Bala Govindasamy @ 2026-09-16 20:13 UTC (permalink / raw)
To: Andreas Hindborg; +Cc: boqun, ojeda, rust-for-linux, ardalan, zhiyunq, dzueck
I see. I agree that that's a better solution. Thanks.
Best regards,
Priya
On Wed, Sep 16, 2026 at 2:50 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> Hi Priva,
>
> "Priya Bala Govindasamy" <pgovind2@uci.edu> writes:
>
> > Dear Linux kernel maintainers,
> >
> > We are developing a tool called FerroLens to detect potential
> > unsound behavior in Rust code in the Linux kernel. The tool
> > internally uses an LLM to detect bugs.
> > We then perform manual analysis to verify these reports.
> > FerroLens reported the following bug in rust/kernel/block/mq/operations.rs:
> >
> > A safe `Operations` implementation of `queue_rq` can retain a clone
> > of the provided `ARef<Request>` and return an error. This should not be
> > valid under the intended blk-mq ownership semantics, as an error
> > means the driver returns ownership of the `Request` to the block layer
> > which may requeue or end the request.
> > The refcount of the `ARef` is expected to be dropped to 0.
> >
> > If the driver retains a clone of the `ARef<Request>` while
> > returning an error, it leads to a mismatch in the ownership state of the
> > request. The refcount of the `ARef` will remain 2 or greater.
> > But the refcount alone does not prevent the underlying C allocation
> > of the `Request` from being freed.
> > A driver with such an incorrect implementation of `queue_rq`
> > can lead to use-after-free.
> >
> > The Rust `Operations::queue_rq` documentation and type signature do
> > not currently state or enforce the restriction that it is invalid to
> > retain a clone of the `ARef<Request>` while returning an error.
> > Operations is also a safe trait. Stating the restriction in
> > the documentation may not be enough as soundness depends on the
> > implementation.
>
> I am aware of the issue. We have are fixing it by reworking the
> reference count on the request structure and introducing a typestate for
> the request [1].
>
> I would appreciate review tags on the change.
>
> The change is depending on the `Ownable` series being merged, which
> hopefully is not that far into the future [2].
>
> I do not think your solution of making the `Operations` trait unsafe is
> viable.
>
> Best regards,
> Andreas Hindborg
>
>
> [1] https://urldefense.com/v3/__https://lore.kernel.org/r/20260609-rnull-v6-19-rc5-send-v2-38-82c7404542e2@kernel.org__;!!CzAuKJ42GuquVTTmVmPViYEvSg!Mmu6zot6sYJyX3kAVFwlFI5CTUE48mHNXBkT5jjgxS6Y8BBntxgWOKwJUXFuJezuLmGMgd8SS4cUwZoKcskObA$
> [2] https://urldefense.com/v3/__https://lore.kernel.org/r/20260910-unique-ref-v21-0-e83257373062@kernel.org__;!!CzAuKJ42GuquVTTmVmPViYEvSg!Mmu6zot6sYJyX3kAVFwlFI5CTUE48mHNXBkT5jjgxS6Y8BBntxgWOKwJUXFuJezuLmGMgd8SS4cUwZppzzXxNg$
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-16 20:13 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <dr-4ZXYvFqamrGT7sNDgGGci-fvvY9rMjSg9s4XG_gslBqFmVHmmd7yEt5xN5mBU5MlsdK-uvAL4Ydfz0J86Sw==@protonmail.internalid>
2026-09-14 21:47 ` [PATCH 0/1] rust: block: Fix unsoundness in `Operations::queue_rq` Priya Bala Govindasamy
2026-09-14 21:47 ` [PATCH 1/1] " Priya Bala Govindasamy
2026-09-15 5:39 ` Miguel Ojeda
2026-09-15 6:55 ` Miguel Ojeda
2026-09-15 17:28 ` Priya Bala Govindasamy
2026-09-15 9:42 ` kernel test robot
2026-09-15 13:45 ` kernel test robot
2026-09-16 9:50 ` [PATCH 0/1] " Andreas Hindborg
2026-09-16 20:13 ` Priya Bala Govindasamy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.