# Syscall Migration — Upstream 0.9.0 BREAKING Changes **Date**: 2026-07-07 **Status**: Assessment complete, migration plan ready **Reference**: `local/sources/syscall/` — our fork `7e9cffd` vs upstream `1db4871` --- ## 1. What Changed Upstream Redox OS upstream (`gitlab.redox-os.org/redox-os/syscall.git`) introduced two breaking changes in version 0.9.0: ### 1.1 FD Reservation Refactor (`4bb9233`) The old auto-allocation FD API was replaced with reservation-based allocation: | Old (deprecated) | New (upstream 0.9.0) | |---|---| | `syscall::open(path, flags)` → returns auto-allocated fd | `syscall::open_into(path, flags, reserved_fd)` | | `syscall::dup(fd, buf)` → returns auto-allocated fd | `syscall::dup_into(fd, reserved_fd, buf)` | | Implicit fd allocation | Explicit reservation via `syscall::reserve_fd(n)` | The reservation model requires callers to: 1. Call `reserve_fd(n)` to reserve N consecutive fd numbers 2. Pass the reserved fd to `*_into` variants 3. Release unused reservations via `release_fd(n)` ### 1.2 Removed Syscalls (`1db4871`) These syscall numbers were removed from `src/number.rs` and `src/call.rs`: | Removed Constant | Reason | |---|---| | `SYS_OPENAT_WITH_FILTER` (985) | Replaced by `SYS_OPENAT_INTO` (987) — reservation-based | | `SYS_UNLINKAT_WITH_FILTER` (986) | Replaced by `SYS_UNLINKAT` (263) — no filter needed | | `SYS_SENDFD` (34) | Absorbed into `SYS_CLOSE` / scheme dispatch | | `SYS_OPENAT` (7) | Replaced by `SYS_OPENAT_INTO` (987) | | `SYS_DUP` (41) | Replaced by `SYS_DUP_INTO` (988) | The corresponding call wrappers were also removed: - `openat_with_filter()` — removed - `unlinkat_with_filter()` — removed ### 1.3 New Upstream Features (unrelated, useful) | Commit | Change | |---|---| | `79cb6d9` | `AcpiVerb` — new proc scheme ACPI verb | | `a358928` | Additional proc scheme & addrsp verbs | | `fcce297` | `Error::new` as `const fn` | --- ## 2. Our Fork State Our fork `7e9cffd` is based on upstream at the pre-breaking-change point (before `4bb9233`). Five commits were added to preserve backward compatibility: | Our Commit | What It Preserves | |---|---| | `812d74e` | `SYS_OPENAT` and `SYS_DUP` aliases | | `bf54ba8` | `SYS_SENDFD` constant | | `488ed0c` | `SYS_OPENAT_WITH_FILTER` and `SYS_UNLINKAT_WITH_FILTER` constants | | `2c06be3` | Legacy `openat`/`dup`/`sendfd`/`close` call wrappers | | `7e9cffd` | `openat_with_filter` / `unlinkat_with_filter` call wrappers | **Current divergence**: 5 commits behind upstream HEAD (2 actual changes + 3 cosmetic). --- ## 3. Consumer Impact Analysis ### 3.1 `openat_with_filter` / `unlinkat_with_filter` Usage Only 1 file uses these deprecated APIs: | File | Usages | Migration Difficulty | |---|---|---| | `local/sources/base/bootstrap/src/initnsmgr.rs` | 2 (openat + unlinkat) | **Low** — straightforward replacement | ### 3.2 Legacy Constant References | File | Constants Used | Action | |---|---|---| | `local/sources/kernel/src/syscall/mod.rs` | `SYS_OPENAT_WITH_FILTER`, `SYS_UNLINKAT_WITH_FILTER`, `SYS_SENDFD` | Update dispatch table | | `local/sources/kernel/src/scheme/proc.rs` | `SYS_SENDFD` | Update proc scheme handler | | `local/sources/kernel/src/syscall/debug.rs` | `SYS_OPENAT`, `SYS_DUP` | Update debug logging | | `local/sources/syscall/src/flag.rs` | `SYS_SENDFD` | Internal — will be updated by sync | | `local/sources/relibc/redox-rt/src/sys.rs` | `SYS_OPENAT`, `SYS_DUP`, `SYS_SENDFD` | Update redox-rt wrappers | ### 3.3 Recipe Consumers (26 recipes) All 26 recipes reference `redox_syscall` via `Cargo.toml` but do NOT use the deprecated APIs directly — they use stable APIs (`open`, `read`, `write`, etc.). **No recipe changes needed.** --- ## 4. Migration Plan ### Phase 1: Bootstrap Migration (Low Risk, 2 call sites) **File**: `local/sources/base/bootstrap/src/initnsmgr.rs` Replace `openat_with_filter` with the upstream `openat_into` + reservation pattern: ```rust // OLD: let scheme_fd = syscall::openat_with_filter( cap_fd, reference, flags, ctx.uid, ctx.gid )?; // NEW (reservation-based): let reserved = syscall::reserve_fd(1)?; let scheme_fd = syscall::openat_into( cap_fd, reference, flags, reserved, ctx.uid, ctx.gid )?; ``` Replace `unlinkat_with_filter` with `unlinkat`: ```rust // OLD: syscall::unlinkat_with_filter(cap_fd, reference, flags, ctx.uid, ctx.gid)?; // NEW: syscall::unlinkat(cap_fd, reference, flags)?; ``` **Verification**: `cargo check -p bootstrap` passes. ### Phase 2: Kernel Dispatch Update (Medium Risk, 3 files) Update `local/sources/kernel/src/syscall/mod.rs` — replace deprecated constants in the syscall dispatch match: | Old | New | |---|---| | `SYS_OPENAT_WITH_FILTER` | `SYS_OPENAT_INTO` | | `SYS_UNLINKAT_WITH_FILTER` | Remove (no longer dispatched) | | `SYS_SENDFD` | Remove (absorbed into scheme dispatch) | | `SYS_OPENAT` | `SYS_OPENAT_INTO` | | `SYS_DUP` | `SYS_DUP_INTO` | Update `local/sources/kernel/src/scheme/proc.rs` — remove `SYS_SENDFD` handling. Update `local/sources/kernel/src/syscall/debug.rs` — update constant names in log messages. **Verification**: `cargo check -p kernel` passes. Boot test in QEMU. ### Phase 3: relibc redox-rt Update (Medium Risk, 1 file) Update `local/sources/relibc/redox-rt/src/sys.rs` — replace deprecated constant references with the new names. The redox-rt module wraps kernel syscalls for relibc's POSIX layer. **Verification**: `cargo check` in relibc passes. `sys_socket` tests pass. ### Phase 4: Syscall Fork Sync (High Risk, entire fork) Squash-merge the upstream changes into our fork: ```bash cd local/sources/syscall git fetch upstream git checkout -b sync-0.9.0 upstream/master git merge --squash master # re-apply our preservation commits on top of upstream # Resolve conflicts in: # src/call.rs — keep upstream's reservation API, drop our legacy wrappers # src/number.rs — keep upstream's constants, drop our legacy constants # src/flag.rs — merge minimally ``` **After sync, our fork drops all 5 preservation commits** since: 1. `openat_with_filter` / `unlinkat_with_filter` are no longer needed (bootstrap migrated) 2. `SYS_OPENAT_WITH_FILTER` etc. are no longer needed (kernel migrated) 3. The reservation API is the canonical path **Verification**: - `cargo check` in syscall passes - All 26 recipes compile against new syscall - Kernel compiles against new syscall - relibc compiles against new syscall - Full `redbear-mini` ISO builds ### Phase 5: Full Image Build + Validation ```bash touch syscall && make prefix ./local/scripts/build-redbear.sh --upstream redbear-mini # QEMU boot test # DHCP + curl test ``` --- ## 5. Risk Assessment | Risk | Severity | Mitigation | |---|---|---| | Kernel panic from missing syscall dispatch | **HIGH** | Test each syscall removal individually in QEMU | | FD leak from reservation API misuse | **MEDIUM** | Audit all `reserve_fd` / `release_fd` call pairs | | relibc ABI break | **MEDIUM** | Run full `sys_socket` test suite | | Recipe compile failure | **LOW** | All 26 recipes use stable APIs — no changes needed | | Bootstrap fails to init | **LOW** | Only 2 call sites, simple replacement | --- ## 6. Execution Order ``` Phase 1 (bootstrap) → Phase 2 (kernel) → Phase 3 (relibc) → Phase 4 (syscall sync) → Phase 5 (full build) 30 min 2-4 hours 1 hour 1-2 hours 2-4 hours ``` **Total estimated duration**: 1-2 days. **Prerequisite**: None — all phases are independent except Phase 4 depends on 1-3 completing first (consumers must be migrated before syscall drops legacy support). --- ## 7. Rollback Plan If the migration fails, revert each component: ```bash # Revert syscall fork to pre-sync state cd local/sources/syscall && git checkout master # Revert kernel (git stash or checkout) cd local/sources/kernel && git checkout -- . # Revert bootstrap cd local/sources/base && git checkout -- bootstrap/ # Revert relibc cd local/sources/relibc && git checkout -- redox-rt/ ``` The legacy constants and wrappers are preserved in our fork's git history at `7e9cffd`.