Add signal support - exit on signal

This commit is contained in:
Jeremy Soller 2016-11-17 12:12:02 -07:00
parent b551b30300
commit bf292bc0d1
31 changed files with 396 additions and 314 deletions

6
.gitmodules vendored
View file

@ -1,9 +1,6 @@
[submodule "rust"] [submodule "rust"]
path = rust path = rust
url = https://github.com/redox-os/rust.git url = https://github.com/redox-os/rust.git
[submodule "libstd"]
path = libstd
url = https://github.com/redox-os/libstd.git
[submodule "ion"] [submodule "ion"]
path = programs/ion path = programs/ion
url = https://github.com/redox-os/ion.git url = https://github.com/redox-os/ion.git
@ -52,3 +49,6 @@
[submodule "crates/docgen"] [submodule "crates/docgen"]
path = crates/docgen path = crates/docgen
url = https://github.com/redox-os/docgen.git url = https://github.com/redox-os/docgen.git
[submodule "libstd_real/openlibm"]
path = libstd/openlibm
url = https://github.com/redox-os/openlibm.git

View file

@ -28,7 +28,6 @@ FORCE:
clean: clean:
cargo clean cargo clean
cargo clean --manifest-path libstd/Cargo.toml 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/ahcid/Cargo.toml
cargo clean --manifest-path drivers/e1000d/Cargo.toml cargo clean --manifest-path drivers/e1000d/Cargo.toml
cargo clean --manifest-path drivers/ps2d/Cargo.toml cargo clean --manifest-path drivers/ps2d/Cargo.toml
@ -82,7 +81,6 @@ ref: FORCE
test: test:
cargo test cargo test
cargo test --manifest-path libstd/Cargo.toml 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/ahcid/Cargo.toml
cargo test --manifest-path drivers/e1000d/Cargo.toml cargo test --manifest-path drivers/e1000d/Cargo.toml
cargo test --manifest-path drivers/ps2d/Cargo.toml cargo test --manifest-path drivers/ps2d/Cargo.toml
@ -114,7 +112,6 @@ test:
update: update:
cargo update cargo update
cargo update --manifest-path libstd/Cargo.toml 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/ahcid/Cargo.toml
cargo update --manifest-path drivers/e1000d/Cargo.toml cargo update --manifest-path drivers/e1000d/Cargo.toml
cargo update --manifest-path drivers/ps2d/Cargo.toml cargo update --manifest-path drivers/ps2d/Cargo.toml
@ -314,13 +311,9 @@ $(BUILD)/libopenlibm.a: libstd/openlibm/libopenlibm.a
mkdir -p $(BUILD) mkdir -p $(BUILD)
cp $< $@ 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 $(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/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
$(CARGO) rustc --verbose --manifest-path $< $(CARGOFLAGS) -o $@ $(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 initfs/bin/%: drivers/%/Cargo.toml drivers/%/src/** $(BUILD)/libstd.rlib
mkdir -p initfs/bin mkdir -p initfs/bin
@ -438,6 +431,7 @@ coreutils: \
filesystem/bin/false \ filesystem/bin/false \
filesystem/bin/free \ filesystem/bin/free \
filesystem/bin/head \ filesystem/bin/head \
filesystem/bin/kill \
filesystem/bin/ls \ filesystem/bin/ls \
filesystem/bin/mkdir \ filesystem/bin/mkdir \
filesystem/bin/mv \ filesystem/bin/mv \

View file

@ -1,3 +1,4 @@
use core::mem;
use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
/// This must be used by the kernel to ensure that context switches are done atomically /// This must be used by the kernel to ensure that context switches are done atomically
@ -65,6 +66,23 @@ impl Context {
self.rsp = address; 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::<usize>();
*(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::<usize>();
value
}
/// Switch to the next context by restoring its stack and registers /// Switch to the next context by restoring its stack and registers
#[cold] #[cold]
#[inline(never)] #[inline(never)]
@ -108,3 +126,61 @@ impl Context {
asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); 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");
}

View file

@ -1,5 +1,4 @@
use super::{halt, stack_trace}; use interrupt::stack_trace;
use syscall::flag::*; use syscall::flag::*;
extern { extern {
@ -8,9 +7,8 @@ extern {
interrupt_stack!(divide_by_zero, stack, { interrupt_stack!(divide_by_zero, stack, {
println!("Divide by zero fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Divide by zero fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGFPE);
}); });
interrupt_stack!(debug, stack, { interrupt_stack!(debug, stack, {
@ -34,107 +32,92 @@ interrupt_stack!(overflow, stack, {
interrupt_stack!(bound_range, stack, { interrupt_stack!(bound_range, stack, {
println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Bound range exceeded fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_stack!(invalid_opcode, stack, { interrupt_stack!(invalid_opcode, stack, {
println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Invalid opcode fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGILL);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGILL);
}); });
interrupt_stack!(device_not_available, stack, { interrupt_stack!(device_not_available, stack, {
println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Device not available fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGILL);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGILL);
}); });
interrupt_error!(double_fault, stack, { interrupt_error!(double_fault, stack, {
println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Double fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_error!(invalid_tss, stack, { interrupt_error!(invalid_tss, stack, {
println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Invalid TSS fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_error!(segment_not_present, stack, { interrupt_error!(segment_not_present, stack, {
println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Segment not present fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_error!(stack_segment, stack, { interrupt_error!(stack_segment, stack, {
println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Stack segment fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_error!(protection, stack, { interrupt_error!(protection, stack, {
println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Protection fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_error!(page, stack, { interrupt_error!(page, stack, {
let cr2: usize; let cr2: usize;
asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile"); asm!("mov rax, cr2" : "={rax}"(cr2) : : : "intel", "volatile");
println!("Page fault: {:>02X}:{:>016X} at {:>02X}:{:>016X}", stack.code, cr2, stack.cs, stack.rip); println!("Page fault: {:>02X}:{:>016X} at {:>02X}:{:>016X}", stack.code, cr2, stack.cs, stack.rip);
ksignal(SIGSEGV);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGSEGV);
}); });
interrupt_stack!(fpu, stack, { interrupt_stack!(fpu, stack, {
println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("FPU floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGFPE);
}); });
interrupt_error!(alignment_check, stack, { interrupt_error!(alignment_check, stack, {
println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Alignment check fault: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGBUS);
}); });
interrupt_stack!(machine_check, stack, { interrupt_stack!(machine_check, stack, {
println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Machine check fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGBUS);
}); });
interrupt_stack!(simd, stack, { interrupt_stack!(simd, stack, {
println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("SIMD floating point fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGFPE);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGFPE);
}); });
interrupt_stack!(virtualization, stack, { interrupt_stack!(virtualization, stack, {
println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip); println!("Virtualization fault at {:>02X}:{:>016X}", stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGBUS);
}); });
interrupt_error!(security, stack, { interrupt_error!(security, stack, {
println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip); println!("Security exception: {:X} at {:>02X}:{:>016X}", stack.code, stack.cs, stack.rip);
ksignal(SIGBUS);
stack_trace(); stack_trace();
loop { halt(); } ksignal(SIGBUS);
}); });

View file

@ -1,6 +1,6 @@
use alloc::arc::Arc; use alloc::arc::Arc;
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::{BTreeMap, Vec}; use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex; use spin::Mutex;
use arch; use arch;
@ -48,6 +48,8 @@ pub struct Context {
pub vfork: bool, pub vfork: bool,
/// Context is being waited on /// Context is being waited on
pub waitpid: Arc<WaitMap<ContextId, usize>>, pub waitpid: Arc<WaitMap<ContextId, usize>>,
/// Context should handle pending signals
pub pending: VecDeque<u8>,
/// Context should wake up at specified time /// Context should wake up at specified time
pub wake: Option<(u64, u64)>, pub wake: Option<(u64, u64)>,
/// The architecture specific context /// The architecture specific context
@ -94,6 +96,7 @@ impl Context {
cpu_id: None, cpu_id: None,
vfork: false, vfork: false,
waitpid: Arc::new(WaitMap::new()), waitpid: Arc::new(WaitMap::new()),
pending: VecDeque::new(),
wake: None, wake: None,
arch: arch::context::Context::new(), arch: arch::context::Context::new(),
kfx: None, kfx: None,

View file

@ -1,7 +1,8 @@
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
use arch; use arch;
use super::{contexts, Context, Status, CONTEXT_ID}; use context::{contexts, Context, Status, CONTEXT_ID};
use syscall;
/// Switch to the next context /// Switch to the next context
/// ///
@ -20,6 +21,7 @@ pub unsafe fn switch() -> bool {
let from_ptr; let from_ptr;
let mut to_ptr = 0 as *mut Context; let mut to_ptr = 0 as *mut Context;
let mut to_sig = None;
{ {
let contexts = contexts(); 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())); // 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() { if context.status == Status::Blocked && context.wake.is_some() {
let wake = context.wake.expect("context::switch: wake not set"); 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(); let mut context = context_lock.write();
if check_context(&mut context) { if check_context(&mut context) {
to_ptr = context.deref_mut() as *mut Context; to_ptr = context.deref_mut() as *mut Context;
to_sig = context.pending.pop_front();
break; break;
} }
} }
@ -68,6 +75,7 @@ pub unsafe fn switch() -> bool {
let mut context = context_lock.write(); let mut context = context_lock.write();
if check_context(&mut context) { if check_context(&mut context) {
to_ptr = context.deref_mut() as *mut Context; to_ptr = context.deref_mut() as *mut Context;
to_sig = context.pending.pop_front();
break; 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 // 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); 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); (&mut *from_ptr).arch.switch_to(&mut (&mut *to_ptr).arch);
true true
} }
extern fn signal_handler(signal: usize) {
println!("Signal handler: {}", signal);
syscall::exit(signal);
}

View file

@ -113,6 +113,7 @@ pub extern fn ksignal(signal: usize) {
println!("NAME {}", unsafe { ::core::str::from_utf8_unchecked(&context.name.lock()) }); 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 /// This is the kernel entry point for the primary CPU. The arch crate is responsible for calling this

130
kernel/syscall/driver.rs Normal file
View file

@ -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<usize> {
enforce_root()?;
//TODO
Ok(0)
}
pub fn physalloc(size: usize) -> Result<usize> {
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<usize> {
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<usize> {
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<usize> {
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<usize> {
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))
}
}

View file

@ -4,8 +4,10 @@ extern crate syscall;
pub use self::syscall::{data, error, flag, number, scheme}; pub use self::syscall::{data, error, flag, number, scheme};
pub use self::driver::*;
pub use self::fs::*; pub use self::fs::*;
pub use self::futex::futex; pub use self::futex::futex;
pub use self::privilege::*;
pub use self::process::*; pub use self::process::*;
pub use self::time::*; pub use self::time::*;
pub use self::validate::*; pub use self::validate::*;
@ -17,12 +19,18 @@ use self::number::*;
use context::ContextId; use context::ContextId;
use scheme::FileHandle; use scheme::FileHandle;
/// Driver syscalls
pub mod driver;
/// Filesystem syscalls /// Filesystem syscalls
pub mod fs; pub mod fs;
/// Fast userspace mutex /// Fast userspace mutex
pub mod futex; pub mod futex;
/// Privilege syscalls
pub mod privilege;
/// Process syscalls /// Process syscalls
pub mod process; 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_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_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_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_GETPID => getpid().map(ContextId::into),
SYS_IOPL => iopl(b),
SYS_CLONE => clone(b, stack).map(ContextId::into), 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_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
SYS_GETUID => getuid(), SYS_GETUID => getuid(),
SYS_GETGID => getgid(), SYS_GETGID => getgid(),

View file

@ -0,0 +1,85 @@
use collections::Vec;
use context;
use scheme;
use syscall::error::*;
use syscall::validate::validate_slice;
pub fn getegid() -> Result<usize> {
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<usize> {
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<usize> {
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<usize> {
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<usize> {
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<usize> {
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<usize> {
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)
}

View file

@ -7,19 +7,18 @@ use core::ops::DerefMut;
use spin::Mutex; use spin::Mutex;
use arch; use arch;
use arch::memory::{allocate_frame, allocate_frames, deallocate_frames, Frame}; use arch::memory::allocate_frame;
use arch::paging::{ActivePageTable, InactivePageTable, Page, PhysicalAddress, VirtualAddress, entry}; use arch::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, entry};
use arch::paging::temporary_page::TemporaryPage; use arch::paging::temporary_page::TemporaryPage;
use arch::start::usermode; use arch::start::usermode;
use context; use context;
use context::ContextId; use context::ContextId;
use context::memory::Grant;
use elf::{self, program_header}; use elf::{self, program_header};
use scheme::{self, FileHandle}; use scheme::{self, FileHandle};
use syscall; use syscall;
use syscall::data::Stat; use syscall::data::Stat;
use syscall::error::*; 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}; use syscall::validate::{validate_slice, validate_slice_mut};
pub fn brk(address: usize) -> Result<usize> { pub fn brk(address: usize) -> Result<usize> {
@ -838,27 +837,6 @@ pub fn exit(status: usize) -> ! {
unreachable!(); unreachable!();
} }
pub fn getegid() -> Result<usize> {
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<usize> {
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<usize> {
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<ContextId> { pub fn getpid() -> Result<ContextId> {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -866,224 +844,29 @@ pub fn getpid() -> Result<ContextId> {
Ok(context.id) Ok(context.id)
} }
pub fn getuid() -> Result<usize> { pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
let (ruid, euid) = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read(); let context = context_lock.read();
Ok(context.ruid as usize) (context.ruid, context.euid)
} };
pub fn iopl(_level: usize) -> Result<usize> { if sig > 0 && sig <= 0x7F {
//TODO
Ok(0)
}
pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
use syscall::flag::*;
let _context_lock = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?; 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<usize> {
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<usize> {
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<usize> {
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<usize> {
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<usize> {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let mut context = context_lock.write(); let mut context = context_lock.write();
if context.egid == 0 { if euid == 0
context.rgid = gid; || euid == context.ruid
context.egid = gid; || ruid == context.ruid
Ok(0)
} else {
Err(Error::new(EPERM))
}
}
pub fn setuid(uid: u32) -> Result<usize> {
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<usize> {
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(); context.pending.push_back(sig as u8);
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let mut context = context_lock.write();
context.scheme_ns = to;
}
Ok(0) Ok(0)
} } else {
Err(Error::new(EPERM))
pub fn virttophys(virtual_address: usize) -> Result<usize> { }
let active_table = unsafe { ActivePageTable::new() }; } else {
match active_table.translate(VirtualAddress::new(virtual_address)) { Err(Error::new(EINVAL))
Some(physical_address) => Ok(physical_address.get()),
None => Err(Error::new(EFAULT))
} }
} }

1
libstd

@ -1 +0,0 @@
Subproject commit 18d61d7e8a469fb0a05a9db4d00970b7e45954ad

1
libstd/openlibm Submodule

@ -0,0 +1 @@
Subproject commit 3c837e79655c4be724efb945a6345ec97c07635c

View file

@ -1,36 +1,36 @@
extern crate syscall; extern crate syscall;
use std::fs::File; use std::os::unix::process::CommandExt;
use std::io::{BufRead, BufReader, Read}; use std::process::Command;
pub fn main() { pub fn main() {
let names = [
"file",
"rand",
"tcp",
"udp"
];
let command = "sh";
let pid = unsafe { syscall::clone(0).unwrap() }; let pid = unsafe { syscall::clone(0).unwrap() };
if pid == 0 { if pid == 0 {
let rand = b"rand"; let mut name_ptrs = Vec::new();
syscall::setns(&[[rand.as_ptr() as usize, rand.len()]]).unwrap(); for name in names.iter() {
name_ptrs.push([name.as_ptr() as usize, name.len()]);
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 rand = File::open("rand:").unwrap(); syscall::setns(&name_ptrs).unwrap();
let mut byte = [0]; println!("Entering container: {}", command);
rand.read(&mut byte).unwrap();
println!("Rand: {}", byte[0]); let err = Command::new(command).exec();
panic!("contain: failed to launch {}: {}", command, err);
} else { } else {
let mut status = 0; let mut status = 0;
syscall::waitpid(pid, &mut status, 0).unwrap(); syscall::waitpid(pid, &mut status, 0).unwrap();
println!("Parent Namespace:"); println!("Exiting container: {:X}", status);
let file = BufReader::new(File::open("sys:scheme").unwrap());
for line in file.lines() {
let line = line.unwrap();
println!("{}", line);
}
} }
} }

@ -1 +1 @@
Subproject commit ff47394f57a8847313ac0850e029f5d21393fee6 Subproject commit 4b58de0b3c66634f95668e47466014138c5f71bd

2
rust

@ -1 +1 @@
Subproject commit 267bc54fbd2cfeadde7a87fc2aa3fb975ff58b6c Subproject commit f01add1a3bc3d86ee62f5819fa6ed9f79d453665