From 3121cc9ba928bc3c9c7510c7a77fb3a7bf3c6218 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sun, 21 Nov 2021 11:44:33 +0200 Subject: [PATCH] feature: fuzzy --- fs/memfs/src/dir.rs | 6 +- kernel/src/syscall/mod.rs | 7 ++- libsys/src/abi.rs | 1 + libsys/src/calls.rs | 9 +++ libusr/src/signal.rs | 36 +++++++++-- libusr/src/sys/mod.rs | 1 + libusr/src/thread.rs | 8 ++- user/src/fuzzy/main.rs | 126 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 184 insertions(+), 10 deletions(-) diff --git a/fs/memfs/src/dir.rs b/fs/memfs/src/dir.rs index 791ceee..5766e1a 100644 --- a/fs/memfs/src/dir.rs +++ b/fs/memfs/src/dir.rs @@ -1,6 +1,6 @@ use crate::{BlockAllocator, Bvec, FileInode}; use alloc::boxed::Box; -use libsys::error::Errno; +use libsys::{error::Errno, stat::Stat}; use vfs::{Vnode, VnodeImpl, VnodeKind, VnodeRef}; pub struct DirInode { @@ -31,6 +31,10 @@ impl VnodeImpl for DirInode { fn remove(&mut self, _parent: VnodeRef, _name: &str) -> Result<(), Errno> { Ok(()) } + + fn stat(&mut self, _at: VnodeRef, _stat: &mut Stat) -> Result<(), Errno> { + Ok(()) + } } impl DirInode { diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 2c0892f..055ce08 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -1,8 +1,9 @@ //! System call implementation -use crate::arch::platform::exception::ExceptionFrame; +use crate::arch::{machine, platform::exception::ExceptionFrame}; use crate::debug::Level; use crate::proc::{self, elf, wait, Process, ProcessIo, Thread}; +use crate::dev::timer::TimestampSource; use core::mem::size_of; use core::ops::DerefMut; use core::time::Duration; @@ -248,6 +249,10 @@ pub fn syscall(num: usize, args: &[usize]) -> Result { find_at_node(&mut io, at_fd, path, flags & AT_EMPTY_PATH != 0)?.check_access(io.ioctx(), mode)?; Ok(0) }, + abi::SYS_EX_GETCPUTIME => { + let time = machine::local_timer().timestamp()?; + Ok(time.as_nanos() as usize) + } _ => { let thread = Thread::current(); diff --git a/libsys/src/abi.rs b/libsys/src/abi.rs index 056563e..67dcbe4 100644 --- a/libsys/src/abi.rs +++ b/libsys/src/abi.rs @@ -9,6 +9,7 @@ pub const SYS_EX_YIELD: usize = 134; pub const SYS_EX_THREAD_EXIT: usize = 135; pub const SYS_EX_THREAD_WAIT: usize = 136; pub const SYS_EX_GETTID: usize = 137; +pub const SYS_EX_GETCPUTIME: usize = 138; pub const SYS_EXIT: usize = 1; pub const SYS_READ: usize = 2; diff --git a/libsys/src/calls.rs b/libsys/src/calls.rs index 8f09427..48bce17 100644 --- a/libsys/src/calls.rs +++ b/libsys/src/calls.rs @@ -6,9 +6,11 @@ use crate::{ signal::{Signal, SignalDestination}, stat::{AccessMode, FdSet, FileDescriptor, FileMode, OpenFlags, Stat}, }; +use core::time::Duration; // TODO document the syscall ABI +// TODO move this to libusr macro_rules! syscall { ($num:expr) => {{ let mut res: usize; @@ -247,6 +249,13 @@ pub fn sys_ioctl( }) } +#[inline(always)] +pub fn sys_ex_getcputime() -> Result { + Errno::from_syscall(unsafe { + syscall!(abi::SYS_EX_GETCPUTIME) + }).map(|e| Duration::from_nanos(e as u64)) +} + #[inline(always)] pub fn sys_ex_signal(entry: usize, stack: usize) -> Result<(), Errno> { Errno::from_syscall_unit(unsafe { syscall!(abi::SYS_EX_SIGNAL, argn!(entry), argn!(stack)) }) diff --git a/libusr/src/signal.rs b/libusr/src/signal.rs index f9d8787..e6fd5a0 100644 --- a/libusr/src/signal.rs +++ b/libusr/src/signal.rs @@ -1,13 +1,37 @@ -use libsys::{calls::sys_ex_sigreturn, signal::Signal}; -use crate::trace; +use libsys::{calls::{sys_exit, sys_ex_sigreturn}, signal::Signal, proc::ExitCode}; +use crate::{trace, thread}; + +#[derive(Clone, Copy)] +pub enum SignalHandler { + Func(fn(Signal) -> ()), + Ignore, + Terminate +} + +// TODO per-thread signal handler table +static mut SIGNAL_HANDLERS: [SignalHandler; 32] = [SignalHandler::Terminate; 32]; + +pub fn set_handler(sig: Signal, handler: SignalHandler) -> SignalHandler { + unsafe { + let old = SIGNAL_HANDLERS[sig as usize]; + SIGNAL_HANDLERS[sig as usize] = handler; + old + } +} #[inline(never)] pub(crate) extern "C" fn signal_handler(arg: Signal) -> ! { + // TODO tpidr_el0 is invalidated when entering signal context trace!("Entered signal handler: arg={:?}", arg); - match arg { - Signal::Interrupt | Signal::SegmentationFault => - loop {}, - _ => todo!() + let no = arg as usize; + if no >= 32 { + panic!("Undefined signal number: {}", no); } + match unsafe { SIGNAL_HANDLERS[no] } { + SignalHandler::Func(f) => f(arg), + SignalHandler::Ignore => (), + SignalHandler::Terminate => sys_exit(ExitCode::from(-1)), + } + sys_ex_sigreturn(); } diff --git a/libusr/src/sys/mod.rs b/libusr/src/sys/mod.rs index 09c2212..8a6ab86 100644 --- a/libusr/src/sys/mod.rs +++ b/libusr/src/sys/mod.rs @@ -1,6 +1,7 @@ pub use libsys::signal::{Signal, SignalDestination}; pub use libsys::proc::ExitCode; pub use libsys::termios; +pub use libsys::abi; pub use libsys::calls::*; pub use libsys::stat::{self, AccessMode, FileDescriptor}; pub use libsys::error::Errno; diff --git a/libusr/src/thread.rs b/libusr/src/thread.rs index f08848f..71df64e 100644 --- a/libusr/src/thread.rs +++ b/libusr/src/thread.rs @@ -68,8 +68,12 @@ unsafe fn init_common(signal_stack_pointer: *mut u8) { } pub(crate) unsafe fn init_main() { - static mut SIGNAL_STACK: [u8; 4096] = [0; 4096]; - init_common(SIGNAL_STACK.as_mut_ptr().add(SIGNAL_STACK.len())) + #[repr(align(16))] + struct StackWrapper { + data: [u8; 8192] + } + static mut STACK: StackWrapper = StackWrapper { data: [0; 8192] }; + init_common(STACK.data.as_mut_ptr().add(8192)) } pub fn current() -> Thread { diff --git a/user/src/fuzzy/main.rs b/user/src/fuzzy/main.rs index 974561f..c87864f 100644 --- a/user/src/fuzzy/main.rs +++ b/user/src/fuzzy/main.rs @@ -1,10 +1,136 @@ +#![feature(asm)] #![no_std] #![no_main] #[macro_use] extern crate libusr; +use libusr::sys::{abi, stat::Stat, Signal}; +use libusr::signal::{self, SignalHandler}; + +static mut STATE: u64 = 0; + +macro_rules! syscall { + ($num:expr) => {{ + let mut res: usize; + asm!("svc #0", out("x0") res, in("x8") $num, options(nostack)); + res + }}; + ($num:expr, $a0:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, + in("x8") $num, options(nostack)); + res + }}; + ($num:expr, $a0:expr, $a1:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, in("x1") $a1, + in("x8") $num, options(nostack)); + res + }}; + ($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, in("x1") $a1, in("x2") $a2, + in("x8") $num, options(nostack)); + res + }}; + ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, in("x1") $a1, in("x2") $a2, + in("x3") $a3, in("x8") $num, options(nostack)); + res + }}; + ($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{ + let mut res: usize = $a0; + asm!("svc #0", + inout("x0") res, in("x1") $a1, in("x2") $a2, + in("x3") $a3, in("x4") $a4, in("x8") $num, options(nostack)); + res + }}; +} + +/// Integer/size argument +macro_rules! argn { + ($a:expr) => { + $a as usize + }; +} +/// Pointer/base argument +macro_rules! argp { + ($a:expr) => { + $a as usize + }; +} + +fn random_set_seed(seed: u64) { + unsafe { STATE = seed; } +} + +fn random_u64() -> u64 { + let mut x = unsafe { STATE }; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + unsafe { + STATE = x; + } + x +} + +fn random_ascii_char() -> u8 { + ((random_u64() % (0x7F - 0x20)) as u8) + 0x20 +} + +fn random_str_range(buf: &mut [u8], min: usize, max: usize) -> &str { + let max = core::cmp::min(buf.len(), max); + assert!(max > min); + let len = ((random_u64() as usize) % (max - min)) + min; + for c in buf[..len].iter_mut() { + *c = random_ascii_char(); + } + core::str::from_utf8(&buf[..len]).unwrap() +} + +fn random_str(buf: &mut [u8]) -> &str { + random_str_range(buf, 0, buf.len()) +} + +fn random_bytes(buf: &mut [u8]) { + for byte in buf.iter_mut() { + *byte = (random_u64() & 0xFF) as u8; + } +} + #[no_mangle] fn main() -> i32 { + let seed = libusr::sys::sys_ex_getcputime().unwrap().as_nanos() as u64 / 13; + trace!("Using seed: {:#x}", seed); + random_set_seed(seed); + + let mut buf = [0; 256]; + + // Test sys_ex_getcputime() + let mut prev_time = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); + for _ in 0..100000 { + let t = libusr::sys::sys_ex_getcputime().unwrap().as_nanos(); + assert!(t >= prev_time); + } + + // Test non-utf8 input fed into syscalls expecting strings + // let old_signal = signal::set_handler(Signal::InvalidSystemCall, SignalHandler::Ignore); + for _ in 0..10000 { + random_bytes(&mut buf); + let mut stat = Stat::default(); + + unsafe { + syscall!(abi::SYS_FSTATAT, (-2i32) as usize, buf.as_mut_ptr() as usize, buf.len(), (&mut stat) as *mut _ as usize); + } + } + // signal::set_handler(Signal::InvalidSystemCall, old_signal); + 0 }