asterinas/kernel/src/syscall/execve.rs

89 lines
2.2 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
use ostd::arch::cpu::context::UserContext;
use super::{constants::*, SyscallReturn};
use crate::{
fs::{
file_table::FileDesc,
fs_resolver::{FsPath, AT_FDCWD},
path::Path,
},
prelude::*,
process::{check_executable_file, do_execve},
};
pub fn sys_execve(
filename_ptr: Vaddr,
argv_ptr_ptr: Vaddr,
envp_ptr_ptr: Vaddr,
ctx: &Context,
user_context: &mut UserContext,
) -> Result<SyscallReturn> {
let elf_file = {
let flags = OpenFlags::empty();
lookup_executable_file(AT_FDCWD, filename_ptr, flags, ctx)?
};
do_execve(elf_file, argv_ptr_ptr, envp_ptr_ptr, ctx, user_context)?;
Ok(SyscallReturn::NoReturn)
}
pub fn sys_execveat(
dfd: FileDesc,
filename_ptr: Vaddr,
argv_ptr_ptr: Vaddr,
envp_ptr_ptr: Vaddr,
flags: u32,
ctx: &Context,
user_context: &mut UserContext,
) -> Result<SyscallReturn> {
let elf_file = {
let flags = OpenFlags::from_bits(flags)
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?;
lookup_executable_file(dfd, filename_ptr, flags, ctx)?
};
do_execve(elf_file, argv_ptr_ptr, envp_ptr_ptr, ctx, user_context)?;
Ok(SyscallReturn::NoReturn)
}
fn lookup_executable_file(
dfd: FileDesc,
filename_ptr: Vaddr,
flags: OpenFlags,
ctx: &Context,
) -> Result<Path> {
let filename = ctx
.user_space()
.read_cstring(filename_ptr, MAX_FILENAME_LEN)?;
let path = {
let filename = filename.to_string_lossy();
let fs_path = if flags.contains(OpenFlags::AT_EMPTY_PATH) && filename.is_empty() {
FsPath::from_fd(dfd)?
} else {
FsPath::from_fd_and_path(dfd, &filename)?
};
let fs_ref = ctx.thread_local.borrow_fs();
let fs_resolver = fs_ref.resolver().read();
if flags.contains(OpenFlags::AT_SYMLINK_NOFOLLOW) {
fs_resolver.lookup_no_follow(&fs_path)?
} else {
fs_resolver.lookup(&fs_path)?
}
};
check_executable_file(&path)?;
Ok(path)
}
bitflags::bitflags! {
struct OpenFlags: u32 {
const AT_EMPTY_PATH = 0x1000;
const AT_SYMLINK_NOFOLLOW = 0x100;
}
}