x86-64: enable smep and smap

This commit is contained in:
Matheus
2026-04-23 15:29:43 -03:00
parent b0542a165c
commit 71dd6d1125
9 changed files with 100 additions and 4 deletions
+56
View File
@@ -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);
+10
View File
@@ -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)) {