diff --git a/aero.py b/aero.py
index 4fef1ad123c..de2b7637483 100755
--- a/aero.py
+++ b/aero.py
@@ -470,11 +470,11 @@ def run_in_emulator(args, iso_path):
print("Running with KVM acceleration enabled")
if platform.system() == 'Darwin':
- qemu_args += ['-accel', 'hvf', '-cpu', 'qemu64,+la57' if args.la57 else 'qemu64']
+ qemu_args += ['-accel', 'hvf', '-cpu', 'qemu64,+la57,+smap,+smep,+umip' if args.la57 else 'qemu64,+smap,+smep,+umip']
else:
- qemu_args += ['-enable-kvm', '-cpu', 'host,+la57' if args.la57 else 'host']
+ qemu_args += ['-enable-kvm', '-cpu', 'host,+la57,+smap,+smep,+umip' if args.la57 else 'host,+smap,+smep,+umip']
else:
- qemu_args += ["-cpu", "qemu64,+la57" if args.la57 else "qemu64"]
+ qemu_args += ["-cpu", "qemu64,+la57,+smap,+smep,+umip" if args.la57 else "qemu64,+smap,+smep,+umip"]
run_command(['qemu-system-x86_64', *qemu_args])
diff --git a/bootstrap.yml b/bootstrap.yml
index 1aacef0a1ba..3aba7989d61 100644
--- a/bootstrap.yml
+++ b/bootstrap.yml
@@ -236,9 +236,9 @@ tools:
# -g blows up the binary size.
- 'CFLAGS=-pipe'
compile:
- - args: ['make', '-j@PARALLELISM@']
+ - args: ['make', '-j@PARALLELISM@', 'all-binutils', 'all-gas', 'all-ld']
install:
- - args: ['make', 'install']
+ - args: ['make', 'install-binutils', 'install-gas', 'install-ld']
- name: host-gcc
from_source: gcc
diff --git a/src/aero_kernel/src/arch/x86_64/controlregs.rs b/src/aero_kernel/src/arch/x86_64/controlregs.rs
index d8663b1bd86..5c3911f638d 100644
--- a/src/aero_kernel/src/arch/x86_64/controlregs.rs
+++ b/src/aero_kernel/src/arch/x86_64/controlregs.rs
@@ -17,6 +17,8 @@
* along with Aero. If not, see .
*/
+use core::sync::atomic::{AtomicUsize, Ordering};
+
use crate::mem::paging::{PhysAddr, PhysFrame, VirtAddr};
bitflags::bitflags! {
@@ -273,3 +275,34 @@ pub fn read_cr2() -> VirtAddr {
VirtAddr::new(value)
}
}
+
+/// Returns true if Supervisor Mode Access Prevention (SMAP) is supported by the CPU and is enabled in Cr4.
+#[inline]
+pub fn smap_enabled() -> bool {
+ read_cr4().contains(Cr4Flags::SUPERVISOR_MODE_ACCESS_PREVENTION)
+}
+
+#[inline]
+pub fn with_userspace_access(f: F) -> R
+where
+ F: FnOnce() -> R,
+{
+ static REF_COUNT: AtomicUsize = AtomicUsize::new(0);
+ if smap_enabled() {
+ unsafe {
+ asm!("stac");
+ }
+ REF_COUNT.fetch_add(1, Ordering::Acquire);
+ };
+ let r = f();
+ if smap_enabled() {
+ REF_COUNT.fetch_sub(1, Ordering::Release);
+
+ if REF_COUNT.load(Ordering::Relaxed) == 0 {
+ unsafe {
+ asm!("clac");
+ }
+ }
+ };
+ r
+}
diff --git a/src/aero_kernel/src/arch/x86_64/interrupts/exceptions.rs b/src/aero_kernel/src/arch/x86_64/interrupts/exceptions.rs
index 0b8c16ce424..4eea3c55553 100644
--- a/src/aero_kernel/src/arch/x86_64/interrupts/exceptions.rs
+++ b/src/aero_kernel/src/arch/x86_64/interrupts/exceptions.rs
@@ -97,6 +97,23 @@ pub(super) fn page_fault(stack: &mut InterruptErrorStack) {
log::error!("stack: {:#x?}", stack);
};
+ if reason.contains(PageFaultErrorCode::PROTECTION_VIOLATION) && !reason.contains(PageFaultErrorCode::USER_MODE) {
+ if controlregs::smap_enabled() {
+ unwind::prepare_panic();
+
+ log::error!("SMAP violation page fault");
+ print_info();
+
+ controlregs::with_userspace_access(||unwind::unwind_stack_trace());
+
+ unsafe {
+ loop {
+ super::halt();
+ }
+ }
+ }
+ }
+
if accessed_address < userland_last_address && scheduler::is_initialized()
|| stack.stack.iret.is_user()
{
@@ -130,7 +147,7 @@ pub(super) fn page_fault(stack: &mut InterruptErrorStack) {
scheduler::get_scheduler().log_ptable();
}
- unwind::unwind_stack_trace();
+ controlregs::with_userspace_access(||unwind::unwind_stack_trace());
let task = scheduler::get_scheduler().current_task();
task.signal(aero_syscall::signal::SIGSEGV);
@@ -147,7 +164,7 @@ pub(super) fn page_fault(stack: &mut InterruptErrorStack) {
log::error!("Page fault");
print_info();
- unwind::unwind_stack_trace();
+ controlregs::with_userspace_access(||unwind::unwind_stack_trace());
unsafe {
loop {
diff --git a/src/aero_kernel/src/arch/x86_64/mod.rs b/src/aero_kernel/src/arch/x86_64/mod.rs
index d26b478b0d9..2fb8293ed3b 100644
--- a/src/aero_kernel/src/arch/x86_64/mod.rs
+++ b/src/aero_kernel/src/arch/x86_64/mod.rs
@@ -146,9 +146,6 @@ extern "C" fn x86_64_aero_main(boot_info: &'static StivaleStruct) -> ! {
.unwrap()
});
- // Initialize the CPU specific features.
- init_cpu();
-
// We initialize the COM ports before doing anything else.
//
// This will help printing panics and logs before or when the debug renderer
@@ -156,6 +153,9 @@ extern "C" fn x86_64_aero_main(boot_info: &'static StivaleStruct) -> ! {
drivers::uart_16550::init();
logger::init();
+ // Initialize the CPU specific features.
+ init_cpu();
+
// Parse the kernel command line.
let command_line: &'static _ = boot_info.command_line().map_or("", |cmd| unsafe {
let cmdline = PhysAddr::new(cmd.command_line).as_hhdm_virt();
@@ -251,13 +251,50 @@ pub fn init_cpu() {
cr0.remove(controlregs::Cr0Flags::EMULATE_COPROCESSOR);
cr0.insert(controlregs::Cr0Flags::MONITOR_COPROCESSOR);
+ cr0.insert(controlregs::Cr0Flags::WRITE_PROTECT);
controlregs::write_cr0(cr0);
}
{
+ // Check if SMAP is supported.
+ let has_smap = CpuId::new()
+ .get_extended_feature_info()
+ .map_or(false, |i| i.has_smap());
+
+ // Check if SMEP is supported.
+ let has_smep = CpuId::new()
+ .get_extended_feature_info()
+ .map_or(false, |i| i.has_smep());
+
+ // Check if UMIP is supported.
+ let has_umip = CpuId::new()
+ .get_extended_feature_info()
+ .map_or(false, |i| i.has_umip());
+
let mut cr4 = controlregs::read_cr4();
+ if has_smap {
+ log::info!("SMAP is supported, enabling SMAP.");
+ cr4.insert(controlregs::Cr4Flags::SUPERVISOR_MODE_ACCESS_PREVENTION);
+ } else {
+ log::info!("SMAP is not supported.");
+ }
+
+ if has_smep {
+ log::info!("SMEP is supported, enabling SMEP.");
+ cr4.insert(controlregs::Cr4Flags::SUPERVISOR_MODE_EXECUTION_PROTECTION);
+ } else {
+ log::info!("SMEP is not supported.");
+ }
+
+ if has_umip {
+ log::info!("UMIP is supported, enabling UMIP.");
+ cr4.insert(controlregs::Cr4Flags::USER_MODE_INSTRUCTION_PREVENTION);
+ } else {
+ log::info!("UMIP is not supported.");
+ }
+
cr4.insert(controlregs::Cr4Flags::OSFXSR);
cr4.insert(controlregs::Cr4Flags::OSXMMEXCPT_ENABLE);
diff --git a/src/aero_kernel/src/arch/x86_64/signals.rs b/src/aero_kernel/src/arch/x86_64/signals.rs
index 21ad2ccd4f4..620892da028 100644
--- a/src/aero_kernel/src/arch/x86_64/signals.rs
+++ b/src/aero_kernel/src/arch/x86_64/signals.rs
@@ -20,6 +20,7 @@
use crate::userland;
use crate::userland::scheduler;
use crate::utils::StackHelper;
+use crate::arch::controlregs;
use super::interrupts::InterruptStack;
@@ -107,11 +108,11 @@ pub fn sigreturn(stack: &mut InterruptStack) -> usize {
let current_task = scheduler::get_scheduler().current_task();
- current_task.signals().set_mask(
+ controlregs::with_userspace_access(||current_task.signals().set_mask(
aero_syscall::signal::SigProcMask::Set,
signal_frame.sigmask,
None,
- );
+ ));
writer.get_by(REDZONE_SIZE);
diff --git a/src/aero_kernel/src/drivers/tty.rs b/src/aero_kernel/src/drivers/tty.rs
index 77822adc1c3..bef794c5e6e 100644
--- a/src/aero_kernel/src/drivers/tty.rs
+++ b/src/aero_kernel/src/drivers/tty.rs
@@ -28,6 +28,7 @@ use crate::fs::inode;
use crate::fs::inode::INodeInterface;
use crate::mem::paging::VirtAddr;
use crate::utils::sync::{BlockQueue, Mutex};
+use crate::arch::controlregs;
use super::keyboard::KeyCode;
use super::keyboard::KeyboardListener;
@@ -234,11 +235,11 @@ impl INodeInterface for Tty {
if buffer.len() > stdin.front_buffer.len() {
for (i, c) in stdin.front_buffer.drain(..).enumerate() {
- buffer[i] = c;
+ controlregs::with_userspace_access(||buffer[i] = c);
}
} else {
for (i, c) in stdin.front_buffer.drain(..buffer.len()).enumerate() {
- buffer[i] = c;
+ controlregs::with_userspace_access(||buffer[i] = c);
}
}
@@ -264,13 +265,13 @@ impl INodeInterface for Tty {
let (rows, cols) = crate::rendy::get_rows_cols();
- winsize.ws_row = rows as u16;
- winsize.ws_col = cols as u16;
+ controlregs::with_userspace_access(||winsize.ws_row = rows as u16);
+ controlregs::with_userspace_access(||winsize.ws_col = cols as u16);
let (xpixel, ypixel) = crate::rendy::get_resolution();
- winsize.ws_xpixel = xpixel as u16;
- winsize.ws_ypixel = ypixel as u16;
+ controlregs::with_userspace_access(||winsize.ws_xpixel = xpixel as u16);
+ controlregs::with_userspace_access(||winsize.ws_ypixel = ypixel as u16);
Ok(0x00)
}
@@ -282,7 +283,7 @@ impl INodeInterface for Tty {
let lock = TERMIOS.lock_irq();
let this = &*lock;
- *termios = this.clone();
+ controlregs::with_userspace_access(||*termios = this.clone());
Ok(0x00)
}
@@ -299,7 +300,7 @@ impl INodeInterface for Tty {
let mut lock = TERMIOS.lock_irq();
let this = &mut *lock;
- *this = termios.clone();
+ controlregs::with_userspace_access(||*this = termios.clone());
Ok(0x00)
}
diff --git a/src/aero_kernel/src/syscall/fs.rs b/src/aero_kernel/src/syscall/fs.rs
index 229958ef6fe..28f77d07192 100644
--- a/src/aero_kernel/src/syscall/fs.rs
+++ b/src/aero_kernel/src/syscall/fs.rs
@@ -20,6 +20,8 @@
use aero_syscall::prelude::FdFlags;
use aero_syscall::{AeroSyscallError, OpenFlags};
+use crate::arch::controlregs;
+
use crate::fs::inode::DirEntry;
use crate::fs::pipe::Pipe;
use crate::fs::{self, lookup_path, LookupMode};
@@ -39,8 +41,8 @@ pub fn write(fd: usize, buffer: usize, size: usize) -> Result Result Result Result Result Result {
@@ -136,7 +138,7 @@ pub fn close(fd: usize) -> Result {
}
pub fn chdir(path: usize, size: usize) -> Result {
- let buffer = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
+ let buffer = controlregs::with_userspace_access(||validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL))?;
let inode = fs::lookup_path(Path::new(buffer))?;
if !inode.inode().metadata()?.is_directory() {
@@ -149,7 +151,7 @@ pub fn chdir(path: usize, size: usize) -> Result {
}
pub fn mkdirat(dfd: usize, path: usize, size: usize) -> Result {
- let path_str = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
+ let path_str = controlregs::with_userspace_access(||validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL))?;
let path = Path::new(path_str);
// NOTE: If the pathname given in pathname is relative, then it is interpreted
@@ -197,7 +199,7 @@ pub fn mkdir(path: usize, size: usize) -> Result {
}
pub fn rmdir(path: usize, size: usize) -> Result {
- let path_str = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
+ let path_str = controlregs::with_userspace_access(||validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL))?;
let path = Path::new(path_str);
let (_, child) = path.parent_and_basename();
@@ -224,7 +226,7 @@ pub fn getcwd(buffer: usize, size: usize) -> Result {
let buffer = validate_slice_mut(buffer as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
let cwd = scheduler::get_scheduler().current_task().get_cwd();
- buffer[..cwd.len()].copy_from_slice(cwd.as_bytes());
+ controlregs::with_userspace_access(||buffer[..cwd.len()].copy_from_slice(cwd.as_bytes()));
Ok(cwd.len())
}
@@ -275,8 +277,8 @@ pub fn pipe(fds: usize, flags: usize) -> Result {
Ok(fd2) => fd2,
};
- fds[0] = fd1;
- fds[1] = fd2;
+ controlregs::with_userspace_access(||fds[0] = fd1);
+ controlregs::with_userspace_access(||fds[1] = fd2);
Ok(0x00)
}
@@ -287,7 +289,7 @@ pub fn unlink(
path_size: usize,
flags: usize,
) -> Result {
- let path_str = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
+ let path_str = controlregs::with_userspace_access(||validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL))?;
let path = Path::new(path_str);
// TODO: Make use of the open flags.
@@ -319,7 +321,7 @@ pub fn access(
_mode: usize,
_flags: usize,
) -> Result {
- let path_str = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
+ let path_str = controlregs::with_userspace_access(||validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL))?;
let path = Path::new(path_str);
if fd as isize == aero_syscall::AT_FDCWD {
diff --git a/src/aero_kernel/src/syscall/ipc.rs b/src/aero_kernel/src/syscall/ipc.rs
index ea0f76f98cc..860a61f8e4a 100644
--- a/src/aero_kernel/src/syscall/ipc.rs
+++ b/src/aero_kernel/src/syscall/ipc.rs
@@ -17,6 +17,7 @@
* along with Aero. If not, see .
*/
+use crate::arch::controlregs;
use crate::userland::scheduler::get_scheduler;
use crate::userland::task::TaskId;
@@ -60,11 +61,10 @@ fn handle_recieve(
let output =
validate_slice_mut(message_ptr as *mut u8, message_size).ok_or(AeroSyscallError::EINVAL)?;
- output[0..msg.data.len()].copy_from_slice(&msg.data);
-
- unsafe {
+ controlregs::with_userspace_access(||unsafe {
+ output[0..msg.data.len()].copy_from_slice(&msg.data);
pid_ptr.write(msg.from);
- }
+ });
Ok(msg.data.len())
}
@@ -82,9 +82,11 @@ pub fn send(pid: usize, message: usize, message_size: usize) -> Result Result {
let init_bytes = init.as_bytes();
let len = init.len();
- fixed[..len].copy_from_slice(init_bytes)
+ controlregs::with_userspace_access(||fixed[..len].copy_from_slice(init_bytes))
}
// TODO: Safety checks!
@@ -104,10 +106,10 @@ pub fn exec(
envs: usize,
envc: usize,
) -> Result {
- let path = validate_str(path as *const u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
+ let path = controlregs::with_userspace_access(||validate_str(path as *const u8, path_size).ok_or(AeroSyscallError::EINVAL))?;
let path = Path::new(path);
- let executable = fs::lookup_path(path)?;
+ let executable = controlregs::with_userspace_access(||fs::lookup_path(path))?;
if executable.inode().metadata()?.is_directory() {
return Err(AeroSyscallError::EISDIR);
@@ -135,7 +137,7 @@ pub fn exec(
}
pub fn log(msg_start: usize, msg_size: usize) -> Result {
- let message = validate_str(msg_start as *const u8, msg_size).ok_or(AeroSyscallError::EINVAL)?;
+ let message = controlregs::with_userspace_access(||validate_str(msg_start as *const u8, msg_size).ok_or(AeroSyscallError::EINVAL))?;
log::debug!("{}", message);
Ok(0x00)
@@ -145,7 +147,7 @@ pub fn waitpid(pid: usize, status: usize, _flags: usize) -> Result Result
if bytes.len() > slice.len() {
Err(AeroSyscallError::ENAMETOOLONG)
} else {
- slice[0..bytes.len()].copy_from_slice(bytes);
+ controlregs::with_userspace_access(||slice[0..bytes.len()].copy_from_slice(bytes));
Ok(bytes.len())
}
@@ -225,7 +227,7 @@ pub fn info(struc: usize) -> Result {
let struc = unsafe { &mut *(struc as *mut aero_syscall::SysInfo) };
// TODO: Fill in the rest of the struct.
- struc.uptime = crate::time::get_uptime_ticks() as i64;
+ controlregs::with_userspace_access(||struc.uptime = crate::time::get_uptime_ticks() as i64);
Ok(0x00)
}
@@ -235,7 +237,7 @@ pub fn sethostname(ptr: usize, length: usize) -> Result
match core::str::from_utf8(slice) {
Ok(new_hostname) => {
- *hostname().lock() = String::from(new_hostname);
+ controlregs::with_userspace_access(||*hostname().lock() = String::from(new_hostname));
Ok(0)
}
Err(_) => Err(AeroSyscallError::EINVAL),
@@ -259,7 +261,7 @@ pub fn sigaction(
};
let entry = if let Some(new) = new {
- Some(SignalEntry::from_sigaction(*new, sigreturn)?)
+ Some(controlregs::with_userspace_access(||SignalEntry::from_sigaction(*new, sigreturn))?)
} else {
None
};
@@ -278,7 +280,7 @@ pub fn sigaction(
let task = scheduler.current_task();
let signals = task.signals();
- signals.set_signal(sig, entry, old);
+ controlregs::with_userspace_access(||signals.set_signal(sig, entry, old));
Ok(0)
}
diff --git a/src/aero_kernel/src/syscall/time.rs b/src/aero_kernel/src/syscall/time.rs
index ab38eccc441..34707528fdc 100644
--- a/src/aero_kernel/src/syscall/time.rs
+++ b/src/aero_kernel/src/syscall/time.rs
@@ -19,6 +19,7 @@
use aero_syscall::AeroSyscallError;
+use crate::arch::controlregs;
use crate::utils::CeilDiv;
use crate::{mem::paging::VirtAddr, userland::scheduler};
@@ -28,7 +29,7 @@ const CLOCK_TYPE_MONOTONIC: usize = 1;
pub fn sleep(timespec: usize) -> Result {
let timespec = VirtAddr::new(timespec as u64);
let timespec = unsafe { &*(timespec.as_mut_ptr::()) };
- let duration = (timespec.tv_nsec as usize).ceil_div(1000000000) + timespec.tv_sec as usize;
+ let duration = controlregs::with_userspace_access(||(timespec.tv_nsec as usize).ceil_div(1000000000) + timespec.tv_sec as usize);
scheduler::get_scheduler().inner.sleep(Some(duration))?;
@@ -43,8 +44,8 @@ pub fn gettime(clock: usize, timespec: usize) -> Result
CLOCK_TYPE_REALTIME => {
let clock = crate::time::get_realtime_clock();
- timespec.tv_sec = clock.tv_sec;
- timespec.tv_nsec = clock.tv_nsec;
+ controlregs::with_userspace_access(||timespec.tv_sec = clock.tv_sec);
+ controlregs::with_userspace_access(||timespec.tv_nsec = clock.tv_nsec);
Ok(0x00)
}
diff --git a/src/aero_kernel/src/unwind.rs b/src/aero_kernel/src/unwind.rs
index 10a7b13205a..531c1df9858 100644
--- a/src/aero_kernel/src/unwind.rs
+++ b/src/aero_kernel/src/unwind.rs
@@ -32,6 +32,7 @@ use crate::logger;
use crate::rendy;
use crate::arch::interrupts;
+use crate::arch::controlregs;
static PANIC_HOOK_READY: AtomicBool = AtomicBool::new(false);
@@ -186,7 +187,7 @@ extern "C" fn rust_begin_unwind(info: &PanicInfo) -> ! {
// Add a new line to make the stack trace more readable.
log::error!("");
- unwind_stack_trace();
+ controlregs::with_userspace_access(||unwind_stack_trace());
#[cfg(feature = "ci")]
emu::exit_qemu(emu::ExitStatus::Success);
diff --git a/src/aero_kernel/src/userland/signals.rs b/src/aero_kernel/src/userland/signals.rs
index 7cefd53d4c7..b97684411c7 100644
--- a/src/aero_kernel/src/userland/signals.rs
+++ b/src/aero_kernel/src/userland/signals.rs
@@ -29,6 +29,7 @@ use bit_field::BitField;
use aero_syscall::AeroSyscallError;
use super::scheduler;
+use crate::arch::controlregs;
use crate::fs::FileSystemError;
use crate::utils::sync::{Mutex, MutexGuard};
@@ -391,7 +392,7 @@ impl Signals {
*old = self.blocked_mask.load(Ordering::SeqCst);
}
- let set = set & !IMMUTABLE_MASK;
+ let set = controlregs::with_userspace_access(||set & !IMMUTABLE_MASK);
match how {
SigProcMask::Block => {
diff --git a/src/aero_kernel/src/userland/task.rs b/src/aero_kernel/src/userland/task.rs
index 255d823968b..0c0826eaa35 100644
--- a/src/aero_kernel/src/userland/task.rs
+++ b/src/aero_kernel/src/userland/task.rs
@@ -30,6 +30,7 @@ use crate::fs::{self, FileSystem};
use crate::mem::paging::*;
use crate::arch::task::ArchTask;
+use crate::arch::controlregs;
use crate::fs::file_table::FileTable;
use crate::syscall::{ExecArgs, MessageQueue};
use crate::utils::sync::{BlockQueue, Mutex};
@@ -154,9 +155,9 @@ impl Zombies {
// WIFEXITED: The child process has been terminated normally by
// either calling sys_exit() or returning from the main function.
- *status = 0x200;
+ controlregs::with_userspace_access(||*status = 0x200);
// The lower 8-bits are used to store the exit status.
- *status |= st as u32 & 0xff;
+ controlregs::with_userspace_access(||*status |= st as u32 & 0xff);
Ok(tid.as_usize())
}
@@ -399,7 +400,7 @@ impl Task {
// Clear the signals that are pending for this task on exec.
self.signals().clear();
- self.arch_task_mut().exec(vm, executable, argv, envv)
+ controlregs::with_userspace_access(||self.arch_task_mut().exec(vm, executable, argv, envv))
}
pub fn vm(&self) -> &Arc {
diff --git a/src/aero_kernel/src/userland/vm.rs b/src/aero_kernel/src/userland/vm.rs
index e97a78180bc..bb72b916c1a 100644
--- a/src/aero_kernel/src/userland/vm.rs
+++ b/src/aero_kernel/src/userland/vm.rs
@@ -27,6 +27,7 @@ use xmas_elf::header::*;
use xmas_elf::program::*;
use xmas_elf::*;
+use crate::arch::controlregs;
use crate::arch::task::userland_last_address;
use crate::fs;
use crate::fs::cache::DirCacheItem;
@@ -385,7 +386,7 @@ impl Mapping {
let new_slice = new_frame.as_slice_mut::();
// Copy the contents from the old frame to the newly allocated frame.
- new_slice.copy_from_slice(old_slice);
+ controlregs::with_userspace_access(||new_slice.copy_from_slice(old_slice));
// Re-map the page to the newly allocated frame and with the provided
// protection flags.
diff --git a/userland/apps/aero_shell/src/main.rs b/userland/apps/aero_shell/src/main.rs
index 75905eece31..fb24259aa81 100644
--- a/userland/apps/aero_shell/src/main.rs
+++ b/userland/apps/aero_shell/src/main.rs
@@ -144,7 +144,7 @@ fn repl(history: &mut Vec) -> Result<(), AeroSyscallError> {
}
"uptime" => {
- print!("{}", get_uptime()?);
+ println!("{}", get_uptime()?);
}
"sleep" => {