Skip to content
Snippets Groups Projects
Commit c4fb60f2 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Implement script file support

parent e43f5dda
No related branches found
No related tags found
No related merge requests found
...@@ -488,6 +488,14 @@ fn empty(context: &mut context::Context, reaping: bool) { ...@@ -488,6 +488,14 @@ fn empty(context: &mut context::Context, reaping: bool) {
} }
} }
struct ExecFile(FileHandle);
impl Drop for ExecFile {
fn drop(&mut self) {
let _ = syscall::close(self.0);
}
}
pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> { pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
let entry; let entry;
let mut sp = ::USER_STACK_OFFSET + ::USER_STACK_SIZE - 256; let mut sp = ::USER_STACK_OFFSET + ::USER_STACK_SIZE - 256;
...@@ -499,37 +507,62 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> { ...@@ -499,37 +507,62 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory args.push(arg.to_vec()); // Must be moved into kernel space before exec unmaps all memory
} }
let (uid, gid, canonical) = { let (uid, gid, mut canonical) = {
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();
(context.euid, context.egid, context.canonicalize(path)) (context.euid, context.egid, context.canonicalize(path))
}; };
let file = syscall::open(&canonical, syscall::flag::O_RDONLY)?; let mut stat: Stat;
let mut stat = Stat::default(); let mut data: Vec<u8>;
syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file, &mut stat)?; loop {
let file = ExecFile(syscall::open(&canonical, syscall::flag::O_RDONLY)?);
let mut perm = stat.st_mode & 0o7; stat = Stat::default();
if stat.st_uid == uid { syscall::file_op_mut_slice(syscall::number::SYS_FSTAT, file.0, &mut stat)?;
perm |= (stat.st_mode >> 6) & 0o7;
}
if stat.st_gid == gid {
perm |= (stat.st_mode >> 3) & 0o7;
}
if uid == 0 {
perm |= 0o7;
}
if perm & 0o1 != 0o1 { let mut perm = stat.st_mode & 0o7;
let _ = syscall::close(file); if stat.st_uid == uid {
return Err(Error::new(EACCES)); perm |= (stat.st_mode >> 6) & 0o7;
} }
if stat.st_gid == gid {
perm |= (stat.st_mode >> 3) & 0o7;
}
if uid == 0 {
perm |= 0o7;
}
//TODO: Only read elf header, not entire file. Then read required segments if perm & 0o1 != 0o1 {
let mut data = vec![0; stat.st_size as usize]; return Err(Error::new(EACCES));
syscall::file_op_mut_slice(syscall::number::SYS_READ, file, &mut data)?; }
let _ = syscall::close(file);
//TODO: Only read elf header, not entire file. Then read required segments
data = vec![0; stat.st_size as usize];
syscall::file_op_mut_slice(syscall::number::SYS_READ, file.0, &mut data)?;
drop(file);
if data.starts_with(b"#!") {
if let Some(line) = data[2..].split(|&b| b == b'\n').next() {
if ! args.is_empty() {
args.remove(0);
}
args.insert(0, canonical);
args.insert(0, line.to_vec());
canonical = {
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
context.canonicalize(line)
};
} else {
println!("invalid script {}", unsafe { str::from_utf8_unchecked(path) });
return Err(Error::new(ENOEXEC));
}
} else {
break;
}
}
match elf::Elf::from(&data) { match elf::Elf::from(&data) {
Ok(elf) => { Ok(elf) => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment