Commit 6ebcbb53 authored by Michael Neuling's avatar Michael Neuling Committed by Paul Walmsley
Browse files

riscv: Fix register corruption from uninitialized cregs on error



compat_riscv_gpr_set() calls cregs_to_regs() unconditionally, even when
user_regset_copyin() fails. Since cregs is an uninitialized stack
variable, a copyin failure causes uninitialized stack data to be written
into the target task's pt_regs, corrupting its register state and
potentially leaking kernel stack contents.

compat_restore_sigcontext() has the same issue: it calls cregs_to_regs()
even when __copy_from_user() fails, leading to the same corruption of
the signal-returning task's register state on error.

Only call cregs_to_regs() when the user copy succeeds.

Fixes: 4608c159 ("riscv: compat: ptrace: Add compat_arch_ptrace implement")
Fixes: 7383ee05 ("riscv: compat: signal: Add rt_frame implementation")
Signed-off-by: default avatarMichael Neuling <mikey@neuling.org>
Assisted-by: Cursor:claude-4.6-opus-high-thinking
Link: https://patch.msgid.link/20260501062320.2339562-1-mikey@neuling.org


Signed-off-by: default avatarPaul Walmsley <pjw@kernel.org>
parent 4d2b0369
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ static long compat_restore_sigcontext(struct pt_regs *regs,

	/* sc_regs is structured the same as the start of pt_regs */
	err = __copy_from_user(&cregs, &sc->sc_regs, sizeof(sc->sc_regs));
	if (unlikely(err))
		return err;

	cregs_to_regs(&cregs, regs);

+2 −2
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ static int compat_riscv_gpr_set(struct task_struct *target,
	struct compat_user_regs_struct cregs;

	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1);

	if (!ret)
		cregs_to_regs(&cregs, task_pt_regs(target));

	return ret;