fix(process): 修复copy_process的一些bug & 支持默认init进程传参 (#1083)

- 修复`copy_process`函数对标志位处理不正确的bug
- init进程搜索列表中,支持为默认init程序传入参数

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin 2025-02-06 22:51:51 +08:00 committed by GitHub
parent a05738e7cc
commit a3011dd24a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 49 additions and 20 deletions

View File

@ -22,7 +22,12 @@ use crate::{
use super::{cmdline::kenrel_cmdline_param_manager, initcall::do_initcalls};
const INIT_PROC_TRYLIST: [&str; 3] = ["/bin/dragonreach", "/bin/init", "/bin/sh"];
const INIT_PROC_TRYLIST: [(&str, Option<&str>); 4] = [
("/bin/dragonreach", None),
("/bin/init", None),
("/bin/sh", None),
("/bin/busybox", Some("init")),
];
pub fn initial_kernel_thread() -> i32 {
kernel_init().unwrap_or_else(|err| {
@ -88,6 +93,7 @@ fn switch_to_user() -> ! {
try_to_run_init_process(
path.as_c_str().to_str().unwrap(),
&mut proc_init_info,
&None,
&mut trap_frame,
)
.unwrap_or_else(|e| {
@ -98,8 +104,9 @@ fn switch_to_user() -> ! {
});
} else {
let mut ok = false;
for path in INIT_PROC_TRYLIST.iter() {
if try_to_run_init_process(path, &mut proc_init_info, &mut trap_frame).is_ok() {
for (path, ext_args) in INIT_PROC_TRYLIST.iter() {
if try_to_run_init_process(path, &mut proc_init_info, ext_args, &mut trap_frame).is_ok()
{
ok = true;
break;
}
@ -118,10 +125,22 @@ fn switch_to_user() -> ! {
fn try_to_run_init_process(
path: &str,
proc_init_info: &mut ProcInitInfo,
ext_args: &Option<&str>,
trap_frame: &mut TrapFrame,
) -> Result<(), SystemError> {
let mut args_to_insert = alloc::vec::Vec::new();
args_to_insert.push(CString::new(path).unwrap());
if let Some(ext_args) = ext_args {
// Split ext_args by whitespace and trim each part
for arg in ext_args.split_whitespace() {
args_to_insert.push(CString::new(arg.trim()).unwrap());
}
}
proc_init_info.proc_name = CString::new(path).unwrap();
proc_init_info.args.insert(0, CString::new(path).unwrap());
let elements_to_remove = args_to_insert.len();
let old_args = core::mem::replace(&mut proc_init_info.args, args_to_insert);
proc_init_info.args.extend(old_args);
if let Err(e) = run_init_process(proc_init_info, trap_frame) {
if e != SystemError::ENOENT {
error!(
@ -130,12 +149,12 @@ fn try_to_run_init_process(
);
}
proc_init_info.args.remove(0);
proc_init_info.args.drain(0..elements_to_remove);
return Err(e);
}
Ok(())
}
fn run_init_process(
proc_init_info: &ProcInitInfo,
trap_frame: &mut TrapFrame,

View File

@ -69,6 +69,11 @@ impl Signal {
warn!("Kill operation not support: pid={:?}", pid);
return Err(SystemError::ENOSYS);
}
// 暂时不支持发送信号给进程组
if pid.data() == 0 {
return Err(SystemError::ENOSYS);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
// 检查sig是否符合要求如果不符合要求则退出。
if !self.is_valid() {
@ -78,7 +83,7 @@ impl Signal {
let pcb = ProcessManager::find(pid);
if pcb.is_none() {
warn!("No such process.");
warn!("No such process: pid={:?}", pid);
return retval;
}

View File

@ -75,8 +75,6 @@ bitflags! {
const CLONE_NEWNET = 0x40000000;
/// 在新的 I/O 上下文中运行它
const CLONE_IO = 0x80000000;
/// 克隆时,与父进程共享信号结构体
const CLONE_SIGNAL = 0x00010000 | 0x00000800;
/// 克隆时将原本被设置为SIG_IGNORE的信号设置回SIG_DEFAULT
const CLONE_CLEAR_SIGHAND = 0x100000000;
}
@ -347,8 +345,11 @@ impl ProcessManager {
) -> Result<(), SystemError> {
let clone_flags = clone_args.flags;
// 不允许与不同namespace的进程共享根目录
if (clone_flags == (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS))
|| clone_flags == (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_FS)
if (clone_flags & (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS)
== (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS))
|| (clone_flags & (CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_FS))
== (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_FS)
{
return Err(SystemError::EINVAL);
}
@ -373,7 +374,7 @@ impl ProcessManager {
// 如果新进程使用不同的 pid 或 namespace
// 则不允许它与分叉任务共享线程组。
if clone_flags.contains(CloneFlags::CLONE_THREAD)
&& clone_flags.contains(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWPID)
&& !((clone_flags & (CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWPID)).is_empty())
{
return Err(SystemError::EINVAL);
// TODO: 判断新进程与当前进程namespace是否相同不同则返回错误
@ -381,12 +382,12 @@ impl ProcessManager {
// 如果新进程将处于不同的time namespace
// 则不能让它共享vm或线程组。
if clone_flags.contains(CloneFlags::CLONE_THREAD | CloneFlags::CLONE_VM) {
if !((clone_flags & (CloneFlags::CLONE_THREAD | CloneFlags::CLONE_VM)).is_empty()) {
// TODO: 判断time namespace不同则返回错误
}
if clone_flags.contains(CloneFlags::CLONE_PIDFD)
&& clone_flags.contains(CloneFlags::CLONE_DETACHED | CloneFlags::CLONE_THREAD)
&& !((clone_flags & (CloneFlags::CLONE_DETACHED | CloneFlags::CLONE_THREAD)).is_empty())
{
return Err(SystemError::EINVAL);
}
@ -483,6 +484,8 @@ impl ProcessManager {
)?;
*pcb.thread_pid.write() = new_pid;
}
// log::debug!("fork: clone_flags: {:?}", clone_flags);
// 设置线程组id、组长
if clone_flags.contains(CloneFlags::CLONE_THREAD) {
pcb.thread.write_irqsave().group_leader =
@ -493,14 +496,15 @@ impl ProcessManager {
}
} else {
pcb.thread.write_irqsave().group_leader = Arc::downgrade(pcb);
let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
unsafe {
let ptr = pcb.as_ref() as *const ProcessControlBlock as *mut ProcessControlBlock;
(*ptr).tgid = pcb.tgid;
(*ptr).tgid = pcb.pid;
}
}
// CLONE_PARENT re-uses the old parent
if clone_flags.contains(CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD) {
if !((clone_flags & (CloneFlags::CLONE_PARENT | CloneFlags::CLONE_THREAD)).is_empty()) {
*pcb.real_parent_pcb.write_irqsave() =
current_pcb.real_parent_pcb.read_irqsave().clone();

View File

@ -286,7 +286,7 @@ impl KernelThreadMechanism {
KernelThreadMechanism::__inner_create(
&create_info,
CloneFlags::CLONE_VM | CloneFlags::CLONE_SIGNAL,
CloneFlags::CLONE_VM | CloneFlags::CLONE_SIGHAND,
)
.unwrap_or_else(|e| panic!("Failed to create initial kernel thread, error: {:?}", e));
@ -313,7 +313,7 @@ impl KernelThreadMechanism {
.expect("kthreadadd should be run first");
let kthreadd_pid: Pid = Self::__inner_create(
&info,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGHAND,
)
.expect("Failed to create kthread daemon");
let pcb = ProcessManager::find(kthreadd_pid).unwrap();
@ -466,7 +466,7 @@ impl KernelThreadMechanism {
// create a new kernel thread
let result: Result<Pid, SystemError> = Self::__inner_create(
&info,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGNAL,
CloneFlags::CLONE_VM | CloneFlags::CLONE_FS | CloneFlags::CLONE_SIGHAND,
);
if result.is_err() {
// 创建失败

View File

@ -1255,6 +1255,7 @@ impl Syscall {
}
pub fn reboot() -> Result<usize, SystemError> {
log::info!("reboot");
unsafe { cpu_reset() };
}
}