Commit 79685cbe (AF_INET6 socket support) introduced
String::with_capacity() at socket.rs:80 but only imported
ToString from alloc::string, not String itself. This caused
E0433 'cannot find type String in this scope' during canonical
build (edition 2024 with -Z build-std).
Fix: add String to the existing alloc::string import.
Commit dd2cd443 introduced unsafe fn convert_event(*const Event,
*mut epoll_event) but dereferenced both pointers without unsafe
blocks. Edition 2024 (relibc's top-level Cargo.toml) enforces
unsafe-op-in-unsafe-fn by default with -D, so this caused rustc
E0133 errors during canonical build:
error[E0133]: dereference of raw pointer is unsafe and requires
unsafe block
--> src/platform/redox/epoll.rs:139:17 / 143:5
The fix wraps each deref in an explicit unsafe { } block with a
SAFETY justification, keeping the outer unsafe fn signature so the
validity proof stays on callers (the rest of epoll.rs already
upholds those invariants).
No semantic change — same machine code after the wrap, just edition
2024-compliant source.
Adds AF_INET6 (10) to the socket() implementation so that
applications using IPv6 sockets can obtain a usable file descriptor.
Bind and connect accept sockaddr_in6 and translate the 16-byte IPv6
address into a scheme path string of the form
[hh:hh:hh:hh:hh:hh:hh:hh]:port (for global unicast)
[hh:hh:hh:hh:hh:hh:hh:hh%scope]:port (when scope id is set)
with each hh printed in lower-case hexadecimal exactly as smoltcp
accepts. The leading-zero elision that canonical IPv6 text requires
is left to the receiving netcfg /scheme parser; this format is
deliberately reversible (every byte is visible) so the round-trip
through bind -> getsockname is unambiguous.
The corresponding parse path in netstack/scheme/mod.rs::parse_endpoint
is extended with a parallel refactor: it splits on '[' for bracketed
input and on the first ':' otherwise, and then dispatches Ipv6Address
vs Ipv4Address::from_str based on whether ':' appears in the host.
The scope suffix (\%id) is stripped before the FromStr call, matching
the format this commit writes.
Verified locally with 'cargo check' on relibc; netstack will be
re-validated by the canonical build-redbear.sh run.
The kernel can inject a synthetic event with id == EVENT_TIMEOUT_ID
when the requested timeout fires. The previous loop iterated the raw
event buffer with events.add(i) (in epoll_event strides) and then
interpreted the result as a syscall::Event, which produced out-of-bounds
reads when the kernel interleaved timeout events with real events.
Two changes:
1. Cast events to Event* first, then add i in Event strides so the
pointer arithmetic matches the buffer the kernel filled.
2. Filter out entries with id == EVENT_TIMEOUT_ID before copying them
into the user-visible epoll_event array.
Adds a regression test that builds a synthetic Event buffer with a
timeout entry interleaved and verifies that the timeout entry is
dropped while siblings are preserved.
Sync the relibc fork with 50 upstream commits (socket layer rework,
exec/signal/ptrace/path/timer updates, pthread cleanup, ld_so lifecycle
work bringing mark_ready/run_fini into the tree, dynamically-linked
init support, start.rs allocator-model rewrite, test harness updates).
Satisfies the verify-fork-functions gate (2 previously-missing ld_so
functions now present).
Conflicts resolved (4 files; 46 auto-merged):
- src/start.rs: took upstream's version wholesale. Upstream moved
allocator/linker initialization into ld_so's new lifecycle (the
mark_ready/run_fini work this merge brings in), superseding the RB
alloc_init cluster; the old model's function was already merged out
and its lone call would not compile.
- redox-rt/src/sys.rs: kept the RB refresh flow with the non-fatal
lseek fallback (upstream adopted the refresh as a fatal '?' —
RB's conservative fallback protects spawn for uid-dropped /
namespace-restricted exec where the kernel cannot refresh).
- src/platform/redox/exec.rs: kept the RB root exec-permission bypass
(ruid/euid != 0 gate, Linux-matching behavior).
- Cargo.lock: syn 2.0.118 -> 2.0.119 (upstream).
Verified: repo cook relibc --force-rebuild successful;
verify-fork-functions.sh --no-fetch relibc passes;
all 9 forks now pass the gate.
fcntl(F_DUPFD_CLOEXEC) reached redox_rt/kernel with the POSIX/C value 1030
instead of the Redox syscall value (syscall::F_DUPFD_CLOEXEC=5). redox_rt did
not recognize it as a dup, forwarded the raw command to the kernel, and the
kernel's fcntl fell through to its EINVAL catch-all. That made
OwnedFd::try_clone() return EINVAL, which broke tokio Runtime::build() (its I/O
reactor try_clones the epoll fd) for every tokio user on Redox: all the zbus
system daemons (sessiond/polkit/udisks/upower) and the login shell. F_DUPFD and
plain dup worked because they share the same value in both namespaces;
F_DUPFD_CLOEXEC was the sole untranslated command.
Also drop the ineffective epoll_ctl EINVAL/EBADF retry loop: it was based on a
disproven 'transient scheme churn' theory; epoll registrations always succeed
immediately. The real dup failure is fixed above.
Registering an fd with /scheme/event can transiently fail with
EINVAL/EBADF while the scheme backing the fd is still starting up or the
fd table is churning during early boot (e.g. a tokio/mio reactor built by
a daemon that races ahead of ipcd's uds_stream scheme). Without recovery,
tokio's Runtime::build aborts the whole runtime with "Invalid argument
(os error 22)", killing every zbus daemon (sessiond, polkit, udisks,
upower) and any tokio program including the login shell.
Retry the /scheme/event registration write with a 5ms backoff, up to ~2s,
on EINVAL/EBADF; a genuinely permanent failure still surfaces after the
bounded window. Redox-only. This is the registration-site counterpart to
the existing park-path recovery in the P0-epoll-redox-recovery tokio patch.
The copied child table did not reliably retain the thread and process descriptors at the numbers exported through auxv. Explicitly clone both descriptors into the selected child table before loading the image, and remove the ineffective parent-handle leak.
posix_spawn creates a new context and returns its thread fd to the
parent. The kernel currently does not keep a self-reference to the child
context's thread fd, so when the parent closes its handle, the child's
thread object may be destroyed before the dynamic linker reads
AT_REDOX_THR_FD from auxv and opens regs/env. Leak the parent handle
until the kernel is fixed to retain a reference per context.
The previous pipe2 implementation used redox_rt::sys::open() which goes
through the FILETABLE's insert_upper mechanism. This can collide with
the untracked namespace fd (ns_fd) stored in DYNAMIC_PROC_INFO, causing
the kernel to overwrite the namespace fd entry with a pipe scheme root
entry. Subsequent open() calls then resolve to the wrong scheme, and
kdup fails with EBADF because it receives a write-end (odd) ID instead
of a read-end (even) ID.
Fix: bypass the open() function entirely and use raw syscall::openat +
syscall::dup, then register both fds with register_external_fd so the
FILETABLE tracks them correctly.