Skip to content

Commit

Permalink
add system call sys_execve and some others
Browse files Browse the repository at this point in the history
  • Loading branch information
thesayol committed Mar 31, 2024
1 parent b75bad8 commit e587453
Show file tree
Hide file tree
Showing 18 changed files with 771 additions and 38 deletions.
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static_assertions = "1.1.0"
spin = { version = "0.9" }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
flatten_objects = { path = "../../crates/flatten_objects" }

elf = { version = "0.7", default-features = false }
bitflags = "2.2"

[build-dependencies]
Expand Down
40 changes: 40 additions & 0 deletions api/ruxos_posix_api/src/imp/cap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use core::ffi::c_int;

#[derive(Debug, Clone, Copy)]
struct UserCapHeader {
/// Linux Cap Version:
/// Version1 = 0x19980330,
/// Version2 = 0x20071026,
/// Version3 = 0x20080522,
version: u32,
pid: i32,
}

/// The effective, permitted, and inheritable fields are bit masks of the capabilities.
/// Note that the CAP_* values are bit indexes and need to be bit-shifted before ORing into the bit fields.
#[derive(Debug, Clone, Copy)]
struct UserCapData {
effective: u32,
permitted: u32,
inheritable: u32,
}

/// get thread capabilities. specific to Linux.
pub fn sys_cap_get(cap_user_header: usize, cap_user_data: usize) -> c_int {
let hdrp = cap_user_header as *const UserCapHeader;
let datap = cap_user_data as *mut UserCapData;
unsafe {
debug!(
"sys_cap_get <= pid {:?}, version {:x?} ",
(*hdrp).pid,
(*hdrp).version
);
}
unsafe {
// allow all
(*datap).effective = u32::MAX;
(*datap).inheritable = u32::MAX;
(*datap).permitted = u32::MAX;
};
syscall_body!(sys_cap_get, Ok(0))
}
41 changes: 41 additions & 0 deletions api/ruxos_posix_api/src/imp/execve/auxv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![allow(unused)]

pub const AT_NULL: usize = 0;
pub const AT_IGNORE: usize = 1;

pub const AT_EXECFD: usize = 2;

/// The address of the program headers of the executable.
pub const AT_PHDR: usize = 3;

pub const AT_PHENT: usize = 4;
pub const AT_PHNUM: usize = 5;
pub const AT_PAGESZ: usize = 6;

/// The base address of the program interpreter (usually, the dynamic linker).
pub const AT_BASE: usize = 7;

pub const AT_FLAGS: usize = 8;
pub const AT_ENTRY: usize = 9;
pub const AT_NOTELF: usize = 10;
pub const AT_UID: usize = 11;
pub const AT_EUID: usize = 12;
pub const AT_GID: usize = 13;
pub const AT_EGID: usize = 14;
pub const AT_PLATFORM: usize = 15;
pub const AT_HWCAP: usize = 16;
pub const AT_CLKTCK: usize = 17;
pub const AT_DCACHEBSIZE: usize = 19;
pub const AT_ICACHEBSIZE: usize = 20;
pub const AT_UCACHEBSIZE: usize = 21;
pub const AT_SECURE: usize = 23;
pub const AT_RANDOM: usize = 25;

/// A pointer to a string containing the pathname used to execute the program.
pub const AT_EXECFN: usize = 31;

/// The address of a page containing the vDSO that the kernel creates
pub const AT_SYSINFO_EHDR: usize = 33;

/// The entry point to the system call function in the vDSO. Not present/needed on all architectures (e.g., absent on x86-64).
pub const AT_SYSINFO: usize = 32;
170 changes: 170 additions & 0 deletions api/ruxos_posix_api/src/imp/execve/load_elf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
use crate::*;
use alloc::vec::Vec;
use core::{
ffi::c_char,
mem::size_of,
ptr::{null, null_mut},
};

#[derive(Debug)]
pub struct ElfProg {
pub name: Vec<u8>,
pub path: Vec<u8>,
pub platform: Vec<u8>,
pub rand: Vec<u64>,
pub base: usize,
pub entry: usize,
pub interp_path: *const c_char,
pub phent: usize,
pub phnum: usize,
pub phdr: usize,
}

impl ElfProg {
/// read elf from `path`, and copy LOAD segments to a alloacated memory
///
/// and load interp, if needed.
pub fn new(filepath: *const c_char) -> Self {
let name = ptr2vec(filepath);
let path = ptr2vec(filepath);
// info!("---------------------------------");
axlog::ax_println!("new elf prog: {}", vec_u8_to_str(&path));

// open file
let fd = sys_open(filepath, ctypes::O_RDWR as i32, 0);
// info!("open file, fd {}", fd);

// get file size
let buf = sys_mmap(null_mut(), size_of::<ctypes::kstat>(), 0, 0, 0, 0);
let bufsize = unsafe {
sys_fstat(fd, buf);
(*(buf as *const ctypes::kstat)).st_size as usize
};
sys_munmap(buf, size_of::<ctypes::kstat>());
// info!("fize size {}", bufsize);

// read file
let buf = sys_mmap(null_mut(), bufsize, 0, 0, fd, 0);
axlog::ax_println!("mmap to read file at {:p} size {:x}", buf, bufsize);
sys_read(fd, buf, bufsize);

// parse elf
let slice = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, bufsize) };
let file =
elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(slice).expect("Open test1");

// get program's LOAD mem size
let mut msize = 0;
let segs = file.segments().unwrap();
for seg in segs {
if seg.p_type == elf::abi::PT_LOAD {
msize += seg.p_memsz;
}
}
// info!("msize = {}", msize);

// mmap memory to copy LOAD segmeants
let a = crate::sys_mmap(null_mut(), msize as usize, 0, 0, 0, 0);
axlog::ax_println!("mmap to copy LOAD at {:p} size {:x}", a, msize);
let base = a as usize;
// info!("base = 0x{:x}", base);

// copy LOAD segs into base
for seg in segs {
if seg.p_type == elf::abi::PT_LOAD {
// info!("found LOAD: {:?}", seg);
let data = file.segment_data(&seg).unwrap();
let vaddr = seg.p_vaddr as usize + base;
unsafe {
// info!("write to {:x} datalen = {:x}", vaddr, data.len());
let c = vaddr as *mut u8;
for (i, d) in data.iter().enumerate() {
*(c.add(i)) = *d;
}
}
}
}

// phdr
let phdr = base + file.ehdr.e_phoff as usize;

// get entry
let entry = file.ehdr.e_entry as usize + base;
// info!("entry = 0x{:x}", entry);

// parse interpreter
// #[allow(non_upper_case_globals)]
// static static_libc_path: &str = "/lib/ld-musl-aarch64.so.1";
let mut interp_path = null::<c_char>();
for seg in file.segments().unwrap() {
if seg.p_type == elf::abi::PT_INTERP {
let data = file.segment_data(&seg).unwrap();
// interp_path = static_libc_path.as_ptr() as *const c_char;
interp_path = data.as_ptr() as *const c_char;
}
}

let sec = file.section_header_by_name(".got").unwrap().unwrap();
let addr = sec.sh_addr as usize + base;
ax_println!("got vaddr = {:#X}", addr);

// return Self
let mut platform = Vec::new();
for c in b"aarch64" {
platform.push(*c);
}
let ret = Self {
base,
entry,
name,
path,
platform,
rand: alloc::vec![1, 2],
interp_path,
phent: file.ehdr.e_phentsize as usize,
phnum: file.ehdr.e_phnum as usize,
phdr,
};

let text_off = file
.section_header_by_name(".text")
.unwrap()
.unwrap()
.sh_offset;
ax_println!(
"loaded ELF in 0x{:x}, .text is 0x{:x}",
ret.base,
ret.base + text_off as usize
);

// unmap file
sys_munmap(buf, bufsize);
ax_println!("unmap ELF file in memory at {:p} len {:x}", buf, bufsize);

ret
}
}

pub fn ptr2vec(s: *const c_char) -> Vec<u8> {
if s as usize == 0 {
return alloc::vec![];
}
let mut v = Vec::new();
unsafe {
let mut i = 0;
while *s.add(i) != 0 {
v.push(*s.add(i) as u8);
i += 1;
}
}
v
}

pub fn vec_u8_to_str(v: &Vec<u8>) -> &str {
if v.is_empty() {
return "";
}
let a = v.as_slice();
let s = core::str::from_utf8(a).unwrap();
s
}
Loading

0 comments on commit e587453

Please sign in to comment.