[PATCH] riscv: ptrace: reject CFI regset access when extensions are absent

Chen Pei <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
riscv_cfi_get() and riscv_cfi_set() do not check whether the Zicfilp
or Zicfiss extensions are present. On systems without them,
PTRACE_GETREGSET on REGSET_CFI still succeeds and returns a zeroed
user_cfi_state, misleading debuggers into believing the register set
is available, and PTRACE_SETREGSET silently accepts writes that have
no effect (e.g. clearing SR_ELP).

Reject the access with -EINVAL when neither branch landing pads nor
shadow stack is available to userspace, using the same availability
helpers as the prctl path.

Fixes: 2af7c9cf021c ("riscv/ptrace: expose riscv CFI status and state via ptrace and in core files")
Signed-off-by: Chen Pei <[email protected]>
---
This follows the behaviour of the arm64 GCS regset. Unlike vector
registers, no ENODATA case applies here: the CFI status regset has a
valid all-zero representation even when CFI has not been enabled for
the traced task.

is_user_lpad_enabled()/is_user_shstk_enabled() are used instead of a
plain ISA check so that the regset visibility matches what userspace
can actually use via prctl: both helpers also honor the
riscv_nousercfi kernel command line switch.

 arch/riscv/kernel/ptrace.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index f336a183667e..566856e42f65 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -299,6 +299,9 @@ static int riscv_cfi_get(struct task_struct *target,
 	struct user_cfi_state user_cfi;
 	struct pt_regs *regs;
 
+	if (!is_user_lpad_enabled() && !is_user_shstk_enabled())
+		return -EINVAL;
+
 	memset(&user_cfi, 0, sizeof(user_cfi));
 	regs = task_pt_regs(target);
 
@@ -337,6 +340,9 @@ static int riscv_cfi_set(struct task_struct *target,
 	struct user_cfi_state user_cfi;
 	struct pt_regs *regs;
 
+	if (!is_user_lpad_enabled() && !is_user_shstk_enabled())
+		return -EINVAL;
+
 	regs = task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_cfi, 0, -1);
-- 
2.50.1


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.