Skip to content

[bug] localfs: parked resumable session can delete a case-folded successor object after restart #250

Description

@pmaxhogan

Found during the SFTP backend build (Task 4 review, 2026-08-03): the SFTP resumable-completion path had a data-loss window that was fixed there (d969fd8), and independent review confirmed driven-localfs has the identical hole, arguably worse (silent atomic replace, no remove step).

Sequence (crash-then-adopt-then-resume), bites on any case-insensitive/normalizing filesystem - default APFS and NTFS, both first-class targets:

  1. resumable_session for Foo.txt creates the temp and claims the name in-process only - claim keys are to_ascii_lowercase (layout.rs:207) and no sidecar is written until commit.
  2. Process crashes; the in-process claim is gone.
  3. A later create for foo.txt adopts the path: ownership() returns Ours when no sidecar exists, warn-only (layout.rs:277-294).
  4. The parked session is hydrated: store.rs:1011-1012 calls layout::claim_exact(...) blind - no sidecar/ownership probe on that path.
  5. Completion commits via commit_rename = std::fs::rename (store.rs:423 -> fsx.rs:100-101), which silently REPLACES the destination - destroying the object created in step 3.

Fix shape (proven in driven-sftp): on hydration, re-check destination ownership against the sidecar and return SessionInvalid on mismatch (see crates/driven-sftp/src/store.rs hydrate_session's ownership re-check and its mutation test a_parked_session_never_removes_an_object_that_became_someone_elses). Port the same discipline to localfs; a torn/unparseable sidecar mapping to Ok(None) re-opens the window and should fail closed on that path too.

Found by: SFTP Task 4 implementer, independently verified with citations by the task reviewer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:driveGoogle Drive / remote storebugSomething isn't working

    Projects

    • Status
      Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions