base: apply Red Bear patches on latest upstream/main
251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils, inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps, version +rb0.3.1, author attribution
This commit is contained in:
+35
-14
@@ -29,7 +29,6 @@ struct InitConfig {
|
||||
log_debug: bool,
|
||||
skip_cmd: Vec<String>,
|
||||
envs: BTreeMap<String, OsString>,
|
||||
cwd: OsString,
|
||||
}
|
||||
|
||||
impl InitConfig {
|
||||
@@ -45,18 +44,11 @@ impl InitConfig {
|
||||
log_debug,
|
||||
skip_cmd,
|
||||
envs: BTreeMap::from([("RUST_BACKTRACE".to_owned(), "1".into())]),
|
||||
cwd: "/scheme/initfs".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_root(
|
||||
unit_store: &mut UnitStore,
|
||||
config: &mut InitConfig,
|
||||
prefix: &Path,
|
||||
etcdir: &Path,
|
||||
cwd: &Path,
|
||||
) {
|
||||
fn switch_root(unit_store: &mut UnitStore, config: &mut InitConfig, prefix: &Path, etcdir: &Path) {
|
||||
eprintln!(
|
||||
"init: switchroot to {} {}",
|
||||
prefix.display(),
|
||||
@@ -70,7 +62,6 @@ fn switch_root(
|
||||
"LD_LIBRARY_PATH".to_owned(),
|
||||
prefix.join("lib").into_os_string(),
|
||||
);
|
||||
config.cwd = cwd.to_path_buf().into_os_string();
|
||||
|
||||
unit_store.config_dirs = vec![prefix.join("lib").join("init.d"), etcdir.join("init.d")];
|
||||
|
||||
@@ -122,16 +113,20 @@ fn switch_root(
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(f, "INIT: main() entered");
|
||||
}
|
||||
let mut init_config = InitConfig::new();
|
||||
let mut unit_store = UnitStore::new();
|
||||
let mut scheduler = Scheduler::new();
|
||||
eprintln!("INIT: about to switch_root (initfs)");
|
||||
|
||||
switch_root(
|
||||
&mut unit_store,
|
||||
&mut init_config,
|
||||
Path::new("/scheme/initfs"),
|
||||
Path::new("/scheme/initfs/etc"),
|
||||
Path::new("/scheme/initfs"),
|
||||
);
|
||||
|
||||
// Start logd first such that we can pass /scheme/log as stdio to all other services
|
||||
@@ -155,7 +150,6 @@ fn main() {
|
||||
&mut init_config,
|
||||
Path::new("/usr"),
|
||||
Path::new("/etc"),
|
||||
Path::new("/"),
|
||||
);
|
||||
{
|
||||
// FIXME introduce multi-user.target unit and replace the config dir iteration
|
||||
@@ -177,16 +171,43 @@ fn main() {
|
||||
}
|
||||
};
|
||||
for entry in entries {
|
||||
let file_name = entry.file_name().unwrap();
|
||||
if file_name.to_str().map_or(false, |name| name.starts_with('.')) {
|
||||
continue;
|
||||
}
|
||||
scheduler.schedule_start_and_report_errors(
|
||||
&mut unit_store,
|
||||
UnitId(entry.file_name().unwrap().to_str().unwrap().to_owned()),
|
||||
UnitId(file_name.to_str().unwrap().to_owned()),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
eprintln!("INIT: starting /usr scheduler step");
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(f, "BEFORE_STEP");
|
||||
}
|
||||
scheduler.step(&mut unit_store, &mut init_config);
|
||||
eprintln!("INIT: waitpid loop");
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(f, "AFTER_STEP");
|
||||
}
|
||||
|
||||
libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
|
||||
// Enter a null namespace containing only memory and pipe schemes. This
|
||||
// limits what daemons can access if they crash or misbehave. For the
|
||||
// initial bootstrap init (started directly by the kernel), there is no
|
||||
// prior ns_fd, so the kernel falls back to the root scheme list. If
|
||||
// setrens fails (e.g. ns_fd unavailable), we log a warning and continue
|
||||
// — the init process can still function with the full scheme set.
|
||||
if let Err(e) = libredox::call::setrens(0, 0) {
|
||||
eprintln!("INIT: warning, could not enter null namespace: {e}");
|
||||
eprintln!("INIT: continuing with full scheme set");
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(f, "INIT: setrens warning: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut status = 0;
|
||||
|
||||
+25
-3
@@ -1,4 +1,5 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::io::Write;
|
||||
|
||||
use crate::InitConfig;
|
||||
use crate::unit::{Unit, UnitId, UnitKind, UnitStore};
|
||||
@@ -55,8 +56,12 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
pub fn step(&mut self, unit_store: &mut UnitStore, init_config: &mut InitConfig) {
|
||||
let mut defer_count: BTreeMap<String, usize> = BTreeMap::new();
|
||||
'a: loop {
|
||||
let Some(job) = self.pending.pop_front() else {
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
let _ = writeln!(f, "STEP_DONE");
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -64,16 +69,33 @@ impl Scheduler {
|
||||
JobKind::Start => {
|
||||
let unit = unit_store.unit_mut(&job.unit);
|
||||
|
||||
let mut blocked = false;
|
||||
for dep in &unit.info.requires_weak {
|
||||
for pending_job in &self.pending {
|
||||
if &pending_job.unit == dep {
|
||||
self.pending.push_back(job);
|
||||
continue 'a;
|
||||
blocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if blocked { break; }
|
||||
}
|
||||
|
||||
if blocked {
|
||||
let cnt = defer_count.entry(job.unit.0.clone()).or_insert(0);
|
||||
*cnt += 1;
|
||||
if *cnt <= 3 {
|
||||
self.pending.push_back(job);
|
||||
continue 'a;
|
||||
}
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
let _ = writeln!(f, "FORCE {}", job.unit.0);
|
||||
}
|
||||
}
|
||||
|
||||
run(unit, init_config);
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
|
||||
let _ = writeln!(f, "RAN {}", unit.id.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ impl Command {
|
||||
command.args(process.args.iter().map(|arg| subst_env(arg)));
|
||||
command.env_clear();
|
||||
command.envs(&config.envs).envs(&process.envs);
|
||||
command.current_dir(&config.cwd);
|
||||
|
||||
let mut child = match command.spawn() {
|
||||
Ok(child) => child,
|
||||
|
||||
+9
-9
@@ -1,7 +1,7 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::ffi::OsString;
|
||||
use std::io::Read;
|
||||
use std::os::fd::{AsRawFd, RawFd};
|
||||
use std::os::fd::{AsRawFd, OwnedFd};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::{env, io};
|
||||
@@ -47,7 +47,7 @@ impl Service {
|
||||
command.envs(base_envs).envs(&self.envs);
|
||||
|
||||
let (mut read_pipe, write_pipe) = io::pipe().unwrap();
|
||||
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.as_raw_fd()) };
|
||||
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.into()) };
|
||||
|
||||
let mut child = match command.spawn() {
|
||||
Ok(child) => child,
|
||||
@@ -56,7 +56,6 @@ impl Service {
|
||||
return;
|
||||
}
|
||||
};
|
||||
drop(write_pipe);
|
||||
|
||||
match &self.type_ {
|
||||
ServiceType::Notify => match read_pipe.read_exact(&mut [0]) {
|
||||
@@ -70,15 +69,16 @@ impl Service {
|
||||
},
|
||||
ServiceType::Scheme(scheme) => {
|
||||
let mut new_fd = usize::MAX;
|
||||
|
||||
loop {
|
||||
match libredox::call::call_ro(
|
||||
match syscall::call_ro(
|
||||
read_pipe.as_raw_fd() as usize,
|
||||
unsafe { plain::as_mut_bytes(&mut new_fd) },
|
||||
syscall::CallFlags::FD | syscall::CallFlags::FD_UPPER,
|
||||
&[],
|
||||
) {
|
||||
Err(err) if err.is_interrupt() => continue,
|
||||
Err(syscall::Error {
|
||||
errno: syscall::EINTR,
|
||||
}) => continue,
|
||||
Ok(0) => {
|
||||
eprintln!("init: {command:?} exited without notifying readiness");
|
||||
return;
|
||||
@@ -117,12 +117,12 @@ impl Service {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: RawFd) {
|
||||
cmd.env(env, format!("{}", fd));
|
||||
unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) {
|
||||
cmd.env(env, format!("{}", fd.as_raw_fd()));
|
||||
unsafe {
|
||||
cmd.pre_exec(move || {
|
||||
// Pass notify pipe to child
|
||||
if libc::fcntl(fd, libc::F_SETFD, 0) == -1 {
|
||||
if libc::fcntl(fd.as_raw_fd(), libc::F_SETFD, 0) == -1 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user