Files
RedBear-OS/local/docs/RELIBC-IMPLEMENTATION-PLAN.md
T
vasilito 761e0d9de7 state: 36/48 KDE packages build, 12 blocked — honest final state
The literal task 'build ALL KDE packages' cannot be 100% completed
because 12 packages require upstream dependencies not available on Redox:
- kirigami + plasma* (4): QML JIT disabled — no QQuickWindow/QQmlEngine
- kwin real build (1): Qt6::Sensors port needed
- breeze + kf6-kio + kf6-knewstuff + kde-cli-tools (4): source issues
- plasma extras (3): transitive blockers

What WAS completed:
- Cookbook topological sort fix (root cause — all deps now correct order)
- kf6-attica recipe (183 files, 2.4MB pkgar)
- 12 I2C/GPIO/UCSI daemons archived as durable patches
- Source archival system (make sources)
- Config + all docs synced, no contradictions
2026-04-30 01:54:09 +01:00

455 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Red Bear OS relibc Implementation Plan
## Purpose
This document is the canonical engineering plan for closing the remaining POSIX gaps in relibc,
the Rust-based C library used by Red Bear OS (built on Redox).
**Implementation status by phase:**
| Phase | Status | Details |
|-------|--------|---------|
| I1 — `in6_pktinfo` + IPv6 socket options | ✅ **Completed** | `struct in6_pktinfo`, `IPV6_PKTINFO=50`, `IPV6_RECVPKTINFO=49` via `P3-in6-pktinfo.patch` |
| I2 — `getrlimit`/`setrlimit` improvement | ✅ **Completed** | Advisory libc-level implementation: `setrlimit` returns `Ok`, sensible defaults for all `RLIMIT_*` via `P3-getrlimit-getdtablesize.patch` |
| I3 — `timerfd` `TFD_TIMER_CANCEL_ON_SET` | ✅ **Flag accepted** | Flag in `timerfd_settime` supported mask; actual cancel-on-clock-set detection kernel-blocked. Documented as bounded compatibility surface |
| I4 — `ifaddrs` live discovery | 🚧 **Improved, still synthetic** | 3 entries (loopback, eth0 with addr, wlan0); still hardcoded, full scheme-based enumeration deferred |
| I5 — Plain-source TODO headers | ✅ **Partially completed** | `spawn.h` with `posix_spawn` (fork+exec wrapper), `threads.h` with correct C11 types/constants, both cbindgen headers generated; `mqueue.h`, `iconv.h`, `wordexp.h` deferred |
It replaces and supersedes the R0R6 phase structure in `RELIBC-COMPLETENESS-AND-ENHANCEMENT-PLAN.md`.
The evidence-model labels (`plain-source-visible`, `recipe-applied`, `test-present`) remain valid and
should continue to be used in all documentation.
## Evidence Model (unchanged)
- **plain-source-visible**: present in upstream-owned `recipes/core/relibc/source/` without recipe patches
- **recipe-applied**: added only when the active relibc recipe replays Red Bear patch carriers
- **test-present**: test coverage exists in the source tree or active patch chain
- **kernel-blocked**: functionality requires a Redox kernel syscall that does not yet exist
---
## Gap Inventory
### G1 — `struct in6_pktinfo` (QtNetwork blocker)
| Field | Value |
|-------|-------|
| **Status** | ✅ Implemented (`P3-in6-pktinfo.patch`) |
| **Root cause** | (resolved) Missing struct + constants added to netinet_in/mod.rs |
| **Blocks** | `QtNetwork` (and any IPv6 advanced socket usage) |
| **Category** | Immediate — **completed** |
`in6_pktinfo` is defined in `<netinet/in.h>` per POSIX and carries the source/destination IPv6 address
plus interface index for `IPV6_PKTINFO` ancillary data on `sendmsg`/`recvmsg`.
Standard layout:
```c
struct in6_pktinfo {
struct in6_addr ipi6_addr; // src/dst IPv6 address
unsigned int ipi6_ifindex; // interface index
};
```
**Also missing from `netinet_in/mod.rs`**: `IPV6_PKTINFO` (socket option constant = 50),
`IPV6_RECVPKTINFO` (49). `IPPROTO_IPV6` (41) already exists in relibc.
---
### G2 — `getrlimit(2)` kernel backing
| Field | Value |
|-------|-------|
| **Status** | ✅ Improved — `setrlimit` no longer returns `EPERM`, returns `Ok` instead. Additional resource limits now include `RLIMIT_NPROC`, `RLIMIT_NICE`, `RLIMIT_RTPRIO`, `RLIMIT_MSGQUEUE` with sensible defaults |
| **Root cause** | Redox microkernel has no `SYS_GETRLIMIT` / `SYS_SETRLIMIT` syscalls — in a microkernel architecture, resource limits are a libc-level policy concern, not kernel-enforced |
| **Current impl** | Returns sensible defaults for all `RLIMIT_*` constants; `setrlimit()` now returns success (advisory — no kernel enforcement) |
| **Blocks** | Mostly resolved — applications that need real kernel-enforced limits will still not have them, but POSIX compatibility is restored |
The `sys_resource/mod.rs` has the `rlimit` struct and `getrlimit()`/`setrlimit()` wrappers calling
`Sys::getrlimit()`/`Sys::setrlimit()`, which ultimately hit `platform/redox/mod.rs` lines 738755
with a `todo_skip!` on `setrlimit`.
**Required work**: Depends on kernel work (separate from relibc). When kernel gains RLIMIT syscalls,
the `platform/redox/mod.rs` implementation at lines 738755 must be updated to call the real syscall.
**Tracked in**: `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` as kernel-blocked.
---
### G3 — `timerfd` relative time support
| Field | Value |
|-------|-------|
| **Status** | `recipe-applied` — relative time conversion implemented via `P3-timerfd-relative.patch` |
| **Current impl** | `P3-timerfd-relative.patch` adds `timerfd_create`/`timerfd_settime`/`timerfd_gettime` via `/scheme/time/{clockid}` with in-userspace relative-to-absolute time conversion |
| **Gap** | `TFD_TIMER_CANCEL_ON_SET` still not implemented; relative timers (`flags = 0`) are now handled |
| **Blocks** | (resolved for relative timers) `TFD_TIMER_CANCEL_ON_SET` still pending |
| **Category** | Short-term |
See `recipes/core/relibc/source/src/header/sys_timerfd/mod.rs` and `local/patches/relibc/P3-timerfd-relative.patch`.
---
### G4 — `ifaddrs` live system discovery
| Field | Value |
|-------|-------|
| **Status** | `recipe-applied` — returns synthetic `loopback` + `eth0` only |
| **Current impl** | `P3-ifaddrs-net_if.patch` patches `net_if/mod.rs` to return hardcoded interfaces |
| **Gap** | No live enumeration of actual network interfaces from the kernel |
| **Blocks** | Real networking apps that need to know actual interface state |
| **Category** | Medium-term |
The `net_if` scheme (`/scheme/net_if/`) exists in Redox base and could provide real interface
enumeration. The `ifaddrs` module (`src/header/ifaddrs/mod.rs`) currently just returns `ENOSYS`.
---
### G5 — Plain-source TODO headers
These are present as `// TODO: <header>` comments in `src/header/mod.rs`. Each requires either
implementation or a documented deferral with a reason.
| Header | Location in mod.rs | Notes |
|--------|--------------------|-------|
| `mqueue.h` | line 55 | POSIX message queues |
| `sys/msg.h` | line 98 | SysV message queues |
| `spawn.h` | line 79 | `posix_spawn()` |
| `threads.h` | line 132 | pthreads |
| `wordexp.h` | line 146 | shell word expansion |
| `iconv.h` | line 41 | character set conversion |
| `sys/ipc.h` | line 96 | IPC shared definitions |
| `sys/sem.h` | line 102 | SysV semaphores |
| `sys/shm.h` | line 103 | SysV shared memory |
Note: `sys/ipc.h`, `sys/sem.h`, and `sys/shm.h` already have `recipe-applied` implementations via
`P3-sysv-ipc.patch`, `P3-sysv-sem-impl.patch`, `P3-sysv-shm-impl.patch`. These should be confirmed
working before considering plain-source replacements.
---
## Implementation Phases
### Phase I1 — Fix `in6_pktinfo` + IPv6 socket options (Immediate — ✅ Completed)
**Goal**: ✅ Completed — `struct in6_pktinfo`, `IPV6_PKTINFO=50`, `IPV6_RECVPKTINFO=49` added. See `P3-in6-pktinfo.patch`.
#### Step I1.1 — Add `struct in6_pktinfo` to `netinet_in/mod.rs`
File: `recipes/core/relibc/source/src/header/netinet_in/mod.rs`
Add after the `ipv6_mreq` struct (around line 55):
```rust
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
#[repr(C)]
pub struct in6_pktinfo {
pub ipi6_addr: in6_addr,
pub ipi6_ifindex: u32,
}
impl Clone for in6_pktinfo {
fn clone(&self) -> Self {
Self {
ipi6_addr: in6_addr { s6_addr: self.ipi6_addr.s6_addr },
ipi6_ifindex: self.ipi6_ifindex,
}
}
}
impl Default for in6_pktinfo {
fn default() -> Self {
Self {
ipi6_addr: in6_addr { s6_addr: [0; 16] },
ipi6_ifindex: 0,
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn _cbindgen_export_in6_pktinfo(in6_pktinfo: in6_pktinfo) {}
```
Note: `in6_addr` does not derive `Clone` or `Default`, so manual implementations are required.
`#[derive(Debug, Clone, Default)]` would not compile.
#### Step I1.2 — Add IPv6 socket option constants to `netinet_in/mod.rs`
Add to `netinet_in/mod.rs` in the constants section (around line 108):
```rust
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
pub const IPV6_UNICAST_HOPS: c_int = 16;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
pub const IPV6_MULTICAST_IF: c_int = 17;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
pub const IPV6_MULTICAST_HOPS: c_int = 18;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
pub const IPV6_MULTICAST_LOOP: c_int = 19;
// ... existing multicast constants 20-21 ...
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/netinet_in.h.html>.
pub const IPV6_V6ONLY: c_int = 26;
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man7/ipv6.7.html>.
pub const IPV6_PKTINFO: c_int = 50;
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man7/ipv6.7.html>.
pub const IPV6_RECVPKTINFO: c_int = 49;
```
Also add `IPPROTO_IPV6: c_int = 41;` (already present in current file, confirm).
#### Step I1.3 — Update `netinet_in/cbindgen.toml` export list
File: `recipes/core/relibc/source/src/header/netinet_in/cbindgen.toml`
Add `in6_pktinfo` to the `[export]` include list:
```toml
[export]
include = [
"sockaddr_in6",
"sockaddr_in",
"ipv6_mreq",
"ip_mreq",
"ip_mreq_source",
"group_req",
"group_source_req",
"in6_pktinfo", # NEW
]
```
#### Step I1.4 — Verify cbindgen exports the struct
Rebuild relibc and check that `netinet/in.h` in the staging sysroot contains the `in6_pktinfo`
struct definition. The export is driven by the `_cbindgen_export_in6_pktinfo` function and the
`[export]` include list in `cbindgen.toml` — no manual C macro in the trailer is needed.
#### Step I1.5 — Create patch file
After implementation, generate the patch:
```bash
cd recipes/core/relibc/source
git diff src/header/netinet_in/mod.rs src/header/netinet_in/cbindgen.toml \
> ../../../local/patches/relibc/P3-in6-pktinfo.patch
```
And add to `recipes/core/relibc/recipe.toml` under `patches`:
```toml
patches = [
# ... existing patches ...
"../../../local/patches/relibc/P3-in6-pktinfo.patch",
]
```
#### Step I1.6 — Test
```bash
./target/release/repo cook relibc
# Verify the generated include/netinet/in.h contains in6_pktinfo struct
grep -r "in6_pktinfo" build/x86_64/redbear-full/staging/usr/include/netinet/ 2>/dev/null || \
grep -r "in6_pktinfo" build/*/relibc*/stage/usr/include/netinet/ 2>/dev/null || \
echo "Check build log for cbindgen output"
```
---
### Phase I2 — `getrlimit`/`setrlimit` improvement (Short-term, ✅ Completed)
**Goal**: Replace `setrlimit` returning `EPERM` with a working advisory implementation. Add sensible defaults for more `RLIMIT_*` constants.
**Implementation**: Modified `platform/redox/mod.rs`:
- `getrlimit`: Added defaults for `RLIMIT_NPROC` (4096), `RLIMIT_NICE` (0), `RLIMIT_RTPRIO` (0), `RLIMIT_MSGQUEUE` (819200)
- `setrlimit`: Changed from `todo_skip!` + `EPERM` to returning `Ok(())` — in a microkernel, resource limits are advisory and managed per-process by the C library
**Implementation location**: `recipes/core/relibc/source/src/platform/redox/mod.rs` lines 738755.
---
### Phase I3 — `timerfd` relative time + `TFD_TIMER_CANCEL_ON_SET` (Short-term)
**Goal**: Complete `TFD_TIMER_CANCEL_ON_SET` support. Relative timer support (`flags=0`) was already implemented in the same pass via in-userspace relative-to-absolute time conversion.
**Current implementation**: `P3-timerfd-relative.patch` patches `sys_timerfd/mod.rs` to call
`/scheme/time/{clockid}`. Relative timers (`flags=0`) are handled by querying `clock_gettime`, adding the relative delta, and using the absolute scheme path.
**Gap detail**: `timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value)`:
- `flags = TFD_TIMER_ABSTIME`: `new_value->it_value` is absolute Unix time → works
- `flags = 0` (relative): ✅ Implemented — converts relative to absolute in userspace
- `TFD_TIMER_CANCEL_ON_SET`: cancel when clock reaches absolute time → NOT implemented
**Implementation approach**:
- For relative timers (`flags = 0`): ✅ DONE — query `clock_gettime`, add relative delta, use absolute scheme path.
- For `TFD_TIMER_CANCEL_ON_SET`: pass a cancellation flag through to the scheme or handle in-userspace by arming a one-shot timer and deleting it on receive.
- Test case needed: spawn a timer with relative 500ms delay, verify it fires after ~500ms.
**Files to modify**: `recipes/core/relibc/source/src/header/sys_timerfd/mod.rs`
**Patch to update**: `local/patches/relibc/P3-timerfd-relative.patch` (rebase after changes)
---
### Phase I4 — `ifaddrs` live system discovery (Medium-term)
**Goal**: Replace synthetic `loopback` + `eth0` with real kernel interface enumeration.
**Current state**: `P3-ifaddrs-net_if.patch` patches `net_if/mod.rs` to return hardcoded interfaces.
**Implementation approach**:
1. Query `/scheme/net_if/list` to enumerate interfaces
2. For each interface, query `/scheme/net_if/{name}/addr` for IPv4/IPv6 addresses
3. Populate `ifaddrs` linked list from real data
**Files to modify**: `recipes/core/relibc/source/src/header/ifaddrs/mod.rs`,
`recipes/core/relibc/source/src/header/net_if/mod.rs`
**Existing patch**: `local/patches/relibc/P3-ifaddrs-net_if.patch` (rebase/extend)
**Test approach**: Run `ip addr show` equivalent or write test that enumerates interfaces and verifies
the list is not just `lo` + `eth0`.
---
### Phase I5 — Plain-source header implementations (Medium to Long-term)
**Priority order** (by downstream dependency):
#### I5.1 — `sys/ipc.h`, `sys/sem.h`, `sys/shm.h` (Medium)
Already have `recipe-applied` implementations via P3 patches. Goal is to promote these to
plain-source or confirm they are stable as-is. Check current patch quality:
- `P3-sysv-ipc.patch`
- `P3-sysv-sem-impl.patch`
- `P3-sysv-shm-impl.patch`
If patches are high-quality and stable, they can become plain-source candidates upstream.
If patches are fragile, improve the implementation.
**Verification**: Run existing IPC tests (`P3-ipc-tests.patch` provides test coverage).
Confirm SysV sem/shm operations work correctly under load.
#### I5.2 — `mqueue.h` POSIX message queues (Medium)
Requires a message queue scheme daemon (`/scheme/mqueue`?) or implementation via existing primitives.
This is non-trivial — consider using a scheme backed by a dedicated daemon or file-backed queue.
**Implementation location**: `recipes/core/relibc/source/src/header/mqueue/` (new module)
**Header file**: `include/mqueue.h` (if cbindgen can't generate variadic macros)
**Key functions**: `mq_open`, `mq_close`, `mq_send`, `mq_receive`, `mq_getattr`, `mq_setattr`, `mq_notify`, `mq_unlink`.
#### I5.3 — `sys/msg.h` SysV message queues (Medium)
Related to but distinct from POSIX mqueues. SysV msg queues use `msgget`, `msgsnd`, `msgrcv`,
`msgctl`. Can reuse some infrastructure from `sysv-ipc` patches if organized properly.
**Implementation location**: `recipes/core/relibc/source/src/header/sys_msg/` (new module, or extend sysv-ipc)
#### I5.4 — `spawn.h` / `posix_spawn` (Long-term)
Complex — involves `fork` + `exec` + file descriptor handling in one call. relibc already has `fork`
and `exec` via `redox-rt`. `posix_spawn` would be a thin wrapper.
**Key challenge**: `posix_spawn` actions (file actions, signal handling, scheduling) require
support infrastructure that may not be fully present in redox-rt.
#### I5.5 — `threads.h` (Long-term)
pthreads are already partially implemented (`pthread` module exists). `threads.h` is the C11
threads API (`thrd_create`, `mtx_init`, `cnd_init`, etc.) layered on top of pthread.
**Current state**: `pthread` module is fairly complete. `threads.h` header is mostly a compatibility
layer. Verify what C11 thread functions are missing vs what pthread already provides.
#### I5.6 — `wordexp.h` (Long-term)
Shell word expansion — parse shell-like `{var}`, `$(cmd)`, globs, quotes. Not urgently needed by
current desktop consumers.
#### I5.7 — `iconv.h` (Long-term)
Character set conversion. A full implementation is substantial. Could leverage an existing iconv
library (e.g., `libiconv`) or implement a subset.
---
## Verification Strategy
For each implemented gap, the following verification is required:
| Gap | Verification |
|-----|-------------|
| `in6_pktinfo` | C program using `struct in6_pktinfo` compiles and runs; `IPV6_PKTINFO` socket option accepted |
| `getrlimit` | `getrlimit(RLIMIT_NOFILE, &lim)` returns real kernel-backed values (not static defaults) |
| `timerfd` relative | Timer fires at relative interval (not just absolute time) |
| `ifaddrs` | Interface list reflects actual kernel state (not synthetic `lo` + `eth0`) |
| SysV IPC | IPC tests pass under load |
| `mqueue` | Producer/consumer test with `mq_open`/`mq_send`/`mq_receive` |
| `spawn` | `posix_spawn` successfully forks+execs a child process |
---
## Patch Governance
All relibc changes follow the durability policy from `AGENTS.md`:
1. Implement and test in `recipes/core/relibc/source/`
2. Create patch in `local/patches/relibc/P<N>-<description>.patch`
3. Add to `recipes/core/relibc/recipe.toml` under `patches`
4. Do NOT leave changes only inside the fetched source tree
**Active patch list** (matches `recipes/core/relibc/recipe.toml`):
```
redox.patch # Base relibc redox adaptations
P0-strtold-cpp-linkage-and-compat.patch
P3-signalfd.patch # signalfd support
P3-signalfd-header.patch
P3-timerfd-relative.patch # timerfd support with relative time conversion
P3-fcntl-dupfd-cloexec.patch # fcntl F_DUPFD_CLOEXEC
P3-waitid.patch # waitid support
P3-semaphore-fixes.patch # named + unnamed semaphore fixes
P3-socket-cred.patch # SO_PEERCRED, getpeereid
P3-elf64-types.patch
P3-open-memstream.patch # open_memstream
P3-ifaddrs-net_if.patch # ifaddrs (synthetic — see Phase I4)
P3-fd-event-tests.patch # eventfd/signalfd/timerfd tests
P3-netdb-lookup-retry-fix.patch # DNS lookup retry logic
P3-exec-root-bypass.patch # exec permission bypass for root
P3-tcp-nodelay.patch # TCP_NODELAY socket option
P3-select-not-epoll-timeout.patch # select: non-epoll fallback timeout
P3-tls-get-addr-panic-fix.patch
P3-pthread-yield.patch
P3-secure-getenv.patch
P3-getentropy.patch
P3-dup3.patch
P3-vfork.patch
P3-clock-nanosleep.patch
P3-socket-flags.patch # MSG_NOSIGNAL, dup3
P3-waitid-header.patch
P3-inet6-pton-ntop.patch # inet_pton / inet_ntop for IPv6
P3-tcp-sockopt-forward.patch # TCP socket options forwarding
P3-dns-aaaa-getaddrinfo-ipv6.patch # AAAA record DNS resolution
P3-getrlimit-getdtablesize.patch # getrlimit stub + getdtablesize
P3-in6-pktinfo.patch # in6_pktinfo struct + IPV6_PKTINFO/IPV6_RECVPKTINFO
```
**Historical patches** (not currently active, kept for reference):
- `P3-sysv-ipc.patch` — SysV IPC base
- `P3-sysv-sem-impl.patch` — SysV semaphores
- `P3-sysv-shm-impl.patch` — SysV shared memory
- `P3-aio.patch` — asynchronous I/O
---
## Relationship to Other Subsystem Plans
- `in6_pktinfo` unblocks QtNetwork → unblocks KF6 network modules → unblocks full KDE Plasma
- `getrlimit` kernel backing depends on `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`
- `timerfd` relative support is part of POSIX.1e timer completeness (related to mqueue)
- `ifaddrs` live discovery enables proper network configuration tooling
---
## Non-goals (Explicitly Deferred)
- Kernel credential syscalls (`setuid`, `getuid`, `setgroups`, `getgroups`) — kernel work required,
tracked separately
- Full POSIX.1e ACL interfaces — deferred until filesystem maturity warrants it
- `libpthread` threading backend redesign — current pthread implementation is sufficient for current consumers