forked from syswonder/ruxos
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add some syscalls for x86_64 and aarch64.
- Loading branch information
thesayol
committed
Apr 8, 2024
1 parent
8c43a6a
commit 20da344
Showing
37 changed files
with
772 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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 | ||
); | ||
} | ||
syscall_body!(sys_cap_get, { | ||
unsafe { | ||
// allow all | ||
(*datap).effective = u32::MAX; | ||
(*datap).inheritable = u32::MAX; | ||
(*datap).permitted = u32::MAX; | ||
}; | ||
Ok(0) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
use crate::{ctypes::kstat, utils::char_ptr_to_str, *}; | ||
use alloc::{vec, vec::Vec}; | ||
use core::{ | ||
ffi::c_char, | ||
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 = char_ptr_to_str(filepath).unwrap().as_bytes().to_vec(); | ||
let path = name.clone(); | ||
debug!("sys_execve: new elf prog: {:?}", char_ptr_to_str(filepath)); | ||
|
||
// open file | ||
let fd = sys_open(filepath, ctypes::O_RDWR as i32, 0); | ||
|
||
// get file size | ||
let mut buf = ctypes::kstat { | ||
..Default::default() | ||
}; | ||
sys_fstat(fd, &mut buf as *const kstat as *mut _); | ||
let filesize = buf.st_size as usize; | ||
|
||
// read file | ||
let mut file = vec![0u8; filesize]; | ||
sys_read(fd, file.as_mut_ptr() as *mut _, filesize); | ||
debug!("sys_execve: read file size 0x{filesize:x}"); | ||
sys_close(fd); | ||
|
||
// parse elf | ||
let file = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(&file) | ||
.expect("parse ELF failed"); | ||
|
||
// 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; | ||
} | ||
} | ||
|
||
// copy LOAD segments | ||
let base = crate::sys_mmap(null_mut(), msize as usize, 0, 0, 0, 0) as usize; | ||
for seg in segs { | ||
if seg.p_type == elf::abi::PT_LOAD { | ||
let data = file.segment_data(&seg).unwrap(); | ||
let dst = (seg.p_vaddr as usize + base) as *mut u8; | ||
unsafe { dst.copy_from_nonoverlapping(data.as_ptr(), data.len()) }; | ||
} | ||
} | ||
|
||
// phdr | ||
let phdr = base + file.ehdr.e_phoff as usize; | ||
|
||
// get entry | ||
let entry = file.ehdr.e_entry as usize + base; | ||
|
||
// parse interpreter | ||
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 = data.as_ptr() as *const c_char; | ||
break; | ||
} | ||
} | ||
|
||
// platform | ||
#[cfg(target_arch = "aarch64")] | ||
let platform = b"aarch64".to_vec(); | ||
#[cfg(target_arch = "x86_64")] | ||
let platform = b"x86_64".to_vec(); | ||
#[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))] | ||
let platform = b"unknown".to_vec(); | ||
|
||
// get address of .text for debugging | ||
let text_section_addr = base | ||
+ file | ||
.section_header_by_name(".text") | ||
.unwrap() | ||
.unwrap() | ||
.sh_offset as usize; | ||
debug!( | ||
"sys_execve: loaded ELF in 0x{:x}, .text is 0x{:x}", | ||
base, text_section_addr | ||
); | ||
|
||
// create retval | ||
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, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
use core::ffi::c_char; | ||
|
||
mod auxv; | ||
mod load_elf; | ||
mod stack; | ||
|
||
use alloc::vec; | ||
|
||
use crate::{ | ||
imp::stat::{sys_getgid, sys_getuid}, | ||
sys_getegid, sys_geteuid, | ||
}; | ||
|
||
/// int execve(const char *pathname, char *const argv[], char *const envp[] ); | ||
pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { | ||
use auxv::*; | ||
|
||
let prog = load_elf::ElfProg::new(pathname); | ||
|
||
// get entry | ||
let mut entry = prog.entry; | ||
|
||
// if interp is needed | ||
let mut at_base = 0; | ||
if !prog.interp_path.is_null() { | ||
let interp_prog = load_elf::ElfProg::new(prog.interp_path); | ||
entry = interp_prog.entry; | ||
at_base = interp_prog.base; | ||
debug!("sys_execve: INTERP base is {:x}", at_base); | ||
}; | ||
|
||
// create stack | ||
let mut stack = stack::Stack::new(); | ||
|
||
let name = prog.name; | ||
let platform = prog.platform; | ||
|
||
// non 8B info | ||
stack.push(vec![0u8; 32], 16); | ||
let p_progname = stack.push(name, 16); | ||
let _p_plat = stack.push(platform, 16); // platform | ||
let p_rand = stack.push(prog.rand, 16); // rand | ||
|
||
// auxv | ||
// TODO: vdso and rand | ||
// TODO: a way to get pagesz instead of a constant | ||
let auxv = vec![ | ||
AT_PHDR, | ||
prog.phdr, | ||
AT_PHNUM, | ||
prog.phnum, | ||
AT_PHENT, | ||
prog.phent, | ||
AT_BASE, | ||
at_base, | ||
AT_PAGESZ, | ||
0x1000, | ||
AT_HWCAP, | ||
0, | ||
AT_CLKTCK, | ||
100, | ||
AT_FLAGS, | ||
0, | ||
AT_ENTRY, | ||
prog.entry, | ||
AT_UID, | ||
sys_getuid() as usize, | ||
AT_EUID, | ||
sys_geteuid() as usize, | ||
AT_EGID, | ||
sys_getegid() as usize, | ||
AT_GID, | ||
sys_getgid() as usize, | ||
AT_SECURE, | ||
0, | ||
AT_EXECFN, | ||
p_progname, | ||
AT_RANDOM, | ||
p_rand, | ||
AT_SYSINFO_EHDR, | ||
0, | ||
AT_IGNORE, | ||
0, | ||
AT_NULL, | ||
0, | ||
]; | ||
|
||
// handle envs and args | ||
let mut env_vec = vec![]; | ||
let mut arg_vec = vec![]; | ||
let mut argc = 0; | ||
|
||
let envp = envp as *const usize; | ||
unsafe { | ||
let mut i = 0; | ||
while *envp.add(i) != 0 { | ||
env_vec.push(*envp.add(i)); | ||
i += 1; | ||
} | ||
env_vec.push(0); | ||
} | ||
|
||
let argv = argv as *const usize; | ||
unsafe { | ||
let mut i = 0; | ||
loop { | ||
let p = *argv.add(i); | ||
if p == 0 { | ||
break; | ||
} | ||
arg_vec.push(p); | ||
argc += 1; | ||
i += 1; | ||
} | ||
|
||
arg_vec.push(0); | ||
} | ||
|
||
// push | ||
stack.push(auxv, 16); | ||
stack.push(env_vec, 8); | ||
stack.push(arg_vec, 8); | ||
let _sp = stack.push(vec![argc as usize], 8); | ||
|
||
// try run | ||
debug!( | ||
"sys_execve: run at entry 0x{entry:x}, then it will jump to 0x{:x} ", | ||
prog.entry | ||
); | ||
|
||
#[cfg(target_arch = "aarch64")] | ||
unsafe { | ||
core::arch::asm!(" | ||
mov sp, {} | ||
blr {} | ||
", | ||
in(reg)_sp, | ||
in(reg)entry, | ||
); | ||
} | ||
#[cfg(target_arch = "x86_64")] | ||
unsafe { | ||
core::arch::asm!(" | ||
mov rsp, {} | ||
jmp {} | ||
", | ||
in(reg)_sp, | ||
in(reg)entry, | ||
); | ||
} | ||
|
||
unreachable!("sys_execve: unknown arch"); | ||
} |
Oops, something went wrong.