support running shebang executables

This commit is contained in:
Jianfeng Jiang
2023-03-07 16:10:15 +08:00
committed by Tate, Hongliang Tian
parent a084c3b687
commit 57297e0cd5
3 changed files with 81 additions and 17 deletions

View File

@ -25,11 +25,6 @@ use crate::{
};
use process::Process;
use crate::process::{
process_filter::ProcessFilter,
wait::{wait_child_exit, WaitOptions},
};
extern crate alloc;
extern crate lru;
#[macro_use]

View File

@ -11,14 +11,15 @@ use self::signal::sig_queues::SigQueues;
use self::signal::signals::kernel::KernelSignal;
use self::status::ProcessStatus;
use crate::fs::file_table::FileTable;
use crate::fs::fs_resolver::FsResolver;
use crate::fs::fs_resolver::{FsPath, FsResolver};
use crate::fs::utils::AccessMode;
use crate::prelude::*;
use crate::rights::Full;
use crate::thread::{thread_table, Thread};
use crate::tty::get_n_tty;
use crate::vm::vmar::Vmar;
use alloc::string::String;
use jinux_frame::sync::WaitQueue;
use jinux_frame::task::Task;
pub mod clone;
pub mod elf;
@ -386,3 +387,77 @@ impl Process {
pub fn get_init_process() -> Option<Arc<Process>> {
process_table::pid_to_process(INIT_PROCESS_PID)
}
/// Set up root vmar for an executable.
/// About recursion_limit: recursion limit is used to limit th recursion depth of shebang executables.
/// If the interpreter program(the program behind !#) of shebang executable is also a shebang,
/// then it will trigger recursion. We will try to setup root vmar for the interpreter program.
/// I guess for most cases, setting the recursion_limit as 1 should be enough.
/// because the interpreter game is usually an elf binary(e.g., /bin/bash)
pub fn setup_root_vmar(
executable_path: String,
argv: Vec<CString>,
envp: Vec<CString>,
fs_resolver: &FsResolver,
root_vmar: Vmar<Full>,
recursion_limit: usize,
) -> Result<()> {
use crate::fs::fs_resolver::AT_FDCWD;
let fs_path = FsPath::new(AT_FDCWD, &executable_path)?;
let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
// read the first page of file header
let mut file_header_buffer = [0u8; PAGE_SIZE];
file.read(&mut file_header_buffer)?;
if recursion_limit > 0
&& file_header_buffer.starts_with(b"!#")
&& file_header_buffer.contains(&b'\n')
{
return set_up_root_vmar_for_shebang(
argv,
envp,
&file_header_buffer,
fs_resolver,
root_vmar,
recursion_limit,
);
}
todo!()
}
fn set_up_root_vmar_for_shebang(
argv: Vec<CString>,
envp: Vec<CString>,
file_header_buffer: &[u8],
fs_resolver: &FsResolver,
root_vmar: Vmar<Full>,
recursion_limit: usize,
) -> Result<()> {
let first_line_len = file_header_buffer.iter().position(|&c| c == b'\n').unwrap();
// skip !#
let shebang_header = &file_header_buffer[2..first_line_len];
let mut shebang_argv = Vec::new();
for arg in shebang_header.split(|&c| c == b' ') {
let arg = CString::new(arg)?;
shebang_argv.push(arg);
}
if shebang_argv.len() != 1 {
return_errno_with_message!(
Errno::EINVAL,
"One and only one intpreter program should be specified"
);
}
for origin_arg in argv.into_iter() {
shebang_argv.push(origin_arg);
}
use alloc::string::ToString;
let shebang_path = shebang_argv[0].to_str()?.to_string();
setup_root_vmar(
shebang_path,
shebang_argv,
envp,
fs_resolver,
root_vmar,
recursion_limit - 1,
)
}

View File

@ -4,14 +4,12 @@ use crate::prelude::*;
use super::{allocate_tid, status::ThreadStatus, thread_table, Thread};
/// This struct is used to mark a thread is a kernel thread
/// The inner data of a kernel thread
pub struct KernelThread;
pub trait KernelThreadExt {
/// whether the thread is a kernel thread
fn is_kernel_thread(&self) -> bool;
/// get the kernel_thread structure
fn kernel_thread(&self) -> &KernelThread;
fn as_kernel_thread(&self) -> Option<&KernelThread>;
/// create a new kernel thread structure, **NOT** run the thread.
fn new_kernel_thread<F>(task_fn: F) -> Arc<Thread>
where
@ -30,12 +28,8 @@ pub trait KernelThreadExt {
}
impl KernelThreadExt for Thread {
fn is_kernel_thread(&self) -> bool {
self.data().downcast_ref::<KernelThread>().is_some()
}
fn kernel_thread(&self) -> &KernelThread {
self.data().downcast_ref::<KernelThread>().unwrap()
fn as_kernel_thread(&self) -> Option<&KernelThread> {
self.data().downcast_ref::<KernelThread>()
}
fn new_kernel_thread<F>(task_fn: F) -> Arc<Self>