[SECURITY][low] --inplace overwrite preserves original mode/setuid and can retain stale trailing bytes #258

Closed
opened 2026-09-05 12:08:20 +02:00 by TapTap · 1 comment
Owner

Found by security audit of dev (9f8b588).

Where: src/shared/file.c:339-357 (inplace branch: openat O_WRONLY|O_CREAT|O_NOFOLLOW, no O_TRUNC, no mode reset when metadata absent).

Problem: In-place path opens an existing destination file without truncation or re-creating it. With use_metadata=false no fchmod is done, so original mode/ownership persist; if root-owned setuid, root writes do not clear setuid -> attacker-controlled content into root-owned setuid file (local privesc). Shorter payload also leaves stale trailing bytes.

Fix: In the inplace branch always normalize permissions to metadata safe_mode (or 0644) stripping setuid/setgid/sticky, and truncate (O_TRUNC or ftruncate) before/at write so stale trailing bytes never survive.

Add unit test.

Found by security audit of `dev` (9f8b588). **Where:** src/shared/file.c:339-357 (inplace branch: openat O_WRONLY|O_CREAT|O_NOFOLLOW, no O_TRUNC, no mode reset when metadata absent). **Problem:** In-place path opens an existing destination file without truncation or re-creating it. With use_metadata=false no fchmod is done, so original mode/ownership persist; if root-owned setuid, root writes do not clear setuid -> attacker-controlled content into root-owned setuid file (local privesc). Shorter payload also leaves stale trailing bytes. **Fix:** In the inplace branch always normalize permissions to metadata safe_mode (or 0644) stripping setuid/setgid/sticky, and truncate (O_TRUNC or ftruncate) before/at write so stale trailing bytes never survive. Add unit test.
Author
Owner

Resolved on dev (HEAD f7c6c91).

Fixed on dev via fix/security-hardening (2234879): --inplace overwrites now ftruncate to payload length and normalize mode (metadata safe_mode or 0644, special bits stripped) after write. Unit tests added.

CI run #461: all jobs green (lint, build-and-test, sanitizers address+undefined, fuzz-build, coverage, valgrind). Unit 25/25, integration 83 passed / 10 skipped / 1 xpassed. Closing.

**Resolved on `dev`** (HEAD f7c6c91). Fixed on dev via fix/security-hardening (2234879): --inplace overwrites now ftruncate to payload length and normalize mode (metadata safe_mode or 0644, special bits stripped) after write. Unit tests added. CI run #461: all jobs green (lint, build-and-test, sanitizers address+undefined, fuzz-build, coverage, valgrind). Unit 25/25, integration 83 passed / 10 skipped / 1 xpassed. Closing.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: TapTap/FastSync#258