Allow cloning of kernel threads. Userspace breaks potentially due to stack aliasing
This commit is contained in:
parent
4341a2d725
commit
ce50faf7ca
6 changed files with 109 additions and 38 deletions
|
@ -105,32 +105,33 @@ pub fn convert_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]>
|
|||
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
||||
}
|
||||
|
||||
pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> Result<usize> {
|
||||
match Call::from(a) {
|
||||
Ok(call) => match call {
|
||||
Call::Exit => exit(b),
|
||||
Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
|
||||
Call::Write => write(b, convert_slice(c as *const u8, d)?),
|
||||
Call::Open => open(convert_slice(b as *const u8, c)?, d),
|
||||
Call::Close => close(b),
|
||||
Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
|
||||
Call::GetPid => getpid(),
|
||||
Call::Dup => dup(b),
|
||||
Call::Brk => brk(b),
|
||||
Call::Iopl => iopl(b),
|
||||
Call::Clone => clone(b),
|
||||
Call::SchedYield => sched_yield()
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Unknown syscall {}", a);
|
||||
Err(err)
|
||||
#[no_mangle]
|
||||
pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> usize {
|
||||
#[inline(always)]
|
||||
fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize, stack: usize) -> Result<usize> {
|
||||
match Call::from(a) {
|
||||
Ok(call) => match call {
|
||||
Call::Exit => exit(b),
|
||||
Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
|
||||
Call::Write => write(b, convert_slice(c as *const u8, d)?),
|
||||
Call::Open => open(convert_slice(b as *const u8, c)?, d),
|
||||
Call::Close => close(b),
|
||||
Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
|
||||
Call::GetPid => getpid(),
|
||||
Call::Dup => dup(b),
|
||||
Call::Brk => brk(b),
|
||||
Call::Iopl => iopl(b),
|
||||
Call::Clone => clone(b, stack),
|
||||
Call::SchedYield => sched_yield()
|
||||
},
|
||||
Err(err) => {
|
||||
println!("Unknown syscall {}", a);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
|
||||
match handle(a, b, c, d, e, f) {
|
||||
match inner(a, b, c, d, e, f, stack) {
|
||||
Ok(value) => value,
|
||||
Err(value) => (-(value as isize)) as usize
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
///! Process syscalls
|
||||
|
||||
use core::mem;
|
||||
use core::str;
|
||||
|
||||
use arch;
|
||||
|
@ -42,9 +43,52 @@ pub fn brk(address: usize) -> Result<usize> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clone(flags: usize) -> Result<usize> {
|
||||
println!("Clone {:X}", flags);
|
||||
Ok(0)
|
||||
pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
|
||||
println!("Clone {:X}: {:X}", flags, stack_base);
|
||||
|
||||
let arch;
|
||||
let mut stack_option = None;
|
||||
let mut offset = 0;
|
||||
|
||||
// Copy from old process
|
||||
{
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::NoProcess)?;
|
||||
let context = context_lock.read();
|
||||
arch = context.arch.clone();
|
||||
if let Some(ref stack) = context.kstack {
|
||||
offset = stack_base - stack.as_ptr() as usize - mem::size_of::<usize>(); // Add clone ret
|
||||
let mut new_stack = stack.clone();
|
||||
unsafe {
|
||||
let func_ptr = new_stack.as_mut_ptr().offset(offset as isize);
|
||||
*(func_ptr as *mut usize) = arch::interrupt::syscall::clone_ret as usize;
|
||||
}
|
||||
stack_option = Some(new_stack);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up new process
|
||||
let pid;
|
||||
{
|
||||
let mut contexts = context::contexts_mut();
|
||||
let context_lock = contexts.new_context()?;
|
||||
let mut context = context_lock.write();
|
||||
context.arch = arch;
|
||||
if let Some(stack) = stack_option.take() {
|
||||
context.arch.set_stack(stack.as_ptr() as usize + offset);
|
||||
context.kstack = Some(stack);
|
||||
}
|
||||
context.blocked = false;
|
||||
pid = context.id;
|
||||
}
|
||||
|
||||
println!("Clone {}", pid);
|
||||
|
||||
unsafe { asm!("xchg bx, bx" : : : : "intel", "volatile"); }
|
||||
|
||||
unsafe { context::switch(); }
|
||||
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
pub fn exit(status: usize) -> ! {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue