f31522130f
Build system (5 gaps hardened): - COOKBOOK_OFFLINE defaults to true (fork-mode) - normalize_patch handles diff -ruN format - New 'repo validate-patches' command (25/25 relibc patches) - 14 patched Qt/Wayland/display recipes added to protected list - relibc archive regenerated with current patch chain Boot fixes (fixable): - Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset) - D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped) - redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped) - daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch) - udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async) - relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs - greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait) - greeter-ui: built and linked (header guard unification, sem_compat stubs removed) - mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps - greeter config: removed stale keymapd dependency from display/greeter services - prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified Unfixable (diagnosed, upstream): - i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort - kded6/greeter-ui: page fault 0x8 — Qt library null deref - Thread panics fd != -1 — Rust std library on Redox - DHCP timeout / eth0 MAC — QEMU user-mode networking - hwrngd/thermald — no hardware RNG/thermal in VM - live preload allocation — BIOS memory fragmentation, continues on demand
180 lines
5.2 KiB
Rust
180 lines
5.2 KiB
Rust
mod naming;
|
|
mod device_db;
|
|
mod scheme;
|
|
|
|
use std::env;
|
|
use std::os::fd::RawFd;
|
|
use std::sync::{Arc, Mutex};
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
|
|
use log::{error, info, warn, LevelFilter, Metadata, Record};
|
|
use redox_scheme::{
|
|
scheme::{SchemeState, SchemeSync},
|
|
SignalBehavior, Socket,
|
|
};
|
|
|
|
use naming::write_default_rules_file;
|
|
use scheme::UdevScheme;
|
|
|
|
struct StderrLogger {
|
|
level: LevelFilter,
|
|
}
|
|
|
|
impl log::Log for StderrLogger {
|
|
fn enabled(&self, metadata: &Metadata) -> bool {
|
|
metadata.level() <= self.level
|
|
}
|
|
fn log(&self, record: &Record) {
|
|
if self.enabled(record.metadata()) {
|
|
eprintln!("[{}] {}", record.level(), record.args());
|
|
}
|
|
}
|
|
fn flush(&self) {}
|
|
}
|
|
|
|
fn init_logging(level: LevelFilter) {
|
|
if log::set_boxed_logger(Box::new(StderrLogger { level })).is_err() {
|
|
return;
|
|
}
|
|
log::set_max_level(level);
|
|
}
|
|
|
|
unsafe fn get_init_notify_fd() -> Option<RawFd> {
|
|
let fd_str = match env::var("INIT_NOTIFY") {
|
|
Ok(v) => v,
|
|
Err(_) => {
|
|
info!("udev-shim: INIT_NOTIFY not set (expected for oneshot_async); init notification skipped");
|
|
return None;
|
|
}
|
|
};
|
|
match fd_str.parse::<RawFd>() {
|
|
Ok(fd) => {
|
|
libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC);
|
|
Some(fd)
|
|
}
|
|
Err(_) => {
|
|
warn!("udev-shim: INIT_NOTIFY is not a valid fd: {fd_str}");
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
fn notify_scheme_ready(notify_fd: RawFd, socket: &Socket, scheme: &mut UdevScheme) {
|
|
let cap_id = match scheme.scheme_root() {
|
|
Ok(id) => id,
|
|
Err(e) => {
|
|
error!("udev-shim: scheme_root failed: {e:?}");
|
|
return;
|
|
}
|
|
};
|
|
let cap_fd = match socket.create_this_scheme_fd(0, cap_id, 0, 0) {
|
|
Ok(fd) => fd,
|
|
Err(e) => {
|
|
error!("udev-shim: create_this_scheme_fd failed: {e:?}");
|
|
return;
|
|
}
|
|
};
|
|
|
|
if let Err(e) = syscall::call_wo(
|
|
notify_fd as usize,
|
|
&libredox::Fd::new(cap_fd).into_raw().to_ne_bytes(),
|
|
syscall::CallFlags::FD,
|
|
&[],
|
|
) {
|
|
warn!("udev-shim: init notification failed: {e:?}");
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let log_level = match env::var("UDEV_SHIM_LOG").as_deref() {
|
|
Ok("debug") => LevelFilter::Debug,
|
|
Ok("trace") => LevelFilter::Trace,
|
|
_ => LevelFilter::Info,
|
|
};
|
|
|
|
init_logging(log_level);
|
|
|
|
let mut scheme = UdevScheme::new();
|
|
|
|
match scheme.scan_pci_devices() {
|
|
Ok(n) => info!("udev-shim: enumerated {} PCI device(s)", n),
|
|
Err(e) => error!("udev-shim: PCI scan failed: {}", e),
|
|
}
|
|
|
|
match write_default_rules_file() {
|
|
Ok(path) => info!("udev-shim: wrote default rules to {path}"),
|
|
Err(err) => warn!("udev-shim: failed to write default rules: {err}"),
|
|
}
|
|
|
|
let socket = match Socket::create() {
|
|
Ok(s) => s,
|
|
Err(e) => {
|
|
error!("udev-shim: failed to create udev scheme: {e:?}");
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
let mut state = SchemeState::new();
|
|
|
|
if let Some(notify_fd) = unsafe { get_init_notify_fd() } {
|
|
notify_scheme_ready(notify_fd, &socket, &mut scheme);
|
|
}
|
|
|
|
if let Err(e) = libredox::call::setrens(0, 0) {
|
|
error!("udev-shim: failed to enter null namespace: {e:?}");
|
|
}
|
|
|
|
info!("udev-shim: registered scheme:udev");
|
|
|
|
let scheme = Arc::new(Mutex::new(scheme));
|
|
let scheme_clone = Arc::clone(&scheme);
|
|
thread::spawn(move || {
|
|
loop {
|
|
thread::sleep(Duration::from_secs(2));
|
|
if let Ok(mut s) = scheme_clone.lock() {
|
|
match s.scan_pci_devices() {
|
|
Ok(n) if n > 0 => info!("udev-shim: hotplug detected {} device(s)", n),
|
|
Err(e) => error!("udev-shim: hotplug scan failed: {}", e),
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
loop {
|
|
match socket.next_request(SignalBehavior::Restart) {
|
|
Ok(Some(request)) => {
|
|
match request.kind() {
|
|
redox_scheme::RequestKind::Call(request) => {
|
|
let response = {
|
|
let mut guard = match scheme.lock() {
|
|
Ok(guard) => guard,
|
|
Err(poisoned) => {
|
|
error!("udev-shim: recovering from poisoned scheme lock");
|
|
poisoned.into_inner()
|
|
}
|
|
};
|
|
|
|
request.handle_sync(&mut *guard, &mut state)
|
|
};
|
|
if let Err(e) = socket.write_response(response, SignalBehavior::Restart) {
|
|
error!("udev-shim: failed to write response: {e:?}");
|
|
}
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
Ok(None) => {
|
|
info!("udev-shim: scheme unmounted, exiting");
|
|
break;
|
|
}
|
|
Err(e) => {
|
|
error!("udev-shim: failed to read scheme request: {e:?}");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::process::exit(0);
|
|
}
|