mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-31 14:38:21 +00:00
x86-64: enable smep and smap
This commit is contained in:
@@ -12,6 +12,11 @@
|
||||
#include <arch/prof.h>
|
||||
|
||||
#define EFER_SYSCALLENABLE 1
|
||||
#define CR4_SMEP (1 << 20)
|
||||
#define CR4_SMAP (1 << 21)
|
||||
|
||||
static bool has_smap;
|
||||
static bool has_smap_detected;
|
||||
|
||||
void arch_syscall_entry();
|
||||
static void illisr(isr_t *self, context_t *ctx) {
|
||||
@@ -61,6 +66,55 @@ static void reload_ldt(isr_t *self, context_t *ctx) {
|
||||
arch_ldt_invalidate();
|
||||
}
|
||||
|
||||
static void enable_smep_if_available(void) {
|
||||
if (cpuid_base_max_leaf() < 7)
|
||||
return;
|
||||
|
||||
cpuid_results_t results;
|
||||
cpuid_with_ecx(7, 0, &results);
|
||||
if ((results.ebx & CPUID_LEAF_7_EBX_SMEP) == 0)
|
||||
return;
|
||||
|
||||
uint64_t cr4;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(cr4));
|
||||
cr4 |= CR4_SMEP;
|
||||
asm volatile("mov %0, %%cr4" : : "r"(cr4) : "memory");
|
||||
}
|
||||
|
||||
static bool detect_smap(void) {
|
||||
if (cpuid_base_max_leaf() < 7)
|
||||
return false;
|
||||
|
||||
cpuid_results_t results;
|
||||
cpuid_with_ecx(7, 0, &results);
|
||||
return results.ebx & CPUID_LEAF_7_EBX_SMAP;
|
||||
}
|
||||
|
||||
static void enable_smap_if_available(void) {
|
||||
if (!has_smap_detected) {
|
||||
has_smap = detect_smap();
|
||||
has_smap_detected = true;
|
||||
}
|
||||
|
||||
if (!has_smap)
|
||||
return;
|
||||
|
||||
uint64_t cr4;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(cr4));
|
||||
cr4 |= CR4_SMAP;
|
||||
asm volatile("mov %0, %%cr4" : : "r"(cr4) : "memory");
|
||||
}
|
||||
|
||||
void arch_cpu_user_access_begin(void) {
|
||||
if (has_smap)
|
||||
asm volatile("stac" : : : "memory");
|
||||
}
|
||||
|
||||
void arch_cpu_user_access_end(void) {
|
||||
if (has_smap)
|
||||
asm volatile("clac" : : : "memory");
|
||||
}
|
||||
|
||||
void arch_nmi_isr(context_t *ctx) {
|
||||
// we are in an NMI context, running on IST0
|
||||
// first load the proper gsbase to get access to cpu-local variables.
|
||||
@@ -227,6 +281,8 @@ void arch_cpu_init() {
|
||||
);
|
||||
|
||||
x86_64_mmu_enable_global_pages();
|
||||
enable_smep_if_available();
|
||||
enable_smap_if_available();
|
||||
|
||||
// register some exception handlers that give out signals
|
||||
interrupt_register(0, sigfpeisr, NULL, IPL_IGNORE);
|
||||
|
||||
@@ -324,7 +324,14 @@ static volatile struct limine_executable_address_request kaddrreq = {
|
||||
#define ERROR_FETCH 16
|
||||
|
||||
static void pfisr(isr_t *self, context_t *ctx) {
|
||||
if ((ctx->rflags & ARCH_CONTEXT_RFLAGS_AC) == 0 && IS_USER_ADDRESS((void *)ctx->cr2) && !IS_USER_ADDRESS((void *)ctx->rip)) {
|
||||
_panic("SMAP/SMEP violation", ctx);
|
||||
}
|
||||
|
||||
thread_t *thread = current_thread();
|
||||
if (thread && thread->usercopyctx)
|
||||
arch_cpu_user_access_end();
|
||||
|
||||
interrupt_set(true);
|
||||
int vmmerror = 0;
|
||||
|
||||
@@ -338,6 +345,7 @@ static void pfisr(isr_t *self, context_t *ctx) {
|
||||
if (vmm_pagefault((void *)ctx->cr2, ctx->cs != 8, vmmerror) == false) {
|
||||
if (thread && thread->usercopyctx) {
|
||||
memcpy(ctx, thread->usercopyctx, sizeof(context_t));
|
||||
ctx->rflags &= ~ARCH_CONTEXT_RFLAGS_AC;
|
||||
thread->usercopyctx = NULL;
|
||||
CTX_RET(ctx) = EFAULT;
|
||||
} else if (ARCH_CONTEXT_ISUSER(ctx)) {
|
||||
@@ -361,7 +369,9 @@ static void gpfisr(isr_t *self, context_t *ctx) {
|
||||
|
||||
thread_t *thread = current_thread();
|
||||
if (thread && thread->usercopyctx) {
|
||||
arch_cpu_user_access_end();
|
||||
memcpy(ctx, thread->usercopyctx, sizeof(context_t));
|
||||
ctx->rflags &= ~ARCH_CONTEXT_RFLAGS_AC;
|
||||
thread->usercopyctx = NULL;
|
||||
CTX_RET(ctx) = EFAULT;
|
||||
} else if (ARCH_CONTEXT_ISUSER(ctx)) {
|
||||
|
||||
Reference in New Issue
Block a user