core: O_NOFOLLOW the download target open
DAEMON's safepath-adversarial.md accepts a TOCTOU residual between its canonicalise-and-check and the download starting, on the stated grounds that CORE's O_NOFOLLOW open of the final file closes it. That flag was never actually set: SparseFile::open used O_WRONLY|O_CREAT|O_CLOEXEC, so a symlink swapped in as the final path component after DAEMON's check would be followed and redirect our pwrites outside the allowed roots. Add O_NOFOLLOW. A symlinked leaf now fails the open with ELOOP, which errno_to_error already maps to Error::path_rejected. Regular files and the O_CREAT of a fresh part file are unaffected; resume (existing regular part file) is unaffected. Test that a symlinked destination is rejected rather than silently followed, and that the link target is never touched. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
This commit is contained in:
@@ -61,8 +61,14 @@ Rules:
|
||||
|
||||
## 4. Disk I/O — the buffer setting you asked for
|
||||
|
||||
One file, opened once, `O_WRONLY`. Each segment `pwrite()`s at its own absolute offset, so
|
||||
**there is no reassembly pass and no second write of the whole file.**
|
||||
One file, opened once, `O_WRONLY | O_NOFOLLOW`. Each segment `pwrite()`s at its own absolute
|
||||
offset, so **there is no reassembly pass and no second write of the whole file.**
|
||||
|
||||
`O_NOFOLLOW` on the part-file open: DAEMON canonicalises the save path and checks it against
|
||||
the allowed roots before `start()`, but the final component could be swapped for a symlink
|
||||
in the window between that check and our open. A symlinked leaf is rejected here (`ELOOP` →
|
||||
`Error::path_rejected`), not followed — it closes the TOCTOU residual that
|
||||
`daemon/docs/safepath-adversarial.md` accepts on those grounds.
|
||||
|
||||
- `posix_fallocate()` the full size up front → contiguous extents, no ENOSPC surprise at
|
||||
99 %, no fragmentation.
|
||||
|
||||
Reference in New Issue
Block a user