SYSCALL_DEFINE3(map_shadow_stack, unsignedlong, addr, unsignedlong, size, unsignedint, flags)
{ unsignedlong alloc_size; unsignedlong __user *cap_ptr; unsignedlong cap_val; int ret = 0; int cap_offset;
if (!system_supports_gcs()) return -EOPNOTSUPP;
if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER)) return -EINVAL;
if (!PAGE_ALIGNED(addr)) return -EINVAL;
if (size == 8 || !IS_ALIGNED(size, 8)) return -EINVAL;
/* * An overflow would result in attempting to write the restore token * to the wrong location. Not catastrophic, but just return the right * error code and block it.
*/
alloc_size = PAGE_ALIGN(size); if (alloc_size < size) return -EOVERFLOW;
addr = alloc_gcs(addr, alloc_size); if (IS_ERR_VALUE(addr)) return addr;
/* * Put a cap token at the end of the allocated region so it * can be switched to.
*/ if (flags & SHADOW_STACK_SET_TOKEN) { /* Leave an extra empty frame as a top of stack marker? */ if (flags & SHADOW_STACK_SET_MARKER)
cap_offset = 2; else
cap_offset = 1;
/* * Ensure the new cap is ordered before standard * memory accesses to the same location.
*/
gcsb_dsync();
}
return addr;
}
/* * Apply the GCS mode configured for the specified task to the * hardware.
*/ void gcs_set_el0_mode(struct task_struct *task)
{
u64 gcscre0_el1 = GCSCRE0_EL1_nTR;
if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE)
gcscre0_el1 |= GCSCRE0_EL1_RVCHKEN | GCSCRE0_EL1_PCRSEL;
if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_WRITE)
gcscre0_el1 |= GCSCRE0_EL1_STREn;
if (task->thread.gcs_el0_mode & PR_SHADOW_STACK_PUSH)
gcscre0_el1 |= GCSCRE0_EL1_PUSHMEn;
write_sysreg_s(gcscre0_el1, SYS_GCSCRE0_EL1);
}
void gcs_free(struct task_struct *task)
{ if (!system_supports_gcs()) return;
if (!task->mm || task->mm != current->mm) return;
if (task->thread.gcs_base)
vm_munmap(task->thread.gcs_base, task->thread.gcs_size);
ret = gcs_check_locked(task, arg); if (ret != 0) return ret;
/* If we are enabling GCS then make sure we have a stack */ if (arg & PR_SHADOW_STACK_ENABLE &&
!task_gcs_el0_enabled(task)) { /* Do not allow GCS to be reenabled */ if (task->thread.gcs_base || task->thread.gcspr_el0) return -EINVAL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.