`ProgramToLoad` only needs a `elf_inode: Arc<dyn Inode>` instead of a `Path`
This commit is contained in:
parent
808d298938
commit
71632a51b5
|
|
@ -8,7 +8,7 @@ use ostd::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{fs_resolver::FsResolver, path::Path},
|
fs::{fs_resolver::FsResolver, path::Path, utils::Inode},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{
|
process::{
|
||||||
posix_thread::{sigkill_other_threads, thread_table, PosixThread, ThreadLocal, ThreadName},
|
posix_thread::{sigkill_other_threads, thread_table, PosixThread, ThreadLocal, ThreadName},
|
||||||
|
|
@ -46,8 +46,8 @@ pub fn do_execve(
|
||||||
|
|
||||||
let fs_ref = ctx.thread_local.borrow_fs();
|
let fs_ref = ctx.thread_local.borrow_fs();
|
||||||
let fs_resolver = fs_ref.resolver().read();
|
let fs_resolver = fs_ref.resolver().read();
|
||||||
let program_to_load =
|
let elf_inode = elf_file.inode();
|
||||||
ProgramToLoad::build_from_file(elf_file.clone(), &fs_resolver, argv, envp, 1)?;
|
let program_to_load = ProgramToLoad::build_from_inode(elf_inode, &fs_resolver, argv, envp, 1)?;
|
||||||
|
|
||||||
// Ensure no other thread is concurrently performing exit_group or execve.
|
// Ensure no other thread is concurrently performing exit_group or execve.
|
||||||
// If such an operation is in progress, return EAGAIN.
|
// If such an operation is in progress, return EAGAIN.
|
||||||
|
|
@ -152,7 +152,7 @@ fn do_execve_no_return(
|
||||||
set_cpu_context(thread_local, user_context, &elf_load_info);
|
set_cpu_context(thread_local, user_context, &elf_load_info);
|
||||||
|
|
||||||
// Apply file-capability changes.
|
// Apply file-capability changes.
|
||||||
apply_caps_from_exec(process, posix_thread, elf_file)?;
|
apply_caps_from_exec(process, posix_thread, elf_file.inode())?;
|
||||||
|
|
||||||
// If this was a vfork child, reset vfork-specific state.
|
// If this was a vfork child, reset vfork-specific state.
|
||||||
reset_vfork_child(process);
|
reset_vfork_child(process);
|
||||||
|
|
@ -230,62 +230,62 @@ fn set_cpu_context(
|
||||||
debug!("user stack top: 0x{:x}", elf_load_info.user_stack_top);
|
debug!("user stack top: 0x{:x}", elf_load_info.user_stack_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the UID and GID in the credentials according to the ELF file.
|
/// Sets the UID and GID in the credentials according to the ELF inode.
|
||||||
///
|
///
|
||||||
/// The capabilities will be updated accordingly.
|
/// The capabilities will be updated accordingly.
|
||||||
fn apply_caps_from_exec(
|
fn apply_caps_from_exec(
|
||||||
process: &Process,
|
process: &Process,
|
||||||
posix_thread: &PosixThread,
|
posix_thread: &PosixThread,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// FIXME: We need to recalculate the capabilities during execve even the executable file
|
// FIXME: We need to recalculate the capabilities during execve even the executable inode
|
||||||
// does not have setuid/setgid bit.
|
// does not have setuid/setgid bit.
|
||||||
let credentials = posix_thread.credentials_mut();
|
let credentials = posix_thread.credentials_mut();
|
||||||
set_uid_from_elf(process, &credentials, elf_file)?;
|
set_uid_from_elf(process, &credentials, elf_inode)?;
|
||||||
set_gid_from_elf(process, &credentials, elf_file)?;
|
set_gid_from_elf(process, &credentials, elf_inode)?;
|
||||||
credentials.set_keep_capabilities(false)?;
|
credentials.set_keep_capabilities(false)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the UID in the credentials according to the ELF file.
|
/// Sets the UID in the credentials according to the ELF inode.
|
||||||
///
|
///
|
||||||
/// If the ELF file has the `set_uid` bit, the effective UID is set to the same value as the ELF
|
/// If the ELF inode has the `set_uid` bit, the effective UID is set to the same value as the ELF
|
||||||
/// file's UID.
|
/// inode's UID.
|
||||||
fn set_uid_from_elf(
|
fn set_uid_from_elf(
|
||||||
current: &Process,
|
current: &Process,
|
||||||
credentials: &Credentials<WriteOp>,
|
credentials: &Credentials<WriteOp>,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if elf_file.mode()?.has_set_uid() {
|
if elf_inode.mode()?.has_set_uid() {
|
||||||
let uid = elf_file.owner()?;
|
let uid = elf_inode.owner()?;
|
||||||
credentials.set_euid(uid);
|
credentials.set_euid(uid);
|
||||||
|
|
||||||
current.clear_parent_death_signal();
|
current.clear_parent_death_signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// No matter whether the ELF file has `set_uid` bit, SUID should be reset.
|
// No matter whether the ELF inode has `set_uid` bit, SUID should be reset.
|
||||||
credentials.reset_suid();
|
credentials.reset_suid();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the GID in the credentials according to the ELF file.
|
/// Sets the GID in the credentials according to the ELF inode.
|
||||||
///
|
///
|
||||||
/// If the ELF file has the `set_gid` bit, the effective GID is set to the same value as the ELF
|
/// If the ELF inode has the `set_gid` bit, the effective GID is set to the same value as the ELF
|
||||||
/// file's GID.
|
/// inode's GID.
|
||||||
fn set_gid_from_elf(
|
fn set_gid_from_elf(
|
||||||
current: &Process,
|
current: &Process,
|
||||||
credentials: &Credentials<WriteOp>,
|
credentials: &Credentials<WriteOp>,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if elf_file.mode()?.has_set_gid() {
|
if elf_inode.mode()?.has_set_gid() {
|
||||||
let gid = elf_file.group()?;
|
let gid = elf_inode.group()?;
|
||||||
credentials.set_egid(gid);
|
credentials.set_egid(gid);
|
||||||
|
|
||||||
current.clear_parent_death_signal();
|
current.clear_parent_death_signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// No matter whether the ELF file has `set_gid` bit, SGID should be reset.
|
// No matter whether the ELF inode has `set_gid` bit, SGID should be reset.
|
||||||
credentials.reset_sgid();
|
credentials.reset_sgid();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ pub use process::{
|
||||||
};
|
};
|
||||||
pub use process_filter::ProcessFilter;
|
pub use process_filter::ProcessFilter;
|
||||||
pub use process_vm::ProcessVm;
|
pub use process_vm::ProcessVm;
|
||||||
pub use program_loader::{check_executable_file, ProgramToLoad};
|
pub use program_loader::{check_executable_inode, ProgramToLoad};
|
||||||
pub use rlimit::ResourceType;
|
pub use rlimit::ResourceType;
|
||||||
pub use stats::collect_process_creation_count;
|
pub use stats::collect_process_creation_count;
|
||||||
pub use term_status::TermStatus;
|
pub use term_status::TermStatus;
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ fn create_init_task(
|
||||||
let fs_path = FsPath::try_from(executable_path)?;
|
let fs_path = FsPath::try_from(executable_path)?;
|
||||||
let elf_file = fs.resolver().read().lookup(&fs_path)?;
|
let elf_file = fs.resolver().read().lookup(&fs_path)?;
|
||||||
let program_to_load =
|
let program_to_load =
|
||||||
ProgramToLoad::build_from_file(elf_file, &fs_resolver, argv, envp, 1)?;
|
ProgramToLoad::build_from_inode(elf_file.inode(), &fs_resolver, argv, envp, 1)?;
|
||||||
let vmar = process.lock_vmar();
|
let vmar = process.lock_vmar();
|
||||||
program_to_load.load_to_vmar(vmar.unwrap(), &fs_resolver)?
|
program_to_load.load_to_vmar(vmar.unwrap(), &fs_resolver)?
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use xmas_elf::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{path::Path, utils::PATH_MAX},
|
fs::utils::{Inode, PATH_MAX},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
pub struct ElfHeaders {
|
pub struct ElfHeaders {
|
||||||
|
|
@ -92,8 +92,8 @@ impl ElfHeaders {
|
||||||
self.elf_header.pt2.type_.as_type() == header::Type::SharedObject
|
self.elf_header.pt2.type_.as_type() == header::Type::SharedObject
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads the LDSO path from the ELF file.
|
/// Reads the LDSO path from the ELF inode.
|
||||||
pub fn read_ldso_path(&self, elf_file: &Path) -> Result<Option<CString>> {
|
pub fn read_ldso_path(&self, elf_inode: &Arc<dyn Inode>) -> Result<Option<CString>> {
|
||||||
for program_header in &self.program_headers {
|
for program_header in &self.program_headers {
|
||||||
let type_ = program_header.get_type().map_err(|_| {
|
let type_ = program_header.get_type().map_err(|_| {
|
||||||
Error::with_message(Errno::ENOEXEC, "parse program header type fails")
|
Error::with_message(Errno::ENOEXEC, "parse program header type fails")
|
||||||
|
|
@ -109,9 +109,8 @@ impl ElfHeaders {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode = elf_file.inode();
|
|
||||||
let mut buffer = vec![0; file_size];
|
let mut buffer = vec![0; file_size];
|
||||||
inode.read_bytes_at(file_offset, &mut buffer)?;
|
elf_inode.read_bytes_at(file_offset, &mut buffer)?;
|
||||||
|
|
||||||
let ldso_path = CString::from_vec_with_nul(buffer).map_err(|_| {
|
let ldso_path = CString::from_vec_with_nul(buffer).map_err(|_| {
|
||||||
Error::with_message(
|
Error::with_message(
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{FsPath, FsResolver},
|
fs_resolver::{FsPath, FsResolver},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
utils::Inode,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::process_vm::{AuxKey, AuxVec},
|
process::process_vm::{AuxKey, AuxVec},
|
||||||
|
|
@ -29,20 +30,20 @@ use crate::{
|
||||||
/// initialize process init stack.
|
/// initialize process init stack.
|
||||||
pub fn load_elf_to_vmar(
|
pub fn load_elf_to_vmar(
|
||||||
vmar: &Vmar,
|
vmar: &Vmar,
|
||||||
elf_file: Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
elf_headers: ElfHeaders,
|
elf_headers: ElfHeaders,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
) -> Result<ElfLoadInfo> {
|
) -> Result<ElfLoadInfo> {
|
||||||
let ldso = lookup_and_parse_ldso(&elf_headers, &elf_file, fs_resolver)?;
|
let ldso = lookup_and_parse_ldso(&elf_headers, elf_inode, fs_resolver)?;
|
||||||
|
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
not(any(target_arch = "x86_64", target_arch = "riscv64")),
|
not(any(target_arch = "x86_64", target_arch = "riscv64")),
|
||||||
expect(unused_mut)
|
expect(unused_mut)
|
||||||
)]
|
)]
|
||||||
let (_range, entry_point, mut aux_vec) =
|
let (_range, entry_point, mut aux_vec) =
|
||||||
init_and_map_vmos(vmar, ldso, &elf_headers, &elf_file)?;
|
init_and_map_vmos(vmar, ldso, &elf_headers, elf_inode)?;
|
||||||
|
|
||||||
// Map the vDSO and set the entry.
|
// Map the vDSO and set the entry.
|
||||||
// Since the vDSO does not require being mapped to any specific address,
|
// Since the vDSO does not require being mapped to any specific address,
|
||||||
|
|
@ -69,11 +70,11 @@ pub fn load_elf_to_vmar(
|
||||||
|
|
||||||
fn lookup_and_parse_ldso(
|
fn lookup_and_parse_ldso(
|
||||||
headers: &ElfHeaders,
|
headers: &ElfHeaders,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
) -> Result<Option<(Path, ElfHeaders)>> {
|
) -> Result<Option<(Path, ElfHeaders)>> {
|
||||||
let ldso_file = {
|
let ldso_file = {
|
||||||
let Some(ldso_path) = headers.read_ldso_path(elf_file)? else {
|
let Some(ldso_path) = headers.read_ldso_path(elf_inode)? else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
// Our FS requires the path to be valid UTF-8. This may be too restrictive.
|
// Our FS requires the path to be valid UTF-8. This may be too restrictive.
|
||||||
|
|
@ -96,7 +97,7 @@ fn lookup_and_parse_ldso(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_ldso(vmar: &Vmar, ldso_file: &Path, ldso_elf: &ElfHeaders) -> Result<LdsoLoadInfo> {
|
fn load_ldso(vmar: &Vmar, ldso_file: &Path, ldso_elf: &ElfHeaders) -> Result<LdsoLoadInfo> {
|
||||||
let range = map_segment_vmos(ldso_elf, vmar, ldso_file)?;
|
let range = map_segment_vmos(ldso_elf, vmar, ldso_file.inode())?;
|
||||||
Ok(LdsoLoadInfo {
|
Ok(LdsoLoadInfo {
|
||||||
entry_point: range
|
entry_point: range
|
||||||
.relocated_addr_of(ldso_elf.entry_point())
|
.relocated_addr_of(ldso_elf.entry_point())
|
||||||
|
|
@ -116,7 +117,7 @@ fn init_and_map_vmos(
|
||||||
vmar: &Vmar,
|
vmar: &Vmar,
|
||||||
ldso: Option<(Path, ElfHeaders)>,
|
ldso: Option<(Path, ElfHeaders)>,
|
||||||
parsed_elf: &ElfHeaders,
|
parsed_elf: &ElfHeaders,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
) -> Result<(RelocatedRange, Vaddr, AuxVec)> {
|
) -> Result<(RelocatedRange, Vaddr, AuxVec)> {
|
||||||
// After we clear process vm, if any error happens, we must call exit_group instead of return to user space.
|
// After we clear process vm, if any error happens, we must call exit_group instead of return to user space.
|
||||||
let ldso_load_info = if let Some((ldso_file, ldso_elf)) = ldso {
|
let ldso_load_info = if let Some((ldso_file, ldso_elf)) = ldso {
|
||||||
|
|
@ -125,7 +126,7 @@ fn init_and_map_vmos(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let elf_map_range = map_segment_vmos(parsed_elf, vmar, elf_file)?;
|
let elf_map_range = map_segment_vmos(parsed_elf, vmar, elf_inode)?;
|
||||||
|
|
||||||
let mut aux_vec = {
|
let mut aux_vec = {
|
||||||
let ldso_base = ldso_load_info
|
let ldso_base = ldso_load_info
|
||||||
|
|
@ -135,7 +136,7 @@ fn init_and_map_vmos(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set AT_SECURE based on setuid/setgid bits of the executable file.
|
// Set AT_SECURE based on setuid/setgid bits of the executable file.
|
||||||
let mode = elf_file.inode().mode()?;
|
let mode = elf_inode.mode()?;
|
||||||
let secure = if mode.has_set_uid() || mode.has_set_gid() {
|
let secure = if mode.has_set_uid() || mode.has_set_gid() {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -183,7 +184,11 @@ pub struct ElfLoadInfo {
|
||||||
/// boundaries may not be page-aligned.
|
/// boundaries may not be page-aligned.
|
||||||
///
|
///
|
||||||
/// [`Vmo`]: crate::vm::vmo::Vmo
|
/// [`Vmo`]: crate::vm::vmo::Vmo
|
||||||
pub fn map_segment_vmos(elf: &ElfHeaders, vmar: &Vmar, elf_file: &Path) -> Result<RelocatedRange> {
|
pub fn map_segment_vmos(
|
||||||
|
elf: &ElfHeaders,
|
||||||
|
vmar: &Vmar,
|
||||||
|
elf_inode: &Arc<dyn Inode>,
|
||||||
|
) -> Result<RelocatedRange> {
|
||||||
let elf_va_range = get_range_for_all_segments(elf)?;
|
let elf_va_range = get_range_for_all_segments(elf)?;
|
||||||
|
|
||||||
let map_range = if elf.is_shared_object() {
|
let map_range = if elf.is_shared_object() {
|
||||||
|
|
@ -225,7 +230,7 @@ pub fn map_segment_vmos(elf: &ElfHeaders, vmar: &Vmar, elf_file: &Path) -> Resul
|
||||||
.relocated_addr_of(program_header.virtual_addr as Vaddr)
|
.relocated_addr_of(program_header.virtual_addr as Vaddr)
|
||||||
.expect("Address not covered by `get_range_for_all_segments`");
|
.expect("Address not covered by `get_range_for_all_segments`");
|
||||||
|
|
||||||
map_segment_vmo(program_header, elf_file, vmar, map_at)?;
|
map_segment_vmo(program_header, elf_inode, vmar, map_at)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,7 +302,7 @@ fn get_range_for_all_segments(elf: &ElfHeaders) -> Result<Range<Vaddr>> {
|
||||||
/// If needed, create additional anonymous mapping to represents .bss segment.
|
/// If needed, create additional anonymous mapping to represents .bss segment.
|
||||||
fn map_segment_vmo(
|
fn map_segment_vmo(
|
||||||
program_header: &ProgramHeader64,
|
program_header: &ProgramHeader64,
|
||||||
elf_file: &Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
vmar: &Vmar,
|
vmar: &Vmar,
|
||||||
map_at: Vaddr,
|
map_at: Vaddr,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
@ -318,8 +323,7 @@ fn map_segment_vmo(
|
||||||
let virtual_addr = program_header.virtual_addr as usize;
|
let virtual_addr = program_header.virtual_addr as usize;
|
||||||
debug_assert!(file_offset % PAGE_SIZE == virtual_addr % PAGE_SIZE);
|
debug_assert!(file_offset % PAGE_SIZE == virtual_addr % PAGE_SIZE);
|
||||||
let segment_vmo = {
|
let segment_vmo = {
|
||||||
let inode = elf_file.inode();
|
elf_inode.page_cache().ok_or(Error::with_message(
|
||||||
inode.page_cache().ok_or(Error::with_message(
|
|
||||||
Errno::ENOENT,
|
Errno::ENOENT,
|
||||||
"executable has no page cache",
|
"executable has no page cache",
|
||||||
))?
|
))?
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ use self::{
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{
|
fs::{
|
||||||
fs_resolver::{FsPath, FsResolver},
|
fs_resolver::{FsPath, FsResolver},
|
||||||
path::Path,
|
utils::{Inode, InodeType, Permission},
|
||||||
utils::{InodeType, Permission},
|
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
vm::vmar::Vmar,
|
vm::vmar::Vmar,
|
||||||
|
|
@ -22,7 +21,7 @@ use crate::{
|
||||||
/// This struct encapsulates the ELF file to be executed along with its header data,
|
/// This struct encapsulates the ELF file to be executed along with its header data,
|
||||||
/// the `argv` and the `envp` which is required for the program execution.
|
/// the `argv` and the `envp` which is required for the program execution.
|
||||||
pub struct ProgramToLoad {
|
pub struct ProgramToLoad {
|
||||||
elf_file: Path,
|
elf_inode: Arc<dyn Inode>,
|
||||||
file_first_page: Box<[u8; PAGE_SIZE]>,
|
file_first_page: Box<[u8; PAGE_SIZE]>,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
|
|
@ -36,18 +35,17 @@ impl ProgramToLoad {
|
||||||
/// then it will trigger recursion. We will try to setup VMAR for the interpreter.
|
/// then it will trigger recursion. We will try to setup VMAR for the interpreter.
|
||||||
/// I guess for most cases, setting the `recursion_limit` as 1 should be enough.
|
/// I guess for most cases, setting the `recursion_limit` as 1 should be enough.
|
||||||
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
|
/// because the interpreter is usually an elf binary(e.g., /bin/bash)
|
||||||
pub fn build_from_file(
|
pub fn build_from_inode(
|
||||||
elf_file: Path,
|
elf_inode: &Arc<dyn Inode>,
|
||||||
fs_resolver: &FsResolver,
|
fs_resolver: &FsResolver,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
recursion_limit: usize,
|
recursion_limit: usize,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let inode = elf_file.inode();
|
|
||||||
let file_first_page = {
|
let file_first_page = {
|
||||||
// Read the first page of file header, which must contain the ELF header.
|
// Read the first page of file header, which must contain the ELF header.
|
||||||
let mut buffer = Box::new([0u8; PAGE_SIZE]);
|
let mut buffer = Box::new([0u8; PAGE_SIZE]);
|
||||||
inode.read_bytes_at(0, &mut *buffer)?;
|
elf_inode.read_bytes_at(0, &mut *buffer)?;
|
||||||
buffer
|
buffer
|
||||||
};
|
};
|
||||||
if let Some(mut new_argv) = parse_shebang_line(&*file_first_page)? {
|
if let Some(mut new_argv) = parse_shebang_line(&*file_first_page)? {
|
||||||
|
|
@ -60,9 +58,9 @@ impl ProgramToLoad {
|
||||||
let fs_path = FsPath::try_from(filename.as_str())?;
|
let fs_path = FsPath::try_from(filename.as_str())?;
|
||||||
fs_resolver.lookup(&fs_path)?
|
fs_resolver.lookup(&fs_path)?
|
||||||
};
|
};
|
||||||
check_executable_file(&interpreter)?;
|
check_executable_inode(interpreter.inode())?;
|
||||||
return Self::build_from_file(
|
return Self::build_from_inode(
|
||||||
interpreter,
|
interpreter.inode(),
|
||||||
fs_resolver,
|
fs_resolver,
|
||||||
new_argv,
|
new_argv,
|
||||||
envp,
|
envp,
|
||||||
|
|
@ -71,7 +69,7 @@ impl ProgramToLoad {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
elf_file,
|
elf_inode: elf_inode.clone(),
|
||||||
file_first_page,
|
file_first_page,
|
||||||
argv,
|
argv,
|
||||||
envp,
|
envp,
|
||||||
|
|
@ -80,14 +78,12 @@ impl ProgramToLoad {
|
||||||
|
|
||||||
/// Loads the executable into the specified virtual memory space.
|
/// Loads the executable into the specified virtual memory space.
|
||||||
///
|
///
|
||||||
/// Returns a tuple containing:
|
/// Returns the information about the ELF loading process.
|
||||||
/// 1. The absolute path of the loaded executable.
|
|
||||||
/// 2. Information about the ELF loading process.
|
|
||||||
pub fn load_to_vmar(self, vmar: &Vmar, fs_resolver: &FsResolver) -> Result<ElfLoadInfo> {
|
pub fn load_to_vmar(self, vmar: &Vmar, fs_resolver: &FsResolver) -> Result<ElfLoadInfo> {
|
||||||
let elf_headers = ElfHeaders::parse_elf(&*self.file_first_page)?;
|
let elf_headers = ElfHeaders::parse_elf(&*self.file_first_page)?;
|
||||||
let elf_load_info = load_elf_to_vmar(
|
let elf_load_info = load_elf_to_vmar(
|
||||||
vmar,
|
vmar,
|
||||||
self.elf_file,
|
&self.elf_inode,
|
||||||
fs_resolver,
|
fs_resolver,
|
||||||
elf_headers,
|
elf_headers,
|
||||||
self.argv,
|
self.argv,
|
||||||
|
|
@ -98,21 +94,21 @@ impl ProgramToLoad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_executable_file(path: &Path) -> Result<()> {
|
pub fn check_executable_inode(inode: &Arc<dyn Inode>) -> Result<()> {
|
||||||
if path.type_().is_directory() {
|
if inode.type_().is_directory() {
|
||||||
return_errno_with_message!(Errno::EISDIR, "the file is a directory");
|
return_errno_with_message!(Errno::EISDIR, "the inode is a directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.type_() == InodeType::SymLink {
|
if inode.type_() == InodeType::SymLink {
|
||||||
return_errno_with_message!(Errno::ELOOP, "the file is a symbolic link");
|
return_errno_with_message!(Errno::ELOOP, "the inode is a symbolic link");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !path.type_().is_regular_file() {
|
if !inode.type_().is_regular_file() {
|
||||||
return_errno_with_message!(Errno::EACCES, "the path is not a regular file");
|
return_errno_with_message!(Errno::EACCES, "the inode is not a regular file");
|
||||||
}
|
}
|
||||||
|
|
||||||
if path.inode().check_permission(Permission::MAY_EXEC).is_err() {
|
if inode.check_permission(Permission::MAY_EXEC).is_err() {
|
||||||
return_errno_with_message!(Errno::EACCES, "the path is not executable");
|
return_errno_with_message!(Errno::EACCES, "the inode is not executable");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
path::Path,
|
path::Path,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{check_executable_file, do_execve},
|
process::{check_executable_inode, do_execve},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn sys_execve(
|
pub fn sys_execve(
|
||||||
|
|
@ -75,7 +75,7 @@ fn lookup_executable_file(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
check_executable_file(&path)?;
|
check_executable_inode(path.inode())?;
|
||||||
|
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue