* [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-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 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 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.