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"]
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

View file

@ -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 \

View file

@ -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::<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
#[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");
}

View file

@ -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);
});

View file

@ -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<WaitMap<ContextId, usize>>,
/// Context should handle pending signals
pub pending: VecDeque<u8>,
/// 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,

View file

@ -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);
}

View file

@ -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

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::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(),

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 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<usize> {
@ -838,27 +837,6 @@ pub fn exit(status: usize) -> ! {
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> {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -866,224 +844,29 @@ pub fn getpid() -> Result<ContextId> {
Ok(context.id)
}
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 iopl(_level: usize) -> Result<usize> {
//TODO
Ok(0)
}
pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
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<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();
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)
}
pub fn virttophys(virtual_address: usize) -> Result<usize> {
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))
}
}

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;
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);
}
}

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

2
rust

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