[PW_SID:1141880] riscv: signal: protect regs->status RMW from concurrent preemption - #2425
[PW_SID:1141880] riscv: signal: protect regs->status RMW from concurrent preemption#2425linux-riscv-bot wants to merge 2 commits into
Conversation
__fstate_clean() performs a non-atomic read-modify-write (RMW) on
task_pt_regs(current)->status to clear the FS bits. This RMW is
unprotected - it runs with preemption enabled and IRQs on during
signal delivery (setup_rt_frame -> fstate_save) and sigreturn
(restore_fp_state -> fstate_restore).
If a reschedule IPI or timer interrupt triggers preemption between
the load and store of this RMW, __switch_to_vector() calls
riscv_v_vstate_set_restore() which modifies the VS bits of the
same regs->status. When the preempted task resumes, it stores back
the stale value captured before preemption, overwriting the VS
update and restoring VS=DIRTY while TIF_RISCV_V_DEFER_RESTORE
remains set - a combination that should never occur and leads to
vector state corruption.
The race window:
__fstate_clean (signal path) set_restore (schedule path)
----------------------------- -----------------------------
ld a0, regs->status // VS=DIRTY, FS=DIRTY
<- preempted (reschedule IPI)
regs->status VS = INITIAL
set TIF_RISCV_V_DEFER_RESTORE
<- resumed
andi a0, ~FS
ori a0, FS_CLEAN // stale a0 still has VS=DIRTY
sd a0, regs->status // overwrites VS=INITIAL with VS=DIRTY
-> result: VS=DIRTY + DEFER -> ANOMALY
Fix by adding preempt_disable/enable around the RMW in
__fstate_clean() and fstate_off(). riscv_v_vstate_set_restore()
has the identical hazard: it is called from __restore_v_state()
(sigreturn path) with preemption enabled, and it can race the same
way against the scheduler's own call to riscv_v_vstate_set_restore()
for the same task in __switch_to_vector(). Wrap that call site with
preempt_disable/enable as well.
Add WARN_ON_ONCE(preemptible()) to riscv_v_vstate_restore()
to catch any future unprotected callers at development time.
Signed-off-by: Guobin Zhang <guobin.zhang@intel.com>
Signed-off-by: Linux RISC-V bot <linux.riscv.bot@gmail.com>
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
|
Patch 1: "riscv: signal: protect regs->status RMW from concurrent preemption" |
abf8962 to
9fa746d
Compare
PR for series 1141880 applied to workflow__riscv__fixes
Name: riscv: signal: protect regs->status RMW from concurrent preemption
URL: https://patchwork.kernel.org/project/linux-riscv/list/?series=1141880
Version: 1