diff --git a/Cargo.toml b/Cargo.toml index 1a83185..bb5b264 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -resolver = "2" +resolver = "3" members = ["lib/acpica-rs", "lib/kernel-common", "loader", "kernel", "init"] [profile.release] diff --git a/kernel/src/sys/process.rs b/kernel/src/sys/process.rs index 8518e1e..eb1e6c8 100644 --- a/kernel/src/sys/process.rs +++ b/kernel/src/sys/process.rs @@ -17,6 +17,7 @@ use super::{locks::Spinlock, scheduler::SCHEDULER, task::create_task}; pub struct Process { pub pid: usize, + pub uid: usize, pub address_space: AddressSpace, pub binary: Option<&'static [u8]>, pub num_tasks: usize, @@ -25,6 +26,7 @@ pub struct Process { static KERNEL_PROCESS: Spinlock>>> = Spinlock::new(LazyCell::new(|| { let process = Process { pid: 0, + uid: 0, address_space: AddressSpace { is_kernel: true, pml4: OnceCell::new(), @@ -46,6 +48,7 @@ pub fn create_process(binary: Option<&'static [u8]>) -> Arc> { let pid = NEXT_PID.fetch_add(1, Ordering::SeqCst); let mut process = Process { pid, + uid: 0, address_space: AddressSpace { is_kernel: false, pml4: OnceCell::new(), diff --git a/kernel/src/sys/syscall.rs b/kernel/src/sys/syscall.rs index 19c4d5a..8c93a2d 100644 --- a/kernel/src/sys/syscall.rs +++ b/kernel/src/sys/syscall.rs @@ -1,5 +1,6 @@ use core::{error::Error, ptr::copy}; +use acpica_rs::{AcpiEnterSleepState, AcpiEnterSleepStatePrep, AcpiReset}; use alloc::{boxed::Box, string::String, vec, vec::Vec}; use log::{debug, trace}; @@ -8,7 +9,10 @@ use crate::cpu::{ paging::USER_END, }; -use super::task::{terminate_current_task, with_current_task}; +use super::{ + sync::increase_lock_count, + task::{terminate_current_task, with_current_task}, +}; struct SyscallArgs { arg1: usize, @@ -22,7 +26,7 @@ struct Syscall { num_args: usize, } -const SYSCALL_TABLE: [Syscall; 4] = [ +const SYSCALL_TABLE: [Syscall; 5] = [ Syscall { func: syscall_get_kernel_version, num_args: 0, @@ -33,6 +37,7 @@ const SYSCALL_TABLE: [Syscall; 4] = [ num_args: 2, }, Syscall { func: syscall_get_pid, num_args: 0 }, + Syscall { func: syscall_shutdown, num_args: 1 }, ]; fn copy_from_user(start: u64, size: usize) -> Result, Box> { @@ -61,6 +66,19 @@ fn copy_from_user(start: u64, size: usize) -> Result, Box> { disable_user_memory_access(); Ok(buffer) } +fn require_root() -> Result<(), Box> { + let mut error = false; + with_current_task(|current_task| { + let process = current_task.process.lock(); + if process.uid != 0 { + error = true; + } + }); + if error { + return Err("Permission denied".into()); + } + Ok(()) +} fn syscall_get_kernel_version(_args: SyscallArgs) -> Result> { Ok(0) } @@ -69,6 +87,7 @@ fn syscall_exit(_args: SyscallArgs) -> Result> { terminate_current_task(); } fn syscall_debug_print(args: SyscallArgs) -> Result> { + require_root()?; let data = copy_from_user(args.arg1 as u64, args.arg2)?; let string = String::from_utf8(data)?; trace!("{}", string); @@ -79,6 +98,26 @@ fn syscall_get_pid(_args: SyscallArgs) -> Result> { with_current_task(|current_task| pid = current_task.process.lock().pid); Ok(pid) } +fn syscall_shutdown(args: SyscallArgs) -> Result> { + require_root()?; + // TODO: Stop all processes and sync devices first + if args.arg1 == 0 { + unsafe { + AcpiEnterSleepStatePrep(5); + } + increase_lock_count(); + unsafe { + AcpiEnterSleepState(5); + } + } else if args.arg1 == 1 { + unsafe { + AcpiReset(); + } + } else { + return Err("Invalid syscall argument".into()); + } + panic!("Shutting down failed"); +} #[no_mangle] extern "C" fn syscall_handler(syscall: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 { if syscall as usize >= SYSCALL_TABLE.len() {