* [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces
@ 2026-04-04 1:40 Paul Walmsley
2026-04-04 1:41 ` [PATCH 1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header Paul Walmsley
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:40 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie
Restructure the per-task CFI indirect branch landing pad prctl()
interface, as suggested by Linus [1]. In place of the current
approach, which follows the style of shadow stack control prctl()s
(PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS), adopt the style of the
speculation control prctl() constants (PR_{GET,SET}_SPECULATION_CTRL).
Then, to improve readability, expand "indir_br_lp", "lpad", and
related abbreviations in the interfaces, also as requested by Linus.
While here, expand "ss" in the shadow stack ptrace macros to "shadow
stack".
While here, let's fix a few bugs in the interfaces that we should have
caught earlier:
- Fix a misspelling of "PTRACE" in one of the macros that is defined
in a uapi header file
- Add a "lock" parameter to the state locking functions, fixing a bug
when a locked process calls exec()
This series is intended to be applied before the v7.0 release, since
it changes user API constants. This series applies on commit
2ff48e0382102b29cba20cdd8bf16a0f045f6e33 ("selftests: riscv: Add
braces around EXPECT_EQ()") in the RISC-V fixes branch.
- Paul
1. https://lore.kernel.org/linux-riscv/CAHk-=whhSLGZAx3N5jJpb4GLFDqH_QvS07D+6BnkPWmCEzTAgw@mail.gmail.com/
---
Paul Walmsley (5):
riscv: ptrace: cfi: fix "PRACE" typo in uapi header
riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers
prctl: rename branch landing pad implementation functions to be more explicit
riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers
prctl: cfi: change the branch landing pad prctl()s to be more descriptive
Zong Li (1):
riscv: cfi: clear CFI lock status in start_thread()
Documentation/arch/riscv/zicfilp.rst | 63 ++++++++++++--------
arch/riscv/include/asm/usercfi.h | 8 +--
arch/riscv/include/uapi/asm/ptrace.h | 42 +++++++------
arch/riscv/kernel/process.c | 2 +
arch/riscv/kernel/ptrace.c | 22 +++----
arch/riscv/kernel/usercfi.c | 39 ++++++------
include/linux/cpu.h | 6 +-
include/uapi/linux/prctl.h | 37 +++++-------
kernel/sys.c | 30 +++++-----
tools/perf/trace/beauty/include/uapi/linux/prctl.h | 36 +++++------
tools/testing/selftests/riscv/cfi/cfitests.c | 13 ++--
11 files changed, 154 insertions(+), 144 deletions(-)
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:41 ` [PATCH 2/6] riscv: cfi: clear CFI lock status in start_thread() Paul Walmsley
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Deepak Gupta
A CFI-related macro defined in arch/riscv/uapi/asm/ptrace.h misspells
"PTRACE" as "PRACE"; fix this.
Fixes: 2af7c9cf021c ("riscv/ptrace: expose riscv CFI status and state via ptrace and in core files")
Cc: Deepak Gupta <debug@rivosinc.com>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/include/uapi/asm/ptrace.h | 2 +-
arch/riscv/kernel/ptrace.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
index 70a74adad914..69d71443e111 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -146,7 +146,7 @@ struct __sc_riscv_cfi_state {
#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
-#define PRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
+#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
PTRACE_CFI_LP_LOCK_STATE | \
PTRACE_CFI_ELP_STATE | \
PTRACE_CFI_SS_EN_STATE | \
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index e592bd6b7665..2704a532e916 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -351,7 +351,7 @@ static int riscv_cfi_set(struct task_struct *target,
if ((user_cfi.cfi_status.cfi_state &
(PTRACE_CFI_LP_EN_STATE | PTRACE_CFI_LP_LOCK_STATE |
PTRACE_CFI_SS_EN_STATE | PTRACE_CFI_SS_LOCK_STATE)) ||
- (user_cfi.cfi_status.cfi_state & PRACE_CFI_STATE_INVALID_MASK))
+ (user_cfi.cfi_status.cfi_state & PTRACE_CFI_STATE_INVALID_MASK))
return -EINVAL;
/* If lpad is enabled on target and ptrace requests to set / clear elp, do that */
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/6] riscv: cfi: clear CFI lock status in start_thread()
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
2026-04-04 1:41 ` [PATCH 1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:41 ` [PATCH 3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers Paul Walmsley
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Zong Li
From: Zong Li <zong.li@sifive.com>
When libc locks the CFI status through the following prctl:
- PR_LOCK_SHADOW_STACK_STATUS
- PR_LOCK_INDIR_BR_LP_STATUS
A newly execd address space will inherit the lock status
if it does not clear the lock bits. Since the lock bits
remain set, libc will later fail to enable the landing
pad and shadow stack.
Signed-off-by: Zong Li <zong.li@sifive.com>
Link: https://patch.msgid.link/20260323065640.4045713-1-zong.li@sifive.com
[pjw@kernel.org: ensure we unlock before changing state; cleaned up subject line]
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/include/asm/usercfi.h | 8 ++++----
arch/riscv/kernel/process.c | 2 ++
arch/riscv/kernel/usercfi.c | 12 ++++++------
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h
index 7495baae1e3c..f56966edbf5c 100644
--- a/arch/riscv/include/asm/usercfi.h
+++ b/arch/riscv/include/asm/usercfi.h
@@ -39,7 +39,7 @@ void set_active_shstk(struct task_struct *task, unsigned long shstk_addr);
bool is_shstk_enabled(struct task_struct *task);
bool is_shstk_locked(struct task_struct *task);
bool is_shstk_allocated(struct task_struct *task);
-void set_shstk_lock(struct task_struct *task);
+void set_shstk_lock(struct task_struct *task, bool lock);
void set_shstk_status(struct task_struct *task, bool enable);
unsigned long get_active_shstk(struct task_struct *task);
int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr);
@@ -47,7 +47,7 @@ int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr);
bool is_indir_lp_enabled(struct task_struct *task);
bool is_indir_lp_locked(struct task_struct *task);
void set_indir_lp_status(struct task_struct *task, bool enable);
-void set_indir_lp_lock(struct task_struct *task);
+void set_indir_lp_lock(struct task_struct *task, bool lock);
#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE)
@@ -69,7 +69,7 @@ void set_indir_lp_lock(struct task_struct *task);
#define is_shstk_allocated(task) false
-#define set_shstk_lock(task) do {} while (0)
+#define set_shstk_lock(task, lock) do {} while (0)
#define set_shstk_status(task, enable) do {} while (0)
@@ -79,7 +79,7 @@ void set_indir_lp_lock(struct task_struct *task);
#define set_indir_lp_status(task, enable) do {} while (0)
-#define set_indir_lp_lock(task) do {} while (0)
+#define set_indir_lp_lock(task, lock) do {} while (0)
#define restore_user_shstk(tsk, shstk_ptr) -EINVAL
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index 5957effab57c..b2df7f72241a 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -160,6 +160,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
* clear shadow stack state on exec.
* libc will set it later via prctl.
*/
+ set_shstk_lock(current, false);
set_shstk_status(current, false);
set_shstk_base(current, 0, 0);
set_active_shstk(current, 0);
@@ -167,6 +168,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
* disable indirect branch tracking on exec.
* libc will enable it later via prctl.
*/
+ set_indir_lp_lock(current, false);
set_indir_lp_status(current, false);
#ifdef CONFIG_64BIT
diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
index 1adba746f164..9052171c1a8c 100644
--- a/arch/riscv/kernel/usercfi.c
+++ b/arch/riscv/kernel/usercfi.c
@@ -74,9 +74,9 @@ void set_shstk_status(struct task_struct *task, bool enable)
csr_write(CSR_ENVCFG, task->thread.envcfg);
}
-void set_shstk_lock(struct task_struct *task)
+void set_shstk_lock(struct task_struct *task, bool lock)
{
- task->thread_info.user_cfi_state.ubcfi_locked = 1;
+ task->thread_info.user_cfi_state.ubcfi_locked = lock;
}
bool is_indir_lp_enabled(struct task_struct *task)
@@ -104,9 +104,9 @@ void set_indir_lp_status(struct task_struct *task, bool enable)
csr_write(CSR_ENVCFG, task->thread.envcfg);
}
-void set_indir_lp_lock(struct task_struct *task)
+void set_indir_lp_lock(struct task_struct *task, bool lock)
{
- task->thread_info.user_cfi_state.ufcfi_locked = 1;
+ task->thread_info.user_cfi_state.ufcfi_locked = lock;
}
/*
* If size is 0, then to be compatible with regular stack we want it to be as big as
@@ -452,7 +452,7 @@ int arch_lock_shadow_stack_status(struct task_struct *task,
!is_shstk_enabled(task) || arg != 0)
return -EINVAL;
- set_shstk_lock(task);
+ set_shstk_lock(task, true);
return 0;
}
@@ -502,7 +502,7 @@ int arch_lock_indir_br_lp_status(struct task_struct *task,
!is_indir_lp_enabled(task) || arg != 0)
return -EINVAL;
- set_indir_lp_lock(task);
+ set_indir_lp_lock(task, true);
return 0;
}
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
2026-04-04 1:41 ` [PATCH 1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header Paul Walmsley
2026-04-04 1:41 ` [PATCH 2/6] riscv: cfi: clear CFI lock status in start_thread() Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:41 ` [PATCH 4/6] prctl: rename branch landing pad implementation functions to be more explicit Paul Walmsley
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Deepak Gupta
Per Linus' comments about the unreadability of abbreviations such as
"LP", rename the RISC-V ptrace landing pad CFI macro names to be more
explicit. This primarily involves expanding "LP" in the names to some
variant of "branch landing pad."
Link: https://lore.kernel.org/linux-riscv/CAHk-=whhSLGZAx3N5jJpb4GLFDqH_QvS07D+6BnkPWmCEzTAgw@mail.gmail.com/
Cc: Deepak Gupta <debug@rivosinc.com>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/include/uapi/asm/ptrace.h | 20 +++++++++++---------
arch/riscv/kernel/ptrace.c | 10 +++++-----
tools/testing/selftests/riscv/cfi/cfitests.c | 5 +++--
3 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
index 69d71443e111..9985bd58148e 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -132,23 +132,25 @@ struct __sc_riscv_cfi_state {
unsigned long ss_ptr; /* shadow stack pointer */
};
-#define PTRACE_CFI_LP_EN_BIT 0
-#define PTRACE_CFI_LP_LOCK_BIT 1
-#define PTRACE_CFI_ELP_BIT 2
+#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT 0
+#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT 1
+#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT 2
#define PTRACE_CFI_SS_EN_BIT 3
#define PTRACE_CFI_SS_LOCK_BIT 4
#define PTRACE_CFI_SS_PTR_BIT 5
-#define PTRACE_CFI_LP_EN_STATE _BITUL(PTRACE_CFI_LP_EN_BIT)
-#define PTRACE_CFI_LP_LOCK_STATE _BITUL(PTRACE_CFI_LP_LOCK_BIT)
-#define PTRACE_CFI_ELP_STATE _BITUL(PTRACE_CFI_ELP_BIT)
+#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT)
+#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE \
+ _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT)
+#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE \
+ _BITUL(PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT)
#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT)
#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
-#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
- PTRACE_CFI_LP_LOCK_STATE | \
- PTRACE_CFI_ELP_STATE | \
+#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
+ PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE | \
+ PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE | \
PTRACE_CFI_SS_EN_STATE | \
PTRACE_CFI_SS_LOCK_STATE | \
PTRACE_CFI_SS_PTR_STATE)
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 2704a532e916..b6156625d6f8 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -303,11 +303,11 @@ static int riscv_cfi_get(struct task_struct *target,
regs = task_pt_regs(target);
if (is_indir_lp_enabled(target)) {
- user_cfi.cfi_status.cfi_state |= PTRACE_CFI_LP_EN_STATE;
+ user_cfi.cfi_status.cfi_state |= PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE;
user_cfi.cfi_status.cfi_state |= is_indir_lp_locked(target) ?
- PTRACE_CFI_LP_LOCK_STATE : 0;
+ PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE : 0;
user_cfi.cfi_status.cfi_state |= (regs->status & SR_ELP) ?
- PTRACE_CFI_ELP_STATE : 0;
+ PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE : 0;
}
if (is_shstk_enabled(target)) {
@@ -349,7 +349,7 @@ static int riscv_cfi_set(struct task_struct *target,
* rsvd field should be set to zero so that if those fields are needed in future
*/
if ((user_cfi.cfi_status.cfi_state &
- (PTRACE_CFI_LP_EN_STATE | PTRACE_CFI_LP_LOCK_STATE |
+ (PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE |
PTRACE_CFI_SS_EN_STATE | PTRACE_CFI_SS_LOCK_STATE)) ||
(user_cfi.cfi_status.cfi_state & PTRACE_CFI_STATE_INVALID_MASK))
return -EINVAL;
@@ -357,7 +357,7 @@ static int riscv_cfi_set(struct task_struct *target,
/* If lpad is enabled on target and ptrace requests to set / clear elp, do that */
if (is_indir_lp_enabled(target)) {
if (user_cfi.cfi_status.cfi_state &
- PTRACE_CFI_ELP_STATE) /* set elp state */
+ PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE) /* set elp state */
regs->status |= SR_ELP;
else
regs->status &= ~SR_ELP; /* clear elp state */
diff --git a/tools/testing/selftests/riscv/cfi/cfitests.c b/tools/testing/selftests/riscv/cfi/cfitests.c
index 298544854415..68374a27ec81 100644
--- a/tools/testing/selftests/riscv/cfi/cfitests.c
+++ b/tools/testing/selftests/riscv/cfi/cfitests.c
@@ -94,7 +94,7 @@ bool cfi_ptrace_test(void)
}
switch (ptrace_test_num) {
-#define CFI_ENABLE_MASK (PTRACE_CFI_LP_EN_STATE | \
+#define CFI_ENABLE_MASK (PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
PTRACE_CFI_SS_EN_STATE | \
PTRACE_CFI_SS_PTR_STATE)
case 0:
@@ -106,7 +106,8 @@ bool cfi_ptrace_test(void)
__func__);
break;
case 1:
- if (!(cfi_reg.cfi_status.cfi_state & PTRACE_CFI_ELP_STATE))
+ if (!(cfi_reg.cfi_status.cfi_state &
+ PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE))
ksft_exit_fail_msg("%s: elp must have been set\n", __func__);
/* clear elp state. not interested in anything else */
cfi_reg.cfi_status.cfi_state = 0;
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/6] prctl: rename branch landing pad implementation functions to be more explicit
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
` (2 preceding siblings ...)
2026-04-04 1:41 ` [PATCH 3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:41 ` [PATCH 5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers Paul Walmsley
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Deepak Gupta
Per Linus' comments about the unreadability of abbreviations such as
"indir_br_lp", rename the three prctl() implementation functions to be more
explicit. This involves renaming "indir_br_lp_status" in the function
names to "branch_landing_pad_state".
While here, add _prctl_ into the function names, following the
speculation control prctl implementation functions.
Link: https://lore.kernel.org/linux-riscv/CAHk-=whhSLGZAx3N5jJpb4GLFDqH_QvS07D+6BnkPWmCEzTAgw@mail.gmail.com/
Cc: Deepak Gupta <debug@rivosinc.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/kernel/usercfi.c | 16 ++++++++--------
include/linux/cpu.h | 6 +++---
kernel/sys.c | 15 ++++++++-------
3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
index 9052171c1a8c..04ab1eb8df29 100644
--- a/arch/riscv/kernel/usercfi.c
+++ b/arch/riscv/kernel/usercfi.c
@@ -457,7 +457,8 @@ int arch_lock_shadow_stack_status(struct task_struct *task,
return 0;
}
-int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
+int arch_prctl_get_branch_landing_pad_state(struct task_struct *t,
+ unsigned long __user *state)
{
unsigned long fcfi_status = 0;
@@ -467,10 +468,10 @@ int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *sta
/* indirect branch tracking is enabled on the task or not */
fcfi_status |= (is_indir_lp_enabled(t) ? PR_INDIR_BR_LP_ENABLE : 0);
- return copy_to_user(status, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
+ return copy_to_user(state, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
}
-int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
+int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state)
{
bool enable_indir_lp = false;
@@ -482,24 +483,23 @@ int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
return -EINVAL;
/* Reject unknown flags */
- if (status & ~PR_INDIR_BR_LP_ENABLE)
+ if (state & ~PR_INDIR_BR_LP_ENABLE)
return -EINVAL;
- enable_indir_lp = (status & PR_INDIR_BR_LP_ENABLE);
+ enable_indir_lp = (state & PR_INDIR_BR_LP_ENABLE);
set_indir_lp_status(t, enable_indir_lp);
return 0;
}
-int arch_lock_indir_br_lp_status(struct task_struct *task,
- unsigned long arg)
+int arch_prctl_lock_branch_landing_pad_state(struct task_struct *task)
{
/*
* If indirect branch tracking is not supported or not enabled on task,
* nothing to lock here
*/
if (!is_user_lpad_enabled() ||
- !is_indir_lp_enabled(task) || arg != 0)
+ !is_indir_lp_enabled(task))
return -EINVAL;
set_indir_lp_lock(task, true);
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 8239cd95a005..9b6b0d87fdb0 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -229,8 +229,8 @@ static inline bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
#define smt_mitigations SMT_MITIGATIONS_OFF
#endif
-int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status);
-int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status);
-int arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status);
+int arch_prctl_get_branch_landing_pad_state(struct task_struct *t, unsigned long __user *state);
+int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state);
+int arch_prctl_lock_branch_landing_pad_state(struct task_struct *t);
#endif /* _LINUX_CPU_H_ */
diff --git a/kernel/sys.c b/kernel/sys.c
index c86eba9aa7e9..a5e0c187bbbf 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2388,17 +2388,18 @@ int __weak arch_lock_shadow_stack_status(struct task_struct *t, unsigned long st
return -EINVAL;
}
-int __weak arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
+int __weak arch_prctl_get_branch_landing_pad_state(struct task_struct *t,
+ unsigned long __user *state)
{
return -EINVAL;
}
-int __weak arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
+int __weak arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state)
{
return -EINVAL;
}
-int __weak arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status)
+int __weak arch_prctl_lock_branch_landing_pad_state(struct task_struct *t)
{
return -EINVAL;
}
@@ -2891,17 +2892,17 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
case PR_GET_INDIR_BR_LP_STATUS:
if (arg3 || arg4 || arg5)
return -EINVAL;
- error = arch_get_indir_br_lp_status(me, (unsigned long __user *)arg2);
+ error = arch_prctl_get_branch_landing_pad_state(me, (unsigned long __user *)arg2);
break;
case PR_SET_INDIR_BR_LP_STATUS:
if (arg3 || arg4 || arg5)
return -EINVAL;
- error = arch_set_indir_br_lp_status(me, arg2);
+ error = arch_prctl_set_branch_landing_pad_state(me, arg2);
break;
case PR_LOCK_INDIR_BR_LP_STATUS:
- if (arg3 || arg4 || arg5)
+ if (arg2 || arg3 || arg4 || arg5)
return -EINVAL;
- error = arch_lock_indir_br_lp_status(me, arg2);
+ error = arch_prctl_lock_branch_landing_pad_state(me);
break;
default:
trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
` (3 preceding siblings ...)
2026-04-04 1:41 ` [PATCH 4/6] prctl: rename branch landing pad implementation functions to be more explicit Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:41 ` [PATCH 6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive Paul Walmsley
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Deepak Gupta
Similar to the recent change to expand "LP" to "branch landing pad",
let's expand "SS" in the ptrace uapi macros to "shadow stack" as well.
This aligns with the existing prctl() arguments, which use the
expanded "shadow stack" names, rather than just the abbreviation.
Link: https://lore.kernel.org/linux-riscv/CAHk-=whhSLGZAx3N5jJpb4GLFDqH_QvS07D+6BnkPWmCEzTAgw@mail.gmail.com/
Cc: Deepak Gupta <debug@rivosinc.com>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
arch/riscv/include/uapi/asm/ptrace.h | 18 +++++++++---------
arch/riscv/kernel/ptrace.c | 10 +++++-----
tools/testing/selftests/riscv/cfi/cfitests.c | 4 ++--
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/riscv/include/uapi/asm/ptrace.h b/arch/riscv/include/uapi/asm/ptrace.h
index 9985bd58148e..3de2b7124aff 100644
--- a/arch/riscv/include/uapi/asm/ptrace.h
+++ b/arch/riscv/include/uapi/asm/ptrace.h
@@ -135,25 +135,25 @@ struct __sc_riscv_cfi_state {
#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT 0
#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT 1
#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT 2
-#define PTRACE_CFI_SS_EN_BIT 3
-#define PTRACE_CFI_SS_LOCK_BIT 4
-#define PTRACE_CFI_SS_PTR_BIT 5
+#define PTRACE_CFI_SHADOW_STACK_EN_BIT 3
+#define PTRACE_CFI_SHADOW_STACK_LOCK_BIT 4
+#define PTRACE_CFI_SHADOW_STACK_PTR_BIT 5
#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT)
#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE \
_BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT)
#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE \
_BITUL(PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT)
-#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT)
-#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
-#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
+#define PTRACE_CFI_SHADOW_STACK_EN_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_EN_BIT)
+#define PTRACE_CFI_SHADOW_STACK_LOCK_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_LOCK_BIT)
+#define PTRACE_CFI_SHADOW_STACK_PTR_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_PTR_BIT)
#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE | \
PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE | \
- PTRACE_CFI_SS_EN_STATE | \
- PTRACE_CFI_SS_LOCK_STATE | \
- PTRACE_CFI_SS_PTR_STATE)
+ PTRACE_CFI_SHADOW_STACK_EN_STATE | \
+ PTRACE_CFI_SHADOW_STACK_LOCK_STATE | \
+ PTRACE_CFI_SHADOW_STACK_PTR_STATE)
struct __cfi_status {
__u64 cfi_state;
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index b6156625d6f8..93de2e7a3074 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -311,10 +311,10 @@ static int riscv_cfi_get(struct task_struct *target,
}
if (is_shstk_enabled(target)) {
- user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SS_EN_STATE |
- PTRACE_CFI_SS_PTR_STATE);
+ user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SHADOW_STACK_EN_STATE |
+ PTRACE_CFI_SHADOW_STACK_PTR_STATE);
user_cfi.cfi_status.cfi_state |= is_shstk_locked(target) ?
- PTRACE_CFI_SS_LOCK_STATE : 0;
+ PTRACE_CFI_SHADOW_STACK_LOCK_STATE : 0;
user_cfi.shstk_ptr = get_active_shstk(target);
}
@@ -350,7 +350,7 @@ static int riscv_cfi_set(struct task_struct *target,
*/
if ((user_cfi.cfi_status.cfi_state &
(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE |
- PTRACE_CFI_SS_EN_STATE | PTRACE_CFI_SS_LOCK_STATE)) ||
+ PTRACE_CFI_SHADOW_STACK_EN_STATE | PTRACE_CFI_SHADOW_STACK_LOCK_STATE)) ||
(user_cfi.cfi_status.cfi_state & PTRACE_CFI_STATE_INVALID_MASK))
return -EINVAL;
@@ -365,7 +365,7 @@ static int riscv_cfi_set(struct task_struct *target,
/* If shadow stack enabled on target, set new shadow stack pointer */
if (is_shstk_enabled(target) &&
- (user_cfi.cfi_status.cfi_state & PTRACE_CFI_SS_PTR_STATE))
+ (user_cfi.cfi_status.cfi_state & PTRACE_CFI_SHADOW_STACK_PTR_STATE))
set_active_shstk(target, user_cfi.shstk_ptr);
return 0;
diff --git a/tools/testing/selftests/riscv/cfi/cfitests.c b/tools/testing/selftests/riscv/cfi/cfitests.c
index 68374a27ec81..0dac74b8553c 100644
--- a/tools/testing/selftests/riscv/cfi/cfitests.c
+++ b/tools/testing/selftests/riscv/cfi/cfitests.c
@@ -95,8 +95,8 @@ bool cfi_ptrace_test(void)
switch (ptrace_test_num) {
#define CFI_ENABLE_MASK (PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
- PTRACE_CFI_SS_EN_STATE | \
- PTRACE_CFI_SS_PTR_STATE)
+ PTRACE_CFI_SHADOW_STACK_EN_STATE | \
+ PTRACE_CFI_SHADOW_STACK_PTR_STATE)
case 0:
if ((cfi_reg.cfi_status.cfi_state & CFI_ENABLE_MASK) != CFI_ENABLE_MASK)
ksft_exit_fail_msg("%s: ptrace_getregset failed, %llu\n", __func__,
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
` (4 preceding siblings ...)
2026-04-04 1:41 ` [PATCH 5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers Paul Walmsley
@ 2026-04-04 1:41 ` Paul Walmsley
2026-04-04 1:50 ` [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces patchwork-bot+linux-riscv
2026-04-05 0:50 ` patchwork-bot+linux-riscv
7 siblings, 0 replies; 9+ messages in thread
From: Paul Walmsley @ 2026-04-04 1:41 UTC (permalink / raw)
To: linux-riscv, linux-kernel; +Cc: torvalds, tglx, peterz, broonie, Deepak Gupta
Per Linus' comments requesting the replacement of "INDIR_BR_LP" in the
indirect branch tracking prctl()s with something more readable, and
suggesting the use of the speculation control prctl()s as an exemplar,
reimplement the prctl()s and related constants that control per-task
forward-edge control flow integrity.
This primarily involves two changes. First, the prctls are
restructured to resemble the style of the speculative execution
workaround control prctls PR_{GET,SET}_SPECULATION_CTRL, to make them
easier to extend in the future. Second, the "indir_br_lp" abbrevation
is expanded to "branch_landing_pads" to be less telegraphic. The
kselftest and documentation is adjusted accordingly.
Link: https://lore.kernel.org/linux-riscv/CAHk-=whhSLGZAx3N5jJpb4GLFDqH_QvS07D+6BnkPWmCEzTAgw@mail.gmail.com/
Cc: Deepak Gupta <debug@rivosinc.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Paul Walmsley <pjw@kernel.org>
---
Documentation/arch/riscv/zicfilp.rst | 63 ++++++++++++--------
arch/riscv/kernel/usercfi.c | 15 ++---
include/uapi/linux/prctl.h | 37 +++++-------
kernel/sys.c | 23 ++++---
tools/perf/trace/beauty/include/uapi/linux/prctl.h | 36 +++++------
tools/testing/selftests/riscv/cfi/cfitests.c | 4 +
6 files changed, 91 insertions(+), 87 deletions(-)
diff --git a/Documentation/arch/riscv/zicfilp.rst b/Documentation/arch/riscv/zicfilp.rst
index 78a3e01ff68c..ab7d8e62ddaf 100644
--- a/Documentation/arch/riscv/zicfilp.rst
+++ b/Documentation/arch/riscv/zicfilp.rst
@@ -76,34 +76,49 @@ the program.
4. prctl() enabling
--------------------
-:c:macro:`PR_SET_INDIR_BR_LP_STATUS` / :c:macro:`PR_GET_INDIR_BR_LP_STATUS` /
-:c:macro:`PR_LOCK_INDIR_BR_LP_STATUS` are three prctls added to manage indirect
-branch tracking. These prctls are architecture-agnostic and return -EINVAL if
-the underlying functionality is not supported.
+Per-task indirect branch tracking state can be monitored and
+controlled via the :c:macro:`PR_GET_CFI` and :c:macro:`PR_SET_CFI`
+``prctl()` arguments (respectively), by supplying
+:c:macro:`PR_CFI_BRANCH_LANDING_PADS` as the second argument. These
+are architecture-agnostic, and will return -EINVAL if the underlying
+functionality is not supported.
-* prctl(PR_SET_INDIR_BR_LP_STATUS, unsigned long arg)
+* prctl(:c:macro:`PR_SET_CFI`, :c:macro:`PR_CFI_BRANCH_LANDING_PADS`, unsigned long arg)
-If arg1 is :c:macro:`PR_INDIR_BR_LP_ENABLE` and if CPU supports
-``zicfilp`` then the kernel will enable indirect branch tracking for the
-task. The dynamic loader can issue this :c:macro:`prctl` once it has
-determined that all the objects loaded in the address space support
-indirect branch tracking. Additionally, if there is a `dlopen` to an
-object which wasn't compiled with ``zicfilp``, the dynamic loader can
-issue this prctl with arg1 set to 0 (i.e. :c:macro:`PR_INDIR_BR_LP_ENABLE`
-cleared).
-
-* prctl(PR_GET_INDIR_BR_LP_STATUS, unsigned long * arg)
+arg is a bitmask.
-Returns the current status of indirect branch tracking. If enabled
-it'll return :c:macro:`PR_INDIR_BR_LP_ENABLE`
-
-* prctl(PR_LOCK_INDIR_BR_LP_STATUS, unsigned long arg)
+If :c:macro:`PR_CFI_ENABLE` is set in arg, and the CPU supports
+``zicfilp``, then the kernel will enable indirect branch tracking for
+the task. The dynamic loader can issue this ``prctl()`` once it has
+determined that all the objects loaded in the address space support
+indirect branch tracking.
+
+Indirect branch tracking state can also be locked once enabled. This
+prevents the task from subsequently disabling it. This is done by
+setting the bit :c:macro:`PR_CFI_LOCK` in arg. Either indirect branch
+tracking must already be enabled for the task, or the bit
+:c:macro:`PR_CFI_ENABLE` must also be set in arg. This is intended
+for environments that wish to run with a strict security posture that
+do not wish to load objects without ``zicfilp`` support.
+
+Indirect branch tracking can also be disabled for the task, assuming
+that it has not previously been enabled and locked. If there is a
+``dlopen()`` to an object which wasn't compiled with ``zicfilp``, the
+dynamic loader can issue this ``prctl()`` with arg set to
+:c:macro:`PR_CFI_DISABLE`. Disabling indirect branch tracking for the
+task is not possible if it has previously been enabled and locked.
+
+
+* prctl(:c:macro:`PR_GET_CFI`, :c:macro:`PR_CFI_BRANCH_LANDING_PADS`, unsigned long * arg)
+
+Returns the current status of indirect branch tracking into a bitmask
+stored into the memory location pointed to by arg. The bitmask will
+have the :c:macro:`PR_CFI_ENABLE` bit set if indirect branch tracking
+is currently enabled for the task, and if it is locked, will
+additionally have the :c:macro:`PR_CFI_LOCK` bit set. If indirect
+branch tracking is currently disabled for the task, the
+:c:macro:`PR_CFI_DISABLE` bit will be set.
-Locks the current status of indirect branch tracking on the task. User
-space may want to run with a strict security posture and wouldn't want
-loading of objects without ``zicfilp`` support in them, to disallow
-disabling of indirect branch tracking. In this case, user space can
-use this prctl to lock the current settings.
5. violations related to indirect branch tracking
--------------------------------------------------
diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
index 04ab1eb8df29..2c535737511d 100644
--- a/arch/riscv/kernel/usercfi.c
+++ b/arch/riscv/kernel/usercfi.c
@@ -465,16 +465,14 @@ int arch_prctl_get_branch_landing_pad_state(struct task_struct *t,
if (!is_user_lpad_enabled())
return -EINVAL;
- /* indirect branch tracking is enabled on the task or not */
- fcfi_status |= (is_indir_lp_enabled(t) ? PR_INDIR_BR_LP_ENABLE : 0);
+ fcfi_status = (is_indir_lp_enabled(t) ? PR_CFI_ENABLE : PR_CFI_DISABLE);
+ fcfi_status |= (is_indir_lp_locked(t) ? PR_CFI_LOCK : 0);
return copy_to_user(state, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
}
int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state)
{
- bool enable_indir_lp = false;
-
if (!is_user_lpad_enabled())
return -EINVAL;
@@ -482,12 +480,13 @@ int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long
if (is_indir_lp_locked(t))
return -EINVAL;
- /* Reject unknown flags */
- if (state & ~PR_INDIR_BR_LP_ENABLE)
+ if (!(state & (PR_CFI_ENABLE | PR_CFI_DISABLE)))
+ return -EINVAL;
+
+ if (state & PR_CFI_ENABLE && state & PR_CFI_DISABLE)
return -EINVAL;
- enable_indir_lp = (state & PR_INDIR_BR_LP_ENABLE);
- set_indir_lp_status(t, enable_indir_lp);
+ set_indir_lp_status(t, !!(state & PR_CFI_ENABLE));
return 0;
}
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 55b0446fff9d..b6ec6f693719 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -397,30 +397,23 @@ struct prctl_mm_map {
# define PR_RSEQ_SLICE_EXT_ENABLE 0x01
/*
- * Get the current indirect branch tracking configuration for the current
- * thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS.
+ * Get or set the control flow integrity (CFI) configuration for the
+ * current thread.
+ *
+ * Some per-thread control flow integrity settings are not yet
+ * controlled through this prctl(); see for example
+ * PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS
*/
-#define PR_GET_INDIR_BR_LP_STATUS 80
-
+#define PR_GET_CFI 80
+#define PR_SET_CFI 81
/*
- * Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will
- * enable cpu feature for user thread, to track all indirect branches and ensure
- * they land on arch defined landing pad instruction.
- * x86 - If enabled, an indirect branch must land on an ENDBRANCH instruction.
- * arch64 - If enabled, an indirect branch must land on a BTI instruction.
- * riscv - If enabled, an indirect branch must land on an lpad instruction.
- * PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect
- * branches will no more be tracked by cpu to land on arch defined landing pad
- * instruction.
- */
-#define PR_SET_INDIR_BR_LP_STATUS 81
-# define PR_INDIR_BR_LP_ENABLE (1UL << 0)
-
-/*
- * Prevent further changes to the specified indirect branch tracking
- * configuration. All bits may be locked via this call, including
- * undefined bits.
+ * Forward-edge CFI variants (excluding ARM64 BTI, which has its own
+ * prctl()s).
*/
-#define PR_LOCK_INDIR_BR_LP_STATUS 82
+#define PR_CFI_BRANCH_LANDING_PADS 0
+/* Return and control values for PR_{GET,SET}_CFI */
+# define PR_CFI_ENABLE _BITUL(0)
+# define PR_CFI_DISABLE _BITUL(1)
+# define PR_CFI_LOCK _BITUL(2)
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index a5e0c187bbbf..62e842055cc9 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2889,20 +2889,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
return -EINVAL;
error = rseq_slice_extension_prctl(arg2, arg3);
break;
- case PR_GET_INDIR_BR_LP_STATUS:
- if (arg3 || arg4 || arg5)
+ case PR_GET_CFI:
+ if (arg2 != PR_CFI_BRANCH_LANDING_PADS)
return -EINVAL;
- error = arch_prctl_get_branch_landing_pad_state(me, (unsigned long __user *)arg2);
- break;
- case PR_SET_INDIR_BR_LP_STATUS:
- if (arg3 || arg4 || arg5)
+ if (arg4 || arg5)
return -EINVAL;
- error = arch_prctl_set_branch_landing_pad_state(me, arg2);
+ error = arch_prctl_get_branch_landing_pad_state(me, (unsigned long __user *)arg3);
break;
- case PR_LOCK_INDIR_BR_LP_STATUS:
- if (arg2 || arg3 || arg4 || arg5)
+ case PR_SET_CFI:
+ if (arg2 != PR_CFI_BRANCH_LANDING_PADS)
return -EINVAL;
- error = arch_prctl_lock_branch_landing_pad_state(me);
+ if (arg4 || arg5)
+ return -EINVAL;
+ error = arch_prctl_set_branch_landing_pad_state(me, arg3);
+ if (error)
+ break;
+ if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE))
+ error = arch_prctl_lock_branch_landing_pad_state(me);
break;
default:
trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);
diff --git a/tools/perf/trace/beauty/include/uapi/linux/prctl.h b/tools/perf/trace/beauty/include/uapi/linux/prctl.h
index 55b0446fff9d..560f99bc4782 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/prctl.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/prctl.h
@@ -397,30 +397,24 @@ struct prctl_mm_map {
# define PR_RSEQ_SLICE_EXT_ENABLE 0x01
/*
- * Get the current indirect branch tracking configuration for the current
- * thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS.
+ * Get or set the control flow integrity (CFI) configuration for the
+ * current thread.
+ *
+ * Some per-thread control flow integrity settings are not yet
+ * controlled through this prctl(); see for example
+ * PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS
*/
-#define PR_GET_INDIR_BR_LP_STATUS 80
-
+#define PR_GET_CFI 80
+#define PR_SET_CFI 81
/*
- * Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will
- * enable cpu feature for user thread, to track all indirect branches and ensure
- * they land on arch defined landing pad instruction.
- * x86 - If enabled, an indirect branch must land on an ENDBRANCH instruction.
- * arch64 - If enabled, an indirect branch must land on a BTI instruction.
- * riscv - If enabled, an indirect branch must land on an lpad instruction.
- * PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect
- * branches will no more be tracked by cpu to land on arch defined landing pad
- * instruction.
+ * Forward-edge CFI variants (excluding ARM64 BTI, which has its own
+ * prctl()s).
*/
-#define PR_SET_INDIR_BR_LP_STATUS 81
-# define PR_INDIR_BR_LP_ENABLE (1UL << 0)
+#define PR_CFI_BRANCH_LANDING_PADS 0
+/* Return and control values for PR_{GET,SET}_CFI */
+# define PR_CFI_ENABLE _BITUL(0)
+# define PR_CFI_DISABLE _BITUL(1)
+# define PR_CFI_LOCK _BITUL(2)
-/*
- * Prevent further changes to the specified indirect branch tracking
- * configuration. All bits may be locked via this call, including
- * undefined bits.
- */
-#define PR_LOCK_INDIR_BR_LP_STATUS 82
#endif /* _LINUX_PRCTL_H */
diff --git a/tools/testing/selftests/riscv/cfi/cfitests.c b/tools/testing/selftests/riscv/cfi/cfitests.c
index 0dac74b8553c..39d097b6881f 100644
--- a/tools/testing/selftests/riscv/cfi/cfitests.c
+++ b/tools/testing/selftests/riscv/cfi/cfitests.c
@@ -146,11 +146,11 @@ int main(int argc, char *argv[])
* pads for user mode except lighting up a bit in senvcfg via a prctl.
* Enable landing pad support throughout the execution of the test binary.
*/
- ret = my_syscall5(__NR_prctl, PR_GET_INDIR_BR_LP_STATUS, &lpad_status, 0, 0, 0);
+ ret = my_syscall5(__NR_prctl, PR_GET_CFI, PR_CFI_BRANCH_LANDING_PADS, &lpad_status, 0, 0);
if (ret)
ksft_exit_fail_msg("Get landing pad status failed with %d\n", ret);
- if (!(lpad_status & PR_INDIR_BR_LP_ENABLE))
+ if (!(lpad_status & PR_CFI_ENABLE))
ksft_exit_fail_msg("Landing pad is not enabled, should be enabled via glibc\n");
ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &ss_status, 0, 0, 0);
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
` (5 preceding siblings ...)
2026-04-04 1:41 ` [PATCH 6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive Paul Walmsley
@ 2026-04-04 1:50 ` patchwork-bot+linux-riscv
2026-04-05 0:50 ` patchwork-bot+linux-riscv
7 siblings, 0 replies; 9+ messages in thread
From: patchwork-bot+linux-riscv @ 2026-04-04 1:50 UTC (permalink / raw)
To: Paul Walmsley; +Cc: linux-riscv, linux-kernel, torvalds, tglx, peterz, broonie
Hello:
This series was applied to riscv/linux.git (for-next)
by Paul Walmsley <pjw@kernel.org>:
On Fri, 3 Apr 2026 19:40:56 -0600 you wrote:
> Restructure the per-task CFI indirect branch landing pad prctl()
> interface, as suggested by Linus [1]. In place of the current
> approach, which follows the style of shadow stack control prctl()s
> (PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS), adopt the style of the
> speculation control prctl() constants (PR_{GET,SET}_SPECULATION_CTRL).
>
> Then, to improve readability, expand "indir_br_lp", "lpad", and
> related abbreviations in the interfaces, also as requested by Linus.
> While here, expand "ss" in the shadow stack ptrace macros to "shadow
> stack".
>
> [...]
Here is the summary with links:
- [1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header
(no matching commit)
- [2/6] riscv: cfi: clear CFI lock status in start_thread()
(no matching commit)
- [3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers
(no matching commit)
- [4/6] prctl: rename branch landing pad implementation functions to be more explicit
https://git.kernel.org/riscv/c/987bd38dee75
- [5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers
https://git.kernel.org/riscv/c/c8acc707f48c
- [6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive
https://git.kernel.org/riscv/c/e0d96d3c63f5
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
` (6 preceding siblings ...)
2026-04-04 1:50 ` [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces patchwork-bot+linux-riscv
@ 2026-04-05 0:50 ` patchwork-bot+linux-riscv
7 siblings, 0 replies; 9+ messages in thread
From: patchwork-bot+linux-riscv @ 2026-04-05 0:50 UTC (permalink / raw)
To: Paul Walmsley; +Cc: linux-riscv, linux-kernel, torvalds, tglx, peterz, broonie
Hello:
This series was applied to riscv/linux.git (fixes)
by Paul Walmsley <pjw@kernel.org>:
On Fri, 3 Apr 2026 19:40:56 -0600 you wrote:
> Restructure the per-task CFI indirect branch landing pad prctl()
> interface, as suggested by Linus [1]. In place of the current
> approach, which follows the style of shadow stack control prctl()s
> (PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS), adopt the style of the
> speculation control prctl() constants (PR_{GET,SET}_SPECULATION_CTRL).
>
> Then, to improve readability, expand "indir_br_lp", "lpad", and
> related abbreviations in the interfaces, also as requested by Linus.
> While here, expand "ss" in the shadow stack ptrace macros to "shadow
> stack".
>
> [...]
Here is the summary with links:
- [1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header
https://git.kernel.org/riscv/c/a621d9cdc8d0
- [2/6] riscv: cfi: clear CFI lock status in start_thread()
https://git.kernel.org/riscv/c/a6ede084c4b7
- [3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers
https://git.kernel.org/riscv/c/ac4e61c730d7
- [4/6] prctl: rename branch landing pad implementation functions to be more explicit
(no matching commit)
- [5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers
(no matching commit)
- [6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive
(no matching commit)
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-04-05 0:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-04 1:40 [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces Paul Walmsley
2026-04-04 1:41 ` [PATCH 1/6] riscv: ptrace: cfi: fix "PRACE" typo in uapi header Paul Walmsley
2026-04-04 1:41 ` [PATCH 2/6] riscv: cfi: clear CFI lock status in start_thread() Paul Walmsley
2026-04-04 1:41 ` [PATCH 3/6] riscv: ptrace: expand "LP" references to "branch landing pads" in uapi headers Paul Walmsley
2026-04-04 1:41 ` [PATCH 4/6] prctl: rename branch landing pad implementation functions to be more explicit Paul Walmsley
2026-04-04 1:41 ` [PATCH 5/6] riscv: ptrace: cfi: expand "SS" references to "shadow stack" in uapi headers Paul Walmsley
2026-04-04 1:41 ` [PATCH 6/6] prctl: cfi: change the branch landing pad prctl()s to be more descriptive Paul Walmsley
2026-04-04 1:50 ` [PATCH 0/6] Restructure per-task CFI prctl() and ptrace interfaces patchwork-bot+linux-riscv
2026-04-05 0:50 ` patchwork-bot+linux-riscv
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox