A TOCTOU Race Condition
Time-Of-Check to Time-Of-Use. Between the check (T1) and the use (T2), an attacker swaps the file out from under a privileged process.
Legitimate actor / call
Attacker action
Critical window (the race)
sequenceDiagram
autonumber
participant P as Privileged Process
participant F as Filesystem
participant A as Attacker
Note over P: T1 — TIME OF CHECK
P->>F: access("/tmp/x", R_OK)
F->>P: OK — normal user-owned file
rect rgb(255, 205, 210)
Note over P,A: TOCTOU window — the file is no longer what was checked
A->>F: unlink("/tmp/x")
A->>F: symlink("/etc/shadow", "/tmp/x")
end
Note over P: T2 — TIME OF USE
P->>F: open("/tmp/x", O_RDONLY)
F->>P: fd for /etc/shadow (symlink followed)
Note over P: Privileged process reads /etc/shadow
Structural fix: close the window instead of trying to shrink it. Use
openat() with O_NOFOLLOW, or open the file once and
operate on the file descriptor (fstat, not stat) — then the
thing you checked and the thing you use are guaranteed to be the same object.