On Sun, Oct 19, 2025 at 4:43 PM Sergey Matyukevich <[email protected]> wrote: > > On Wed, Oct 15, 2025 at 02:54:39PM -0500, Andy Chiu wrote: > > Hi Sergey, > > > > On Tue, Oct 7, 2025 at 6:58 AM Sergey Matyukevich <[email protected]> > > wrote: > > > > > > The vstate in thread_struct is zeroed when the vector context is > > > initialized. That includes read-only register vlenb, which holds > > > the vector register length in bytes. This zeroed state persists > > > until mstatus.VS becomes 'dirty' and a context switch saves the > > > actual hardware values. > > > > > > This can expose the zero vlenb value to the user-space in early > > > debug scenarios, e.g. when ptrace attaches to a traced process > > > early, before any vector instruction except the first one was > > > executed. > > > > > > Fix this by forcing the vector context save on the first context switch. > > > > > > Signed-off-by: Sergey Matyukevich <[email protected]> > > > --- > > > arch/riscv/kernel/vector.c | 4 ++++ > > > 1 file changed, 4 insertions(+) > > > > > > diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c > > > index 901e67adf576..3dd22a71aa18 100644 > > > --- a/arch/riscv/kernel/vector.c > > > +++ b/arch/riscv/kernel/vector.c > > > @@ -120,6 +120,7 @@ static int riscv_v_thread_zalloc(struct kmem_cache > > > *cache, > > > > > > ctx->datap = datap; > > > memset(ctx, 0, offsetof(struct __riscv_v_ext_state, datap)); > > > + > > > return 0; > > > } > > > > > > @@ -216,8 +217,11 @@ bool riscv_v_first_use_handler(struct pt_regs *regs) > > > force_sig(SIGBUS); > > > return true; > > > } > > > + > > > riscv_v_vstate_on(regs); > > > riscv_v_vstate_set_restore(current, regs); > > > + set_tsk_thread_flag(current, TIF_RISCV_V_FORCE_SAVE); > > > + > > > > I am afraid that this approach can result in a security issue where a > > context switch happens before the v-restore part of the current > > process, cheating the kernel to store stale v-regs onto the current > > context memory. Please note that this handler is run with irq enabled > > so preemption is allowed. > > > > I would expect simply initializing the vleb in riscv_v_thread_zalloc, > > perhaps dropping the "z" in the name to prevent confusion. > > Ok, so we can just set 'ctx->vlenb = riscv_v_vsize / 32' in the renamed > riscv_v_thread_alloc function. But note, that w/o forced context save > we implicitly reset the vector configuration to 'all zeros', overwriting > the hardware defaults.
Resetting all vregs to zero is desired as otherwise we may unintentionally leak stale states from other users or the kernel to the user process. > > By the way, could you please elaborate a little bit more about your security > concerns with the TIF_RISCV_V_FORCE_SAVE approach ? The atomic and per-process > flag modification looks safe to me, so I'd like to understand what I am > missing. > The concern is information leak. A context switch can happen right after the FORCE_SAVE bit is set. At this point the kernel saves live vregs on the machine to the context memory (vstate) of that process. The content of live registers may come from another process, or stale value of in-kernel Vector uses, since we don't flush registers at every ownership change. When we switch back to the original process and return to the user space, the saved stale content is restored back to registers. As a result, the user space can read Vector registers from other contexts. Thanks, Andy

