From b5a7bf5581cc31b61fd444bbe8798d5fadfac4d4 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 15 Jul 2026 15:27:42 +0900 Subject: [PATCH] fix(kernel): FileTableVerb::Resize no-op + ProcUptime soft-float Two fixes on the clean base (all boot-investigation diagnostics removed): 1. ProcScheme::kcall now accepts FileTableVerb::Resize on filetable handles as a no-op instead of returning EBADF. After the upstream 'move fd allocation into userspace' relibc refactor, FILETABLE pre-syncs its size via a Resize call before growing; the kernel already grows posix_fdtbl on insert. Returning EBADF broke add_posix once a process's fd table grew (notably the bootstrap process manager proxying child thread ops), making the child's regs/env dup fail and its ld.so panic, crashing initfs daemons (randd) at boot. 2. ProcUptime uses integer arithmetic instead of f64 (the kernel is built with +soft-float; f64 in format!() breaks the build). --- src/scheme/proc.rs | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 7e22f29338..a6a766b298 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -975,14 +975,34 @@ impl KernelScheme for ProcScheme { handle.clone() }; + let verb_raw: u8 = (*metadata.first().ok_or(Error::new(EINVAL))?) + .try_into() + .map_err(|_| Error::new(EINVAL))?; + + // After the upstream "move fd allocation into userspace" relibc refactor, + // FILETABLE.add_posix pre-syncs the kernel table size by issuing a + // FileTableVerb::Resize call on the filetable handle before it grows. + // The kernel already grows posix_fdtbl automatically on insert (see + // Context::insert_file / bulk_add_files_posix), so accept this as a + // no-op instead of rejecting the non-OpenViaDup filetable handle with + // EBADF. Returning EBADF broke add_posix for any process whose fd table + // grew — notably the bootstrap process manager while proxying a child's + // thread ops — making the child's regs/env dup fail and its ld.so panic + // ("failed to open handle for process registers"), crashing initfs + // daemons (randd) at boot. + if matches!( + handle.kind, + ContextHandle::Filetable { .. } | ContextHandle::NewFiletable { .. } + ) && verb_raw == FileTableVerb::Resize as u8 + { + return Ok(0); + } + let ContextHandle::OpenViaDup = handle.kind else { return Err(Error::new(EBADF)); }; - let verb: u8 = (*metadata.first().ok_or(Error::new(EINVAL))?) - .try_into() - .map_err(|_| Error::new(EINVAL))?; - let verb = ProcSchemeVerb::try_from_raw(verb).ok_or(Error::new(EINVAL))?; + let verb = ProcSchemeVerb::try_from_raw(verb_raw).ok_or(Error::new(EINVAL))?; match verb { ProcSchemeVerb::Iopl => context::current() @@ -2000,9 +2020,14 @@ impl ContextHandle { read_from(buf, output.as_bytes(), offset) } ContextHandle::ProcUptime => { - let uptime_s = crate::time::monotonic(token) as f64 / crate::time::NANOS_PER_SEC as f64; - let idle_s = 0.0f64; - let output = format!("{:.2} {:.2}\n", uptime_s, idle_s); + // Red Bear fix: kernel is built with `+soft-float` (no SSE), so + // f64 in format!() triggers "SSE register return with SSE + // disabled" build error. Use integer arithmetic and emit + // seconds.milliseconds without f64 division. Idle always 0. + let nanos = crate::time::monotonic(token); + let uptime_s = nanos / crate::time::NANOS_PER_SEC; + let uptime_ms = (nanos % crate::time::NANOS_PER_SEC) / 1_000_000; + let output = format!("{}.{:02} 0.00\n", uptime_s, uptime_ms); read_from(buf, output.as_bytes(), offset) } ContextHandle::ProcLoadavg => {