Skip to content

Commit

Permalink
kernel/cpu: enable SMAP
Browse files Browse the repository at this point in the history
Enable SMAP if supported.

If supported, SMAP is enabled if CR4.SMAP bit is set, and if RFLAGS.AC is
unset.
It means that we need to clear RFLAGS.AC in entries, to have the kernel
running with RFLAGS.AC = 0.

Two asm macros (asm_clac and asn_stac) have been created to respectively
clear and set RFLAGS.AC from assembly. Two Rust functions have also been
created to perform exactly the same but from Rust code. This is still unused
but it will will be useful when we'll have CPL3 support, to be able to
read/write in userspace (eg. in syscall handlers, or even with user #VC).

Signed-off-by: Thomas Leroy <[email protected]>
  • Loading branch information
p4zuu committed Oct 8, 2024
1 parent 2b23105 commit d259f88
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 3 deletions.
1 change: 1 addition & 0 deletions kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ default = []
enable-gdb = ["dep:gdbstub", "dep:gdbstub_arch"]
mstpm = ["dep:libmstpm"]
nosmep = []
nosmap = []

[dev-dependencies]

Expand Down
7 changes: 6 additions & 1 deletion kernel/src/cpu/control_regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use super::features::cpu_has_pge;
use crate::address::{Address, PhysAddr};
use crate::cpu::features::cpu_has_smep;
use crate::cpu::features::{cpu_has_smap, cpu_has_smep};
use crate::platform::SvsmPlatform;
use bitflags::bitflags;
use core::arch::asm;
Expand Down Expand Up @@ -38,6 +38,11 @@ pub fn cr4_init(platform: &dyn SvsmPlatform) {
cr4.insert(CR4Flags::SMEP);
}

if !cfg!(feature = "nosmap") {
assert!(cpu_has_smap(platform), "CPU does not support SMAP");
cr4.insert(CR4Flags::SMAP);
}

write_cr4(cr4);
}

Expand Down
10 changes: 10 additions & 0 deletions kernel/src/cpu/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::platform::SvsmPlatform;
const X86_FEATURE_NX: u32 = 20;
const X86_FEATURE_PGE: u32 = 13;
const X86_FEATURE_SMEP: u32 = 7;
const X86_FEATURE_SMAP: u32 = 20;

pub fn cpu_has_nx(platform: &dyn SvsmPlatform) -> bool {
let ret = platform.cpuid(0x80000001);
Expand Down Expand Up @@ -36,3 +37,12 @@ pub fn cpu_has_smep(platform: &dyn SvsmPlatform) -> bool {
Some(c) => (c.ebx >> X86_FEATURE_SMEP & 1) == 1,
}
}

pub fn cpu_has_smap(platform: &dyn SvsmPlatform) -> bool {
let ret = platform.cpuid(0x0000_0007);

match ret {
None => false,
Some(c) => (c.ebx >> X86_FEATURE_SMAP & 1) == 1,
}
}
6 changes: 6 additions & 0 deletions kernel/src/cpu/idt/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ HV_DOORBELL_ADDR:
.macro default_entry_no_ist name: req handler:req error_code:req vector:req
.globl asm_entry_\name
asm_entry_\name:
asm_clac

.if \error_code == 0
pushq $0
.endif
Expand All @@ -47,6 +49,8 @@ asm_entry_\name:
.macro irq_entry name:req vector:req
.globl asm_entry_irq_\name
asm_entry_irq_\name:
asm_clac

pushq $0
push_regs
movl $\vector, %edi
Expand Down Expand Up @@ -78,6 +82,8 @@ asm_entry_irq_\name:
// exception.
.globl asm_entry_hv
asm_entry_hv:
asm_clac

// Push a dummy error code, and only three registers. If no #HV
// processing is required, then only these three registers will need to
// be popped.
Expand Down
12 changes: 10 additions & 2 deletions kernel/src/cpu/idt/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::cpu::X86ExceptionContext;
use crate::debug::gdbstub::svsm_gdbstub::handle_debug_exception;
use crate::platform::SVSM_PLATFORM;
use crate::task::{is_task_fault, terminate};

use core::arch::global_asm;

use crate::syscall::*;
Expand Down Expand Up @@ -265,4 +264,13 @@ pub extern "C" fn common_isr_handler(_vector: usize) {
SVSM_PLATFORM.as_dyn_ref().eoi();
}

global_asm!(include_str!("entry.S"), options(att_syntax));
global_asm!(
r#"
.set const_false, 0
.set const_true, 1
"#,
concat!(".set CFG_NOSMAP, const_", cfg!(feature = "nosmap")),
include_str!("../x86/smap.S"),
include_str!("entry.S"),
options(att_syntax)
);
1 change: 1 addition & 0 deletions kernel/src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod tlb;
pub mod tss;
pub mod vc;
pub mod vmsa;
pub mod x86;

pub use apic::LocalApic;
pub use gdt::{gdt, gdt_mut};
Expand Down
7 changes: 7 additions & 0 deletions kernel/src/cpu/x86/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2024 SUSE LLC
//
// Authors: Thomas Leroy <[email protected]>

pub mod smap;
20 changes: 20 additions & 0 deletions kernel/src/cpu/x86/smap.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2024 SUSE LLC
//
// Authors: Thomas Leroy <[email protected]>

.code64

.section .text
.macro asm_clac
.if !CFG_NOSMAP
clac
.endif
.endm

.macro asm_stac
.if !CFG_NOSMAP
stac
.endif
.endm
27 changes: 27 additions & 0 deletions kernel/src/cpu/x86/smap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2024 SUSE LLC
//
// Authors: Thomas Leroy <[email protected]>

use core::arch::asm;

/// Clears RFLAGS.AC to enable SMAP.
/// This is currently only used when SMAP is supported and enabled.
/// SMAP protection is effective only if CR4.SMAP is set and if RFLAGS.AC = 0.
#[inline(always)]
pub fn clac() {
if !cfg!(feature = "nosmap") {
unsafe { asm!("clac", options(att_syntax, nomem, nostack, preserves_flags)) }
}
}

/// Sets RFLAGS.AC to disable SMAP.
/// This is currently only used when SMAP is supported and enabled.
/// SMAP protection is effective only if CR4.SMAP is set and if RFLAGS.AC = 0.
#[inline(always)]
pub fn stac() {
if !cfg!(feature = "nosmap") {
unsafe { asm!("stac", options(att_syntax, nomem, nostack, preserves_flags)) }
}
}

0 comments on commit d259f88

Please sign in to comment.