arch/riscv/kernel/usercfi.c
Source file repositories/reference/linux-study-clean/arch/riscv/kernel/usercfi.c
File Facts
- System
- Linux kernel
- Corpus path
arch/riscv/kernel/usercfi.c- Extension
.c- Size
- 14788 bytes
- Lines
- 536
- Domain
- Architecture Layer
- Bucket
- arch/riscv
- Inferred role
- Architecture Layer: syscall or user/kernel boundary
- Status
- core implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Defines or participates in a user/kernel boundary; inspect argument validation, copy_from_user/copy_to_user, credentials, and dispatch target.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/sched.hlinux/bitops.hlinux/types.hlinux/mm.hlinux/mman.hlinux/uaccess.hlinux/sizes.hlinux/user.hlinux/syscalls.hlinux/prctl.hasm/csr.hasm/usercfi.h
Detected Declarations
syscall map_shadow_stackfunction is_shstk_enabledfunction is_shstk_allocatedfunction is_shstk_lockedfunction set_shstk_basefunction get_shstk_basefunction set_active_shstkfunction get_active_shstkfunction set_shstk_statusfunction set_shstk_lockfunction is_indir_lp_enabledfunction is_indir_lp_lockedfunction set_indir_lp_statusfunction set_indir_lp_lockfunction calc_shstk_sizefunction amo_user_shstkfunction create_rstor_tokenfunction save_user_shstkfunction restore_user_shstkfunction allocate_shadow_stackfunction neededfunction shstk_releasefunction arch_get_shadow_stack_statusfunction arch_set_shadow_stack_statusfunction arch_lock_shadow_stack_statusfunction arch_prctl_get_branch_landing_pad_statefunction arch_prctl_set_branch_landing_pad_statefunction arch_prctl_lock_branch_landing_pad_statefunction is_user_shstk_enabledfunction is_user_lpad_enabledfunction setup_global_riscv_enable
Annotated Snippet
SYSCALL_DEFINE3(map_shadow_stack, unsigned long, addr, unsigned long, size, unsigned int, flags)
{
bool set_tok = flags & SHADOW_STACK_SET_TOKEN;
unsigned long aligned_size = 0;
if (!is_user_shstk_enabled())
return -EOPNOTSUPP;
/* Anything other than set token should result in invalid param */
if (flags & ~SHADOW_STACK_SET_TOKEN)
return -EINVAL;
/*
* Unlike other architectures, on RISC-V, SSP pointer is held in CSR_SSP and is an available
* CSR in all modes. CSR accesses are performed using 12bit index programmed in instruction
* itself. This provides static property on register programming and writes to CSR can't
* be unintentional from programmer's perspective. As long as programmer has guarded areas
* which perform writes to CSR_SSP properly, shadow stack pivoting is not possible. Since
* CSR_SSP is writable by user mode, it itself can setup a shadow stack token subsequent
* to allocation. Although in order to provide portablity with other architectures (because
* `map_shadow_stack` is arch agnostic syscall), RISC-V will follow expectation of a token
* flag in flags and if provided in flags, will setup a token at the base.
*/
/* If there isn't space for a token */
if (set_tok && size < SHSTK_ENTRY_SIZE)
return -ENOSPC;
if (addr && (addr & (PAGE_SIZE - 1)))
return -EINVAL;
aligned_size = PAGE_ALIGN(size);
if (aligned_size < size)
return -EOVERFLOW;
return allocate_shadow_stack(addr, aligned_size, size, set_tok);
}
/*
* This gets called during clone/clone3/fork. And is needed to allocate a shadow stack for
* cases where CLONE_VM is specified and thus a different stack is specified by user. We
* thus need a separate shadow stack too. How a separate shadow stack is specified by
* user is still being debated. Once that's settled, remove this part of the comment.
* This function simply returns 0 if shadow stacks are not supported or if separate shadow
* stack allocation is not needed (like in case of !CLONE_VM)
*/
unsigned long shstk_alloc_thread_stack(struct task_struct *tsk,
const struct kernel_clone_args *args)
{
unsigned long addr, size;
/* If shadow stack is not supported, return 0 */
if (!is_user_shstk_enabled())
return 0;
/*
* If shadow stack is not enabled on the new thread, skip any
* switch to a new shadow stack.
*/
if (!is_shstk_enabled(tsk))
return 0;
/*
* For CLONE_VFORK the child will share the parents shadow stack.
* Set base = 0 and size = 0, this is special means to track this state
* so the freeing logic run for child knows to leave it alone.
*/
if (args->flags & CLONE_VFORK) {
set_shstk_base(tsk, 0, 0);
return 0;
}
/*
* For !CLONE_VM the child will use a copy of the parents shadow
* stack.
*/
if (!(args->flags & CLONE_VM))
return 0;
/*
* reaching here means, CLONE_VM was specified and thus a separate shadow
* stack is needed for new cloned thread. Note: below allocation is happening
* using current mm.
*/
size = calc_shstk_size(args->stack_size);
addr = allocate_shadow_stack(0, size, 0, false);
if (IS_ERR_VALUE(addr))
return addr;
set_shstk_base(tsk, addr, size);
Annotation
- Immediate include surface: `linux/sched.h`, `linux/bitops.h`, `linux/types.h`, `linux/mm.h`, `linux/mman.h`, `linux/uaccess.h`, `linux/sizes.h`, `linux/user.h`.
- Detected declarations: `syscall map_shadow_stack`, `function is_shstk_enabled`, `function is_shstk_allocated`, `function is_shstk_locked`, `function set_shstk_base`, `function get_shstk_base`, `function set_active_shstk`, `function get_active_shstk`, `function set_shstk_status`, `function set_shstk_lock`.
- Atlas domain: Architecture Layer / arch/riscv.
- Implementation status: core implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.