Re: [PATCH] RDMA/rxe: Fix race in do_task() when draining
From: Yanjun.Zhu
Date: Thu Sep 18 2025 - 12:31:31 EST
On 9/17/25 7:21 PM, Gui-Dong Han wrote:
On Thu, Sep 18, 2025 at 3:31 AM yanjun.zhu <yanjun.zhu@xxxxxxxxx> wrote:Thanks a lot for your detailed explanations. Could you update the commit logs to reflect the points you explained above?
On 9/17/25 3:06 AM, Gui-Dong Han wrote:Hi Yanjun,
When do_task() exhausts its RXE_MAX_ITERATIONS budget, it unconditionallyFrom the source code, it will check ret value, then set it to
TASK_STATE_IDLE, not unconditionally.
Thanks for your review. Let me clarify a few points.
You are correct that the code checks the ret value. The if (!ret)
branch specifically handles the case where the RXE_MAX_ITERATIONS
limit is reached while work still remains. My use of "unconditionally"
refers to the action inside this branch, which sets the state to
TASK_STATE_IDLE without a secondary check on task->state. The original
tasklet implementation effectively checked both conditions in this
scenario.
While a spinlock protects state changes, rxe_cleanup_task() andsets the task state to TASK_STATE_IDLE to reschedule. This overwritesFrom the source code, there is a spin lock to protect the state. It
the TASK_STATE_DRAINING state that may have been concurrently set by
rxe_cleanup_task() or rxe_disable_task().
will not make race condition.
rxe_disable_task() do not hold it for its entire duration. It acquires
the lock to set TASK_STATE_DRAINING, but then releases it to wait in
the while (!is_done(task)) loop. The race window exists when do_task()
acquires the lock during this wait period, allowing it to overwrite
the TASK_STATE_DRAINING state.
This issue was identified through code inspection and a staticThis race condition breaks the cleanup and disable logic, which expectsCan you post the call trace when this problem occurred?
the task to stop processing new work. The cleanup code may proceed while
do_task() reschedules itself, leading to a potential use-after-free.
analysis tool we are developing to detect TOCTOU bugs in the kernel,
so I do not have a runtime call trace. The bug is confirmed by
inspecting the Fixes commit (9b4b7c1f9f54), which lost the special
handling for the draining case during the migration from tasklets to
workqueues.
The current commit logs are a bit confusing, but your explanation makes everything clear. If you rewrite the logs with that context, other reviewers will be able to understand your intent directly from the commit message, without needing the extra explanation. That would make the commit much clearer.
Any way,
Reviewed-by: Zhu Yanjun <yanjun.zhu@xxxxxxxxx>
Zhu Yanjun
Regards,
Han