SYSCALL-MIGRATION-PLAN.md:
- Detailed analysis of upstream 0.9.0 BREAKING changes (FD reservation refactor,
removed syscalls, new *_into variants)
- Complete consumer impact catalog: 2 bootstrap call sites, 7 kernel/relibc
constant references, 26 recipes (no impact)
- 5-phase migration plan: bootstrap→kernel→relibc→syscall sync→full build
- Risk assessment with rollback procedure
- Clear migration table: old API → new API for each deprecated function/constant
- Execution order with time estimates (~1-2 days total)
7.9 KiB
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:
- Call
reserve_fd(n)to reserve N consecutive fd numbers - Pass the reserved fd to
*_intovariants - 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()— removedunlinkat_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:
// 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:
// 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:
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:
openat_with_filter/unlinkat_with_filterare no longer needed (bootstrap migrated)SYS_OPENAT_WITH_FILTERetc. are no longer needed (kernel migrated)- The reservation API is the canonical path
Verification:
cargo checkin syscall passes- All 26 recipes compile against new syscall
- Kernel compiles against new syscall
- relibc compiles against new syscall
- Full
redbear-miniISO builds
Phase 5: Full Image Build + Validation
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:
# 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.