Skip to content

touch create path TOCTOU: stat then create leading to truncate via race #10019

@sylvestre

Description

@sylvestre

Component

touch

Description

For a missing path, uutils touch does an existence check first and then creates the file.

File::create() opens with O_CREAT|O_TRUNC, so there is a race window: if another process creates the path (or swaps it to a symlink to an existing file) between the stat and the create, touch will open with truncation.

GNU touch does not have this specific pattern on create: it uses a single openat(O_CREAT) without a prior existence check and without O_TRUNC.

Test / Reproduction Steps

Syscall trace on a missing path:

uutils:

statx(AT_FDCWD, "/tmp/touch-sys/newfile", ..., ...) = -1 ENOENT
openat(AT_FDCWD, "/tmp/touch-sys/newfile", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3

GNU:

openat(AT_FDCWD, "/tmp/touch-sys/newfile", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
utimensat(0, NULL, NULL, 0) = 0

Impact

Race window for unintended truncation/clobbering when touch is run in attacker-writable directories or on attacker-controlled paths, especially when run with elevated privileges.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions