7e34c4c251
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)
242 lines
7.9 KiB
Markdown
242 lines
7.9 KiB
Markdown
# 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`. |