Skip to content

Fix 21 bugs from codebase review (Waves 1+2)#268

Merged
ejc3 merged 4 commits intomainfrom
review-fixes
Feb 7, 2026
Merged

Fix 21 bugs from codebase review (Waves 1+2)#268
ejc3 merged 4 commits intomainfrom
review-fixes

Conversation

@ejc3
Copy link
Copy Markdown
Owner

@ejc3 ejc3 commented Feb 7, 2026

Summary

Systematic codebase review identified 57 issues across fcvm, fuse-pipe, and fc-agent. This PR fixes 21 of them across two waves plus review feedback.

Wave 1 — 8 quick wins

Wave 2 — 10 correctness and safety fixes

Review feedback — 3 fixes

Test plan

```
cargo test -p fuse-pipe --lib # 42 pass
cargo test -p fcvm --lib # 48 pass
cargo test -p exec-proto # 6 pass
cargo build --release # clean
cargo fmt -- --check # clean
```

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 7, 2026

🔍 Claude Review

SEVERITY: medium

Findings

[MEDIUM] e2fsck signal-kill mishandled — unwrap_or(1) lets corrupted filesystems through (src/storage/disk.rs:207)

The new e2fsck exit code check uses:

if e2fsck_output.status.code().unwrap_or(1) >= 4 {

On Unix, ExitStatus::code() returns None when a process is killed by a signal (SIGKILL, SIGSEGV, etc.). With unwrap_or(1), a signal-killed e2fsck is treated as exit code 1 ("errors corrected"), which passes the >= 4 check and allows resize2fs to proceed on an unchecked (potentially corrupted) filesystem. The default should be >= 4 (e.g., unwrap_or(8)) so signal-terminated processes are treated as fatal errors.

[LOW] Stale README reference to removed FCVM_NO_XATTR_FASTPATH env var (README.md:880)

The PR correctly removed the security.capability xattr fast-path from fuse-pipe/src/client/fuse.rs, but README.md line 880 still documents the FCVM_NO_XATTR_FASTPATH environment variable. This is now dead documentation since the fast-path no longer exists.

[LOW] VolumeResponse::Written u32→u64 is cosmetic — FUSE ABI caps at u32

The wire protocol field was widened to u64, but reply.written(size as u32) truncates back to u32 at the FUSE interface (the kernel ABI struct fuse_write_out uses u32). The change prevents no real truncation since individual FUSE write/copy_file_range syscalls never return >4GB. This is not a bug but the PR description's framing as a truncation fix is slightly misleading.

Summary

The e2fsck exit code improvement is valuable but has a bug: signal-killed processes bypass the error check due to unwrap_or(1). The stale README reference is minor cleanup. Overall the PR is a solid set of defensive fixes.


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 7, 2026

🔧 Auto-Fix Created

I found issues and created a fix PR: #269

Fixes included:

  1. e2fsck signal-kill default: unwrap_or(1)unwrap_or(8) so signal-killed processes are treated as fatal errors
  2. Stale README reference: Removed FCVM_NO_XATTR_FASTPATH env var documentation (fast-path was removed in this PR)

Please review and merge the fix PR first, then this PR.

View Claude Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 7, 2026

🔧 CI Auto-Fix

Created fix PR: #270

The CI failure was caused by a rustfmt formatting issue in src/commands/podman.rs. The bail! macro call needed to be split across multiple lines according to rustfmt's formatting rules.

View Claude Run

- Wire protocol Written size u32 → u64 to prevent truncation on
  copy_file_range/remap_file_range returns exceeding 4GB
- Loopback IP exhaustion now returns error instead of silently
  reusing 127.0.0.2 (would cause IP conflicts)
- Remove security.capability xattr fast-path that returned ENODATA
  for all files, hiding real capabilities
- Check e2fsck exit code before resize2fs (exit >= 4 means
  uncorrectable filesystem errors)
- slirp4netns stdout/stderr changed from Stdio::piped() to
  Stdio::null() to prevent pipe buffer deadlock
- Check truncate exit code in create_disk_from_dir
- parse_size uses checked_mul to prevent silent overflow
- Delete dead code mount_vsock_with_readers in fc-agent

Tested: cargo test -p fuse-pipe --lib (42 pass), cargo test -p fcvm --lib (48 pass)
@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 7, 2026

🔍 Claude Review

SEVERITY: medium

Findings

[MEDIUM] Slirp stderr→null breaks error diagnostic path (src/network/slirp.rs:346-347, 365)

The PR changes slirp4netns stdout/stderr from Stdio::piped() to Stdio::null() to prevent a pipe-buffer deadlock. However, the error handling path at line 363-372 calls child.wait_with_output().await? to capture stderr when slirp4netns dies before becoming ready. With stderr now directed to /dev/null, output.stderr will always be empty, so the diagnostic will always be the unhelpful "slirp4netns exited before becoming ready (no stderr)" instead of showing the actual error message.

Fix: Keep stderr as Stdio::piped() (it's only read on the error path after the process exits, so no deadlock risk) or change stdout only to Stdio::null(). The deadlock risk was only from unconsumed piped output on long-running processes — stderr captured after wait_with_output() on a dead process is safe.

[MEDIUM] e2fsck signal-kill mishandled — previously reported, fix still pending

As noted in previous review, unwrap_or(1) on line 207 lets signal-killed e2fsck bypass the error check. Fix PR #269 is still open/unmerged.

[LOW] Stale README reference — previously reported, fix still pending

As noted in previous review, FCVM_NO_XATTR_FASTPATH env var is still documented in README line 878 after the fast-path was removed. Fix PR #269 covers this.

Summary

The slirp pipe-deadlock fix inadvertently breaks error diagnostics by sending stderr to null while the error handler still tries to read it. The e2fsck signal-kill issue from the previous review remains unfixed (PR #269 pending).


Review by Claude | Run

@claude-claude
Copy link
Copy Markdown
Contributor

claude-claude bot commented Feb 7, 2026

🔧 Auto-Fix Created

I found issues and created a fix PR: #271

Fixes included:

  1. Slirp stderr diagnostics: Kept stderr as Stdio::piped() so error messages are captured when slirp4netns dies at startup (stdout remains Stdio::null() — no deadlock risk)
  2. e2fsck signal-kill default: unwrap_or(1)unwrap_or(8) so signal-killed processes are treated as fatal
  3. Stale README: Removed FCVM_NO_XATTR_FASTPATH env var documentation

Note: This PR supersedes #269 which covered fixes 2 and 3 above, plus adds the new slirp stderr fix.

Please review and merge the fix PR first, then this PR.

View Claude Run

EJ Campbell added 3 commits February 6, 2026 18:50
Fixes:
- UFFD server auto-exit: use CancellationToken instead of exiting when
  connections drop to zero (server must stay alive for new clones)
- Health monitor false positive: return None (unknown) instead of
  Some(true) when fcvm binary not found for podman healthcheck
- Health monitor no fast polling revert: reset to startup interval when
  VM becomes unhealthy after being healthy
- Hardcoded port 80: use url.port().unwrap_or(80) for rootless health
- Slirp port forwarding: bail on error response instead of warn
- Bridged cleanup: collect all errors instead of stopping on first
- Clone setup leak: clean up data_dir and state on failure
- Thread-local groups: Drop guard ensures cleanup on panic
- Shell injection: replace bash -c with direct Command args for TAP
  device verification
- set_var unsoundness: pass max_write as parameter instead of using
  std::env::set_var in multi-threaded context
- e2fsck signal-kill: unwrap_or(1) → unwrap_or(8) so signal-killed
  process is treated as fatal error, not "errors corrected"
- Slirp stderr: keep stderr piped (only read after process exits,
  no deadlock risk) so error diagnostics aren't lost
- Remove stale FCVM_NO_XATTR_FASTPATH env var from README (fast-path
  was removed in Wave 1)
# Conflicts:
#	fc-agent/src/fuse/mod.rs
@ejc3 ejc3 merged commit 6978cad into main Feb 7, 2026
1 check passed
@ejc3 ejc3 deleted the review-fixes branch February 7, 2026 03:00
@ejc3 ejc3 changed the title Fix 8 bugs from codebase review (Wave 1) Fix 21 bugs from codebase review (Waves 1+2) Feb 7, 2026
ejc3 added a commit that referenced this pull request Mar 2, 2026
Fix 8 bugs from codebase review (Wave 1)
ejc3 added a commit that referenced this pull request Mar 2, 2026
Fix 8 bugs from codebase review (Wave 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant