From bf292bc0d16f5722b6b45d8013150d774a4882fa Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 17 Nov 2016 12:12:02 -0700 Subject: [PATCH] Add signal support - exit on signal --- .gitmodules | 6 +- Makefile | 12 +- arch/x86_64/src/context.rs | 76 +++++ arch/x86_64/src/interrupt/exception.rs | 51 ++-- kernel/context/context.rs | 5 +- kernel/context/switch.rs | 20 +- kernel/lib.rs | 1 + kernel/syscall/driver.rs | 130 +++++++++ kernel/syscall/mod.rs | 19 +- kernel/syscall/privilege.rs | 85 ++++++ kernel/syscall/process.rs | 259 ++---------------- libstd | 1 - {libstd_real => libstd}/Cargo.toml | 0 .../alloc_system/Cargo.toml | 0 .../alloc_system/src/lib.rs | 0 .../compiler_builtins/Cargo.toml | 0 .../compiler_builtins/src/lib.rs | 0 {libstd_real => libstd}/libc/Cargo.toml | 0 {libstd_real => libstd}/libc/build.rs | 0 {libstd_real => libstd}/libc/src/funcs.rs | 0 {libstd_real => libstd}/libc/src/lib.rs | 0 {libstd_real => libstd}/libc/src/start.rs | 0 {libstd_real => libstd}/libc/src/syscall.rs | 0 {libstd_real => libstd}/libc/src/types.rs | 0 libstd/openlibm | 1 + .../panic_abort/Cargo.toml | 0 .../panic_unwind/Cargo.toml | 0 {libstd_real => libstd}/unwind/Cargo.toml | 0 programs/contain/src/main.rs | 40 +-- programs/coreutils | 2 +- rust | 2 +- 31 files changed, 396 insertions(+), 314 deletions(-) create mode 100644 kernel/syscall/driver.rs create mode 100644 kernel/syscall/privilege.rs delete mode 160000 libstd rename {libstd_real => libstd}/Cargo.toml (100%) rename {libstd_real => libstd}/alloc_system/Cargo.toml (100%) rename {libstd_real => libstd}/alloc_system/src/lib.rs (100%) rename {libstd_real => libstd}/compiler_builtins/Cargo.toml (100%) rename {libstd_real => libstd}/compiler_builtins/src/lib.rs (100%) rename {libstd_real => libstd}/libc/Cargo.toml (100%) rename {libstd_real => libstd}/libc/build.rs (100%) rename {libstd_real => libstd}/libc/src/funcs.rs (100%) rename {libstd_real => libstd}/libc/src/lib.rs (100%) rename {libstd_real => libstd}/libc/src/start.rs (100%) rename {libstd_real => libstd}/libc/src/syscall.rs (100%) rename {libstd_real => libstd}/libc/src/types.rs (100%) create mode 160000 libstd/openlibm rename {libstd_real => libstd}/panic_abort/Cargo.toml (100%) rename {libstd_real => libstd}/panic_unwind/Cargo.toml (100%) rename {libstd_real => libstd}/unwind/Cargo.toml (100%) diff --git a/.gitmodules b/.gitmodules index 3b2a8c6..187ed86 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "rust"] path = rust url = https://github.com/redox-os/rust.git -[submodule "libstd"] - path = libstd - url = https://github.com/redox-os/libstd.git [submodule "ion"] path = programs/ion url = https://github.com/redox-os/ion.git @@ -52,3 +49,6 @@ [submodule "crates/docgen"] path = crates/docgen url = https://github.com/redox-os/docgen.git +[submodule "libstd_real/openlibm"] + path = libstd/openlibm + url = https://github.com/redox-os/openlibm.git diff --git a/Makefile b/Makefile index 3faa115..fced8f3 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,6 @@ FORCE: clean: cargo clean cargo clean --manifest-path libstd/Cargo.toml - cargo clean --manifest-path libstd_real/Cargo.toml cargo clean --manifest-path drivers/ahcid/Cargo.toml cargo clean --manifest-path drivers/e1000d/Cargo.toml cargo clean --manifest-path drivers/ps2d/Cargo.toml @@ -82,7 +81,6 @@ ref: FORCE test: cargo test cargo test --manifest-path libstd/Cargo.toml - cargo test --manifest-path libstd_real/Cargo.toml cargo test --manifest-path drivers/ahcid/Cargo.toml cargo test --manifest-path drivers/e1000d/Cargo.toml cargo test --manifest-path drivers/ps2d/Cargo.toml @@ -114,7 +112,6 @@ test: update: cargo update cargo update --manifest-path libstd/Cargo.toml - cargo update --manifest-path libstd_real/Cargo.toml cargo update --manifest-path drivers/ahcid/Cargo.toml cargo update --manifest-path drivers/e1000d/Cargo.toml cargo update --manifest-path drivers/ps2d/Cargo.toml @@ -314,13 +311,9 @@ $(BUILD)/libopenlibm.a: libstd/openlibm/libopenlibm.a mkdir -p $(BUILD) cp $< $@ -#$(BUILD)/libstd.rlib: libstd/Cargo.toml libstd/src/** $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib $(BUILD)/librustc_unicode.rlib $(BUILD)/libcollections.rlib $(BUILD)/librand.rlib $(BUILD)/libopenlibm.a -# $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -o $@ -# cp libstd/target/$(TARGET)/release/deps/*.rlib $(BUILD) - -$(BUILD)/libstd.rlib: libstd_real/Cargo.toml rust/src/libstd/** $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib $(BUILD)/librustc_unicode.rlib $(BUILD)/libcollections.rlib $(BUILD)/librand.rlib $(BUILD)/libopenlibm.a +$(BUILD)/libstd.rlib: libstd/Cargo.toml rust/src/libstd/** $(BUILD)/libcore.rlib $(BUILD)/liballoc.rlib $(BUILD)/librustc_unicode.rlib $(BUILD)/libcollections.rlib $(BUILD)/librand.rlib $(BUILD)/libopenlibm.a $(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -o $@ - cp libstd_real/target/$(TARGET)/release/deps/*.rlib $(BUILD) + cp libstd/target/$(TARGET)/release/deps/*.rlib $(BUILD) initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib mkdir -p initfs/bin @@ -438,6 +431,7 @@ coreutils: \ filesystem/bin/false \ filesystem/bin/free \ filesystem/bin/head \ + filesystem/bin/kill \ filesystem/bin/ls \ filesystem/bin/mkdir \ filesystem/bin/mv \ diff --git a/arch/x86_64/src/context.rs b/arch/x86_64/src/context.rs index fb4f879..a11ff14 100644 --- a/arch/x86_64/src/context.rs +++ b/arch/x86_64/src/context.rs @@ -1,3 +1,4 @@ +use core::mem; use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; /// This must be used by the kernel to ensure that context switches are done atomically @@ -65,6 +66,23 @@ impl Context { self.rsp = address; } + pub unsafe fn signal_stack(&mut self, handler: extern fn(usize), sig: u8) { + self.push_stack(sig as usize); + self.push_stack(handler as usize); + self.push_stack(signal_handler_wrapper as usize); + } + + pub unsafe fn push_stack(&mut self, value: usize) { + self.rsp -= mem::size_of::(); + *(self.rsp as *mut usize) = value; + } + + pub unsafe fn pop_stack(&mut self) -> usize { + let value = *(self.rsp as *const usize); + self.rsp += mem::size_of::(); + value + } + /// Switch to the next context by restoring its stack and registers #[cold] #[inline(never)] @@ -108,3 +126,61 @@ impl Context { asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); } } + +#[repr(packed)] +pub struct SignalHandlerStack { + r11: usize, + r10: usize, + r9: usize, + r8: usize, + rsi: usize, + rdi: usize, + rdx: usize, + rcx: usize, + rax: usize, + handler: extern fn(usize), + sig: usize, + rip: usize, +} + +#[naked] +unsafe extern fn signal_handler_wrapper() { + #[inline(never)] + unsafe fn inner(stack: &SignalHandlerStack) { + (stack.handler)(stack.sig); + } + + // Push scratch registers + asm!("xchg bx, bx + push rax + push rcx + push rdx + push rdi + push rsi + push r8 + push r9 + push r10 + push r11" + : : : : "intel", "volatile"); + + // Get reference to stack variables + let rsp: usize; + asm!("" : "={rsp}"(rsp) : : : "intel", "volatile"); + + // Call inner rust function + inner(&*(rsp as *const SignalHandlerStack)); + + // Pop scratch registers, error code, and return + asm!("xchg bx, bx + pop r11 + pop r10 + pop r9 + pop r8 + pop rsi + pop rdi + pop rdx + pop rcx + pop rax + add rsp, 16" + : : : : "intel", "volatile"); +} diff --git a/arch/x86_64/src/interrupt/exception.rs b/arch/x86_64/src/interrupt/exception.rs index 2e797f1..3822779 100644 --- a/arch/x86_64/src/interrupt/exception.rs +++ b/arch/x86_64/src/interrupt/exception.rs @@ -1,5 +1,4 @@ -use super::{halt, stack_trace}; - +use interrupt::stack_trace; use syscall::flag::*; extern { @@ -8,9 +7,8 @@ extern { interrupt_stack!(divide_by_zero, stack, { println!("Divide by zero fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGFPE); stack_trace(); - loop { halt(); } + ksignal(SIGFPE); }); interrupt_stack!(debug, stack, { @@ -34,107 +32,92 @@ interrupt_stack!(overflow, stack, { interrupt_stack!(bound_range, stack, { println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_stack!(invalid_opcode, stack, { println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGILL); stack_trace(); - loop { halt(); } + ksignal(SIGILL); }); interrupt_stack!(device_not_available, stack, { println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGILL); stack_trace(); - loop { halt(); } + ksignal(SIGILL); }); interrupt_error!(double_fault, stack, { println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_error!(invalid_tss, stack, { println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_error!(segment_not_present, stack, { println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_error!(stack_segment, stack, { println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_error!(protection, stack, { println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_error!(page, stack, { let cr2: usize; asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile"); println!("Page fault: {:>02X}:{:>016X} at {:>02X}:{:>016X}", stack.code, cr2, stack.cs, stack.rip); - ksignal(SIGSEGV); stack_trace(); - loop { halt(); } + ksignal(SIGSEGV); }); interrupt_stack!(fpu, stack, { println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGFPE); stack_trace(); - loop { halt(); } + ksignal(SIGFPE); }); interrupt_error!(alignment_check, stack, { println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGBUS); stack_trace(); - loop { halt(); } + ksignal(SIGBUS); }); interrupt_stack!(machine_check, stack, { println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGBUS); stack_trace(); - loop { halt(); } + ksignal(SIGBUS); }); interrupt_stack!(simd, stack, { println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGFPE); stack_trace(); - loop { halt(); } + ksignal(SIGFPE); }); interrupt_stack!(virtualization, stack, { println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip); - ksignal(SIGBUS); stack_trace(); - loop { halt(); } + ksignal(SIGBUS); }); interrupt_error!(security, stack, { println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); - ksignal(SIGBUS); stack_trace(); - loop { halt(); } + ksignal(SIGBUS); }); diff --git a/kernel/context/context.rs b/kernel/context/context.rs index 46e456b..5e053ca 100644 --- a/kernel/context/context.rs +++ b/kernel/context/context.rs @@ -1,6 +1,6 @@ use alloc::arc::Arc; use alloc::boxed::Box; -use collections::{BTreeMap, Vec}; +use collections::{BTreeMap, Vec, VecDeque}; use spin::Mutex; use arch; @@ -48,6 +48,8 @@ pub struct Context { pub vfork: bool, /// Context is being waited on pub waitpid: Arc>, + /// Context should handle pending signals + pub pending: VecDeque, /// Context should wake up at specified time pub wake: Option<(u64, u64)>, /// The architecture specific context @@ -94,6 +96,7 @@ impl Context { cpu_id: None, vfork: false, waitpid: Arc::new(WaitMap::new()), + pending: VecDeque::new(), wake: None, arch: arch::context::Context::new(), kfx: None, diff --git a/kernel/context/switch.rs b/kernel/context/switch.rs index a438d89..bbdc8ad 100644 --- a/kernel/context/switch.rs +++ b/kernel/context/switch.rs @@ -1,7 +1,8 @@ use core::sync::atomic::Ordering; use arch; -use super::{contexts, Context, Status, CONTEXT_ID}; +use context::{contexts, Context, Status, CONTEXT_ID}; +use syscall; /// Switch to the next context /// @@ -20,6 +21,7 @@ pub unsafe fn switch() -> bool { let from_ptr; let mut to_ptr = 0 as *mut Context; + let mut to_sig = None; { let contexts = contexts(); { @@ -34,6 +36,10 @@ pub unsafe fn switch() -> bool { // println!("{}: take {} {}", cpu_id, context.id, ::core::str::from_utf8_unchecked(&context.name.lock())); } + if context.status == Status::Blocked && ! context.pending.is_empty() { + context.unblock(); + } + if context.status == Status::Blocked && context.wake.is_some() { let wake = context.wake.expect("context::switch: wake not set"); @@ -57,6 +63,7 @@ pub unsafe fn switch() -> bool { let mut context = context_lock.write(); if check_context(&mut context) { to_ptr = context.deref_mut() as *mut Context; + to_sig = context.pending.pop_front(); break; } } @@ -68,6 +75,7 @@ pub unsafe fn switch() -> bool { let mut context = context_lock.write(); if check_context(&mut context) { to_ptr = context.deref_mut() as *mut Context; + to_sig = context.pending.pop_front(); break; } } @@ -91,7 +99,17 @@ pub unsafe fn switch() -> bool { // Unset global lock before switch, as arch is only usable by the current CPU at this time arch::context::CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst); + if let Some(sig) = to_sig { + println!("Handle {}", sig); + (&mut *to_ptr).arch.signal_stack(signal_handler, sig); + } + (&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch); true } + +extern fn signal_handler(signal: usize) { + println!("Signal handler: {}", signal); + syscall::exit(signal); +} diff --git a/kernel/lib.rs b/kernel/lib.rs index 6c03cfa..bda4da9 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -113,6 +113,7 @@ pub extern fn ksignal(signal: usize) { println!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }); } } + syscall::exit(signal & 0x7F); } /// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this diff --git a/kernel/syscall/driver.rs b/kernel/syscall/driver.rs new file mode 100644 index 0000000..9c3f3cd --- /dev/null +++ b/kernel/syscall/driver.rs @@ -0,0 +1,130 @@ +use arch; +use arch::memory::{allocate_frames, deallocate_frames, Frame}; +use arch::paging::{entry, ActivePageTable, PhysicalAddress, VirtualAddress}; +use context; +use context::memory::Grant; +use syscall::error::{Error, EFAULT, ENOMEM, EPERM, ESRCH, Result}; +use syscall::flag::{MAP_WRITE, MAP_WRITE_COMBINE}; + +fn enforce_root() -> Result<()> { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + if context.euid == 0 { + Ok(()) + } else { + Err(Error::new(EPERM)) + } +} + +pub fn iopl(_level: usize, _stack_base: usize) -> Result { + enforce_root()?; + + //TODO + Ok(0) +} + +pub fn physalloc(size: usize) -> Result { + enforce_root()?; + + allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get()) +} + +pub fn physfree(physical_address: usize, size: usize) -> Result { + enforce_root()?; + + deallocate_frames(Frame::containing_address(PhysicalAddress::new(physical_address)), (size + 4095)/4096); + //TODO: Check that no double free occured + Ok(0) +} + +//TODO: verify exlusive access to physical memory +pub fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { + enforce_root()?; + + if size == 0 { + Ok(0) + } else { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + + let mut grants = context.grants.lock(); + + let from_address = (physical_address/4096) * 4096; + let offset = physical_address - from_address; + let full_size = ((offset + size + 4095)/4096) * 4096; + let mut to_address = arch::USER_GRANT_OFFSET; + + let mut entry_flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE; + if flags & MAP_WRITE == MAP_WRITE { + entry_flags |= entry::WRITABLE; + } + if flags & MAP_WRITE_COMBINE == MAP_WRITE_COMBINE { + entry_flags |= entry::HUGE_PAGE; + } + + for i in 0 .. grants.len() { + let start = grants[i].start_address().get(); + if to_address + full_size < start { + grants.insert(i, Grant::physmap( + PhysicalAddress::new(from_address), + VirtualAddress::new(to_address), + full_size, + entry_flags + )); + + return Ok(to_address + offset); + } else { + let pages = (grants[i].size() + 4095) / 4096; + let end = start + pages * 4096; + to_address = end; + } + } + + grants.push(Grant::physmap( + PhysicalAddress::new(from_address), + VirtualAddress::new(to_address), + full_size, + entry_flags + )); + + Ok(to_address + offset) + } +} + +pub fn physunmap(virtual_address: usize) -> Result { + enforce_root()?; + + if virtual_address == 0 { + Ok(0) + } else { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + + let mut grants = context.grants.lock(); + + for i in 0 .. grants.len() { + let start = grants[i].start_address().get(); + let end = start + grants[i].size(); + if virtual_address >= start && virtual_address < end { + grants.remove(i).unmap(); + + return Ok(0); + } + } + + Err(Error::new(EFAULT)) + } +} + +pub fn virttophys(virtual_address: usize) -> Result { + enforce_root()?; + + let active_table = unsafe { ActivePageTable::new() }; + match active_table.translate(VirtualAddress::new(virtual_address)) { + Some(physical_address) => Ok(physical_address.get()), + None => Err(Error::new(EFAULT)) + } +} diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs index 952cd93..0bb1a64 100644 --- a/kernel/syscall/mod.rs +++ b/kernel/syscall/mod.rs @@ -4,8 +4,10 @@ extern crate syscall; pub use self::syscall::{data, error, flag, number, scheme}; +pub use self::driver::*; pub use self::fs::*; pub use self::futex::futex; +pub use self::privilege::*; pub use self::process::*; pub use self::time::*; pub use self::validate::*; @@ -17,12 +19,18 @@ use self::number::*; use context::ContextId; use scheme::FileHandle; +/// Driver syscalls +pub mod driver; + /// Filesystem syscalls pub mod fs; /// Fast userspace mutex pub mod futex; +/// Privilege syscalls +pub mod privilege; + /// Process syscalls pub mod process; @@ -65,13 +73,14 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_CLOCK_GETTIME => clock_gettime(b, validate_slice_mut(c as *mut TimeSpec, 1).map(|time| &mut time[0])?), SYS_FUTEX => futex(validate_slice_mut(b as *mut i32, 1).map(|uaddr| &mut uaddr[0])?, c, d as i32, e, f as *mut i32), SYS_BRK => brk(b), - SYS_EXIT => exit(b), - SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), - SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), - SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_GETPID => getpid().map(ContextId::into), - SYS_IOPL => iopl(b), SYS_CLONE => clone(b, stack).map(ContextId::into), + SYS_EXIT => exit((b & 0xFF) << 8), + SYS_KILL => kill(ContextId::from(b), c), + SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into), + SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), + SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), + SYS_IOPL => iopl(b, stack), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETUID => getuid(), SYS_GETGID => getgid(), diff --git a/kernel/syscall/privilege.rs b/kernel/syscall/privilege.rs new file mode 100644 index 0000000..a4ce336 --- /dev/null +++ b/kernel/syscall/privilege.rs @@ -0,0 +1,85 @@ +use collections::Vec; + +use context; +use scheme; +use syscall::error::*; +use syscall::validate::validate_slice; + +pub fn getegid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.egid as usize) +} + +pub fn geteuid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.euid as usize) +} + +pub fn getgid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.rgid as usize) +} + +pub fn getuid() -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + Ok(context.ruid as usize) +} + +pub fn setgid(gid: u32) -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let mut context = context_lock.write(); + if context.egid == 0 { + context.rgid = gid; + context.egid = gid; + Ok(0) + } else { + Err(Error::new(EPERM)) + } +} + +pub fn setuid(uid: u32) -> Result { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let mut context = context_lock.write(); + if context.euid == 0 { + context.ruid = uid; + context.euid = uid; + Ok(0) + } else { + Err(Error::new(EPERM)) + } +} + +pub fn setns(name_ptrs: &[[usize; 2]]) -> Result { + let mut names = Vec::new(); + for name_ptr in name_ptrs { + names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); + } + + let from = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + context.scheme_ns + }; + + let to = scheme::schemes_mut().setns(from, &names)?; + + { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let mut context = context_lock.write(); + context.scheme_ns = to; + } + + Ok(0) +} diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index b103365..2a4b9ca 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -7,19 +7,18 @@ use core::ops::DerefMut; use spin::Mutex; use arch; -use arch::memory::{allocate_frame, allocate_frames, deallocate_frames, Frame}; -use arch::paging::{ActivePageTable, InactivePageTable, Page, PhysicalAddress, VirtualAddress, entry}; +use arch::memory::allocate_frame; +use arch::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, entry}; use arch::paging::temporary_page::TemporaryPage; use arch::start::usermode; use context; use context::ContextId; -use context::memory::Grant; use elf::{self, program_header}; use scheme::{self, FileHandle}; use syscall; use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, MAP_WRITE, MAP_WRITE_COMBINE, WNOHANG}; +use syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, WNOHANG}; use syscall::validate::{validate_slice, validate_slice_mut}; pub fn brk(address: usize) -> Result { @@ -838,27 +837,6 @@ pub fn exit(status: usize) -> ! { unreachable!(); } -pub fn getegid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.egid as usize) -} - -pub fn geteuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.euid as usize) -} - -pub fn getgid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.rgid as usize) -} - pub fn getpid() -> Result { let contexts = context::contexts(); let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; @@ -866,224 +844,29 @@ pub fn getpid() -> Result { Ok(context.id) } -pub fn getuid() -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - Ok(context.ruid as usize) -} - -pub fn iopl(_level: usize) -> Result { - //TODO - Ok(0) -} - pub fn kill(pid: ContextId, sig: usize) -> Result { - use syscall::flag::*; + let (ruid, euid) = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + (context.ruid, context.euid) + }; - let _context_lock = { + if sig > 0 && sig <= 0x7F { let contexts = context::contexts(); let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?; - context_lock.clone() - }; - - let term = || { - println!("Terminate {:?}", pid); - }; - - let core = || { - println!("Core {:?}", pid); - }; - - let stop = || { - println!("Stop {:?}", pid); - }; - - let cont = || { - println!("Continue {:?}", pid); - }; - - match sig { - 0 => (), - SIGHUP => term(), - SIGINT => term(), - SIGQUIT => core(), - SIGILL => core(), - SIGTRAP => core(), - SIGABRT => core(), - SIGBUS => core(), - SIGFPE => core(), - SIGKILL => term(), - SIGUSR1 => term(), - SIGSEGV => core(), - SIGPIPE => term(), - SIGALRM => term(), - SIGTERM => term(), - SIGSTKFLT => term(), - SIGCHLD => (), - SIGCONT => cont(), - SIGSTOP => stop(), - SIGTSTP => stop(), - SIGTTIN => stop(), - SIGTTOU => stop(), - SIGURG => (), - SIGXCPU => core(), - SIGXFSZ => core(), - SIGVTALRM => term(), - SIGPROF => term(), - SIGWINCH => (), - SIGIO => term(), - SIGPWR => term(), - SIGSYS => core(), - _ => return Err(Error::new(EINVAL)) - } - - Ok(0) -} - -pub fn physalloc(size: usize) -> Result { - allocate_frames((size + 4095)/4096).ok_or(Error::new(ENOMEM)).map(|frame| frame.start_address().get()) -} - -pub fn physfree(physical_address: usize, size: usize) -> Result { - deallocate_frames(Frame::containing_address(PhysicalAddress::new(physical_address)), (size + 4095)/4096); - //TODO: Check that no double free occured - Ok(0) -} - -//TODO: verify exlusive access to physical memory -pub fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { - if size == 0 { - Ok(0) - } else { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - let from_address = (physical_address/4096) * 4096; - let offset = physical_address - from_address; - let full_size = ((offset + size + 4095)/4096) * 4096; - let mut to_address = arch::USER_GRANT_OFFSET; - - let mut entry_flags = entry::PRESENT | entry::NO_EXECUTE | entry::USER_ACCESSIBLE; - if flags & MAP_WRITE == MAP_WRITE { - entry_flags |= entry::WRITABLE; - } - if flags & MAP_WRITE_COMBINE == MAP_WRITE_COMBINE { - entry_flags |= entry::HUGE_PAGE; - } - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - if to_address + full_size < start { - grants.insert(i, Grant::physmap( - PhysicalAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - entry_flags - )); - - return Ok(to_address + offset); - } else { - let pages = (grants[i].size() + 4095) / 4096; - let end = start + pages * 4096; - to_address = end; - } - } - - grants.push(Grant::physmap( - PhysicalAddress::new(from_address), - VirtualAddress::new(to_address), - full_size, - entry_flags - )); - - Ok(to_address + offset) - } -} - -pub fn physunmap(virtual_address: usize) -> Result { - if virtual_address == 0 { - Ok(0) - } else { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - - let mut grants = context.grants.lock(); - - for i in 0 .. grants.len() { - let start = grants[i].start_address().get(); - let end = start + grants[i].size(); - if virtual_address >= start && virtual_address < end { - grants.remove(i).unmap(); - - return Ok(0); - } - } - - Err(Error::new(EFAULT)) - } -} - -pub fn setgid(gid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - if context.egid == 0 { - context.rgid = gid; - context.egid = gid; - Ok(0) - } else { - Err(Error::new(EPERM)) - } -} - -pub fn setuid(uid: u32) -> Result { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let mut context = context_lock.write(); - if context.euid == 0 { - context.ruid = uid; - context.euid = uid; - Ok(0) - } else { - Err(Error::new(EPERM)) - } -} - -pub fn setns(name_ptrs: &[[usize; 2]]) -> Result { - let mut names = Vec::new(); - for name_ptr in name_ptrs { - names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?); - } - - let from = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - context.scheme_ns - }; - - let to = scheme::schemes_mut().setns(from, &names)?; - - { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let mut context = context_lock.write(); - context.scheme_ns = to; - } - - Ok(0) -} - -pub fn virttophys(virtual_address: usize) -> Result { - let active_table = unsafe { ActivePageTable::new() }; - match active_table.translate(VirtualAddress::new(virtual_address)) { - Some(physical_address) => Ok(physical_address.get()), - None => Err(Error::new(EFAULT)) + if euid == 0 + || euid == context.ruid + || ruid == context.ruid + { + context.pending.push_back(sig as u8); + Ok(0) + } else { + Err(Error::new(EPERM)) + } + } else { + Err(Error::new(EINVAL)) } } diff --git a/libstd b/libstd deleted file mode 160000 index 18d61d7..0000000 --- a/libstd +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 18d61d7e8a469fb0a05a9db4d00970b7e45954ad diff --git a/libstd_real/Cargo.toml b/libstd/Cargo.toml similarity index 100% rename from libstd_real/Cargo.toml rename to libstd/Cargo.toml diff --git a/libstd_real/alloc_system/Cargo.toml b/libstd/alloc_system/Cargo.toml similarity index 100% rename from libstd_real/alloc_system/Cargo.toml rename to libstd/alloc_system/Cargo.toml diff --git a/libstd_real/alloc_system/src/lib.rs b/libstd/alloc_system/src/lib.rs similarity index 100% rename from libstd_real/alloc_system/src/lib.rs rename to libstd/alloc_system/src/lib.rs diff --git a/libstd_real/compiler_builtins/Cargo.toml b/libstd/compiler_builtins/Cargo.toml similarity index 100% rename from libstd_real/compiler_builtins/Cargo.toml rename to libstd/compiler_builtins/Cargo.toml diff --git a/libstd_real/compiler_builtins/src/lib.rs b/libstd/compiler_builtins/src/lib.rs similarity index 100% rename from libstd_real/compiler_builtins/src/lib.rs rename to libstd/compiler_builtins/src/lib.rs diff --git a/libstd_real/libc/Cargo.toml b/libstd/libc/Cargo.toml similarity index 100% rename from libstd_real/libc/Cargo.toml rename to libstd/libc/Cargo.toml diff --git a/libstd_real/libc/build.rs b/libstd/libc/build.rs similarity index 100% rename from libstd_real/libc/build.rs rename to libstd/libc/build.rs diff --git a/libstd_real/libc/src/funcs.rs b/libstd/libc/src/funcs.rs similarity index 100% rename from libstd_real/libc/src/funcs.rs rename to libstd/libc/src/funcs.rs diff --git a/libstd_real/libc/src/lib.rs b/libstd/libc/src/lib.rs similarity index 100% rename from libstd_real/libc/src/lib.rs rename to libstd/libc/src/lib.rs diff --git a/libstd_real/libc/src/start.rs b/libstd/libc/src/start.rs similarity index 100% rename from libstd_real/libc/src/start.rs rename to libstd/libc/src/start.rs diff --git a/libstd_real/libc/src/syscall.rs b/libstd/libc/src/syscall.rs similarity index 100% rename from libstd_real/libc/src/syscall.rs rename to libstd/libc/src/syscall.rs diff --git a/libstd_real/libc/src/types.rs b/libstd/libc/src/types.rs similarity index 100% rename from libstd_real/libc/src/types.rs rename to libstd/libc/src/types.rs diff --git a/libstd/openlibm b/libstd/openlibm new file mode 160000 index 0000000..3c837e7 --- /dev/null +++ b/libstd/openlibm @@ -0,0 +1 @@ +Subproject commit 3c837e79655c4be724efb945a6345ec97c07635c diff --git a/libstd_real/panic_abort/Cargo.toml b/libstd/panic_abort/Cargo.toml similarity index 100% rename from libstd_real/panic_abort/Cargo.toml rename to libstd/panic_abort/Cargo.toml diff --git a/libstd_real/panic_unwind/Cargo.toml b/libstd/panic_unwind/Cargo.toml similarity index 100% rename from libstd_real/panic_unwind/Cargo.toml rename to libstd/panic_unwind/Cargo.toml diff --git a/libstd_real/unwind/Cargo.toml b/libstd/unwind/Cargo.toml similarity index 100% rename from libstd_real/unwind/Cargo.toml rename to libstd/unwind/Cargo.toml diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs index 898bb6b..de94324 100644 --- a/programs/contain/src/main.rs +++ b/programs/contain/src/main.rs @@ -1,36 +1,36 @@ extern crate syscall; -use std::fs::File; -use std::io::{BufRead, BufReader, Read}; +use std::os::unix::process::CommandExt; +use std::process::Command; pub fn main() { + let names = [ + "file", + "rand", + "tcp", + "udp" + ]; + + let command = "sh"; + let pid = unsafe { syscall::clone(0).unwrap() }; if pid == 0 { - let rand = b"rand"; - syscall::setns(&[[rand.as_ptr() as usize, rand.len()]]).unwrap(); - - println!("Child Namespace:"); - let file = BufReader::new(File::open("sys:scheme").unwrap()); - for line in file.lines() { - let line = line.unwrap(); - println!("{}", line); + let mut name_ptrs = Vec::new(); + for name in names.iter() { + name_ptrs.push([name.as_ptr() as usize, name.len()]); } - let mut rand = File::open("rand:").unwrap(); + syscall::setns(&name_ptrs).unwrap(); - let mut byte = [0]; - rand.read(&mut byte).unwrap(); + println!("Entering container: {}", command); - println!("Rand: {}", byte[0]); + let err = Command::new(command).exec(); + + panic!("contain: failed to launch {}: {}", command, err); } else { let mut status = 0; syscall::waitpid(pid, &mut status, 0).unwrap(); - println!("Parent Namespace:"); - let file = BufReader::new(File::open("sys:scheme").unwrap()); - for line in file.lines() { - let line = line.unwrap(); - println!("{}", line); - } + println!("Exiting container: {:X}", status); } } diff --git a/programs/coreutils b/programs/coreutils index ff47394..4b58de0 160000 --- a/programs/coreutils +++ b/programs/coreutils @@ -1 +1 @@ -Subproject commit ff47394f57a8847313ac0850e029f5d21393fee6 +Subproject commit 4b58de0b3c66634f95668e47466014138c5f71bd diff --git a/rust b/rust index 267bc54..f01add1 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 267bc54fbd2cfeadde7a87fc2aa3fb975ff58b6c +Subproject commit f01add1a3bc3d86ee62f5819fa6ed9f79d453665