Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

riscv: cfi: clear CFI lock status in start_thread()

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>

authored by

Zong Li and committed by
Paul Walmsley
a6ede084 a621d9cd

+12 -10
+4 -4
arch/riscv/include/asm/usercfi.h
··· 39 39 bool is_shstk_enabled(struct task_struct *task); 40 40 bool is_shstk_locked(struct task_struct *task); 41 41 bool is_shstk_allocated(struct task_struct *task); 42 - void set_shstk_lock(struct task_struct *task); 42 + void set_shstk_lock(struct task_struct *task, bool lock); 43 43 void set_shstk_status(struct task_struct *task, bool enable); 44 44 unsigned long get_active_shstk(struct task_struct *task); 45 45 int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr); ··· 47 47 bool is_indir_lp_enabled(struct task_struct *task); 48 48 bool is_indir_lp_locked(struct task_struct *task); 49 49 void set_indir_lp_status(struct task_struct *task, bool enable); 50 - void set_indir_lp_lock(struct task_struct *task); 50 + void set_indir_lp_lock(struct task_struct *task, bool lock); 51 51 52 52 #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE) 53 53 ··· 69 69 70 70 #define is_shstk_allocated(task) false 71 71 72 - #define set_shstk_lock(task) do {} while (0) 72 + #define set_shstk_lock(task, lock) do {} while (0) 73 73 74 74 #define set_shstk_status(task, enable) do {} while (0) 75 75 ··· 79 79 80 80 #define set_indir_lp_status(task, enable) do {} while (0) 81 81 82 - #define set_indir_lp_lock(task) do {} while (0) 82 + #define set_indir_lp_lock(task, lock) do {} while (0) 83 83 84 84 #define restore_user_shstk(tsk, shstk_ptr) -EINVAL 85 85
+2
arch/riscv/kernel/process.c
··· 160 160 * clear shadow stack state on exec. 161 161 * libc will set it later via prctl. 162 162 */ 163 + set_shstk_lock(current, false); 163 164 set_shstk_status(current, false); 164 165 set_shstk_base(current, 0, 0); 165 166 set_active_shstk(current, 0); ··· 168 167 * disable indirect branch tracking on exec. 169 168 * libc will enable it later via prctl. 170 169 */ 170 + set_indir_lp_lock(current, false); 171 171 set_indir_lp_status(current, false); 172 172 173 173 #ifdef CONFIG_64BIT
+6 -6
arch/riscv/kernel/usercfi.c
··· 74 74 csr_write(CSR_ENVCFG, task->thread.envcfg); 75 75 } 76 76 77 - void set_shstk_lock(struct task_struct *task) 77 + void set_shstk_lock(struct task_struct *task, bool lock) 78 78 { 79 - task->thread_info.user_cfi_state.ubcfi_locked = 1; 79 + task->thread_info.user_cfi_state.ubcfi_locked = lock; 80 80 } 81 81 82 82 bool is_indir_lp_enabled(struct task_struct *task) ··· 104 104 csr_write(CSR_ENVCFG, task->thread.envcfg); 105 105 } 106 106 107 - void set_indir_lp_lock(struct task_struct *task) 107 + void set_indir_lp_lock(struct task_struct *task, bool lock) 108 108 { 109 - task->thread_info.user_cfi_state.ufcfi_locked = 1; 109 + task->thread_info.user_cfi_state.ufcfi_locked = lock; 110 110 } 111 111 /* 112 112 * If size is 0, then to be compatible with regular stack we want it to be as big as ··· 452 452 !is_shstk_enabled(task) || arg != 0) 453 453 return -EINVAL; 454 454 455 - set_shstk_lock(task); 455 + set_shstk_lock(task, true); 456 456 457 457 return 0; 458 458 } ··· 502 502 !is_indir_lp_enabled(task) || arg != 0) 503 503 return -EINVAL; 504 504 505 - set_indir_lp_lock(task); 505 + set_indir_lp_lock(task, true); 506 506 507 507 return 0; 508 508 }