Optimize the loading process of the ELF file
1. Load ld.so according to the executable automatically 2. Add the position-independent check for ELF file
This commit is contained in:
parent
318f1e6a4f
commit
1a00884e1c
@ -3,7 +3,7 @@ use std::path::Path;
|
||||
|
||||
use self::aux_vec::{AuxKey, AuxVec};
|
||||
use self::exec_loader::{load_exec_file_to_vec, load_file_to_vec};
|
||||
use super::elf_file::{ElfFile, ElfHeader, ProgramHeader, ProgramHeaderExt};
|
||||
use super::elf_file::{ElfFile, ElfHeader, ProgramHeader, ProgramHeaderExt, SegmentData};
|
||||
use super::process::ProcessBuilder;
|
||||
use super::task::Task;
|
||||
use super::thread::ThreadName;
|
||||
@ -117,12 +117,22 @@ fn new_process(
|
||||
file_path.to_string()
|
||||
};
|
||||
|
||||
let ldso_path = "/lib/ld-musl-x86_64.so.1";
|
||||
let ldso_elf_buf = load_file_to_vec(ldso_path, current_ref)
|
||||
.cause_err(|e| errno!(e.errno(), "cannot load ld.so"))?;
|
||||
|
||||
let exec_elf_file =
|
||||
ElfFile::new(&elf_buf).cause_err(|e| errno!(e.errno(), "invalid executable"))?;
|
||||
// Get the ldso_path of the executable
|
||||
let exec_interp_segment = exec_elf_file
|
||||
.program_headers()
|
||||
.find(|segment| segment.is_interpreter())
|
||||
.ok_or_else(|| errno!(EINVAL, "cannot find the interpreter segment"))?;
|
||||
let ldso_path = match exec_interp_segment.get_content(&exec_elf_file) {
|
||||
SegmentData::Undefined(bytes) => std::ffi::CStr::from_bytes_with_nul(bytes)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
_ => return_errno!(EINVAL, "cannot get ldso_path from executable"),
|
||||
};
|
||||
let ldso_elf_buf = load_file_to_vec(ldso_path, current_ref)
|
||||
.cause_err(|e| errno!(e.errno(), "cannot load ld.so"))?;
|
||||
let ldso_elf_file =
|
||||
ElfFile::new(&ldso_elf_buf).cause_err(|e| errno!(e.errno(), "invalid ld.so"))?;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use xmas_elf::{header, program, sections};
|
||||
use crate::prelude::*;
|
||||
|
||||
pub use xmas_elf::header::HeaderPt2 as ElfHeader;
|
||||
pub use xmas_elf::program::{ProgramHeader, ProgramIter};
|
||||
pub use xmas_elf::program::{ProgramHeader, ProgramIter, SegmentData};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ElfFile<'a> {
|
||||
@ -37,6 +37,10 @@ impl<'a> ElfFile<'a> {
|
||||
// Validate the ELF header
|
||||
xmas_elf::header::sanity_check(elf_inner)
|
||||
.map_err(|e| errno!(ENOEXEC, "invalid ELF header"))?;
|
||||
// Validate ELF type
|
||||
if elf_inner.header.pt2.type_().as_type() != xmas_elf::header::Type::SharedObject {
|
||||
return_errno!(ENOEXEC, "ELF is not position-independent");
|
||||
}
|
||||
// Validate the segments
|
||||
for segment in elf_inner.program_iter() {
|
||||
segment.validate()?;
|
||||
@ -45,18 +49,29 @@ impl<'a> ElfFile<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProgramHeaderExt {
|
||||
pub trait ProgramHeaderExt<'a> {
|
||||
fn loadable(&self) -> bool;
|
||||
fn is_interpreter(&self) -> bool;
|
||||
fn validate(&self) -> Result<()>;
|
||||
fn get_content(&self, elf_file: &ElfFile<'a>) -> SegmentData<'a>;
|
||||
}
|
||||
|
||||
impl<'a> ProgramHeaderExt for ProgramHeader<'a> {
|
||||
impl<'a> ProgramHeaderExt<'a> for ProgramHeader<'a> {
|
||||
/// Is the segment loadable?
|
||||
fn loadable(&self) -> bool {
|
||||
let type_ = self.get_type().unwrap();
|
||||
type_ == xmas_elf::program::Type::Load
|
||||
}
|
||||
|
||||
fn is_interpreter(&self) -> bool {
|
||||
let type_ = self.get_type().unwrap();
|
||||
type_ == xmas_elf::program::Type::Interp
|
||||
}
|
||||
|
||||
fn get_content(&self, elf_file: &ElfFile<'a>) -> SegmentData<'a> {
|
||||
self.get_data(&elf_file.elf_inner).unwrap()
|
||||
}
|
||||
|
||||
/// Do some basic sanity checks in case the ELF is corrupted somehow
|
||||
fn validate(&self) -> Result<()> {
|
||||
let ph64 = match self {
|
||||
|
Loading…
Reference in New Issue
Block a user