Skip to content

Do not replace /dev/null with a regular file in WriteFile - #31038

Open
zakinko wants to merge 1 commit into
bazelbuild:masterfrom
zakinko:devnull-unlink
Open

Do not replace /dev/null with a regular file in WriteFile#31038
zakinko wants to merge 1 commit into
bazelbuild:masterfrom
zakinko:devnull-unlink

Conversation

@zakinko

@zakinko zakinko commented Sep 8, 2026

Copy link
Copy Markdown

WriteFile unlinks its target before creating it with O_CREAT. The unlink is
there so a running executable can be replaced, since you cannot open one with
O_TRUNC; it has been in the function since the first import, when WriteFile's
job was to write executables: the open used mode 0755 and the comment said so.

//src/test/cpp/util:file_test writes to /dev/null, in TestWriteFile and again
with a four-gigabyte NUL-filled buffer in TestLargeFileWrite. As an ordinary
user the unlink fails and the write reaches the device, so nothing happens.
As root it succeeds and the node becomes a regular file.

On GitHub's ubuntu-latest runner, where /dev is devtmpfs, at 870abbb,
running the test as root:

before   /dev/null  character special file  crw-rw-rw-  1:3
//src/test/cpp/util:file_test    PASSED
after    /dev/null  regular file            -rw-r--r--  0:0  size=215

Debian 13 in a container and NetBSD 11.0/amd64 do the same. On NetBSD,
polling once a second while TestLargeFileWrite runs:

t=7  Character Device  size=0
t=8  Regular File      size=4000000000
t=9  Regular File      size=0

/dev holds a four-gigabyte file for about a second, until the next thing that
redirects to /dev/null truncates it.

What follows the missing device is harder to find than the device itself:
2>/dev/null becomes a write, and the next program to read /dev/null gets
whatever was left there.

file_windows.cc already returns early for /dev/null. This is the same three
lines on the POSIX side. The POSIX test then writes to /dev/null and checks
that it is still a device: as an ordinary user that cannot fail, and as root
it fails there instead of quietly corrupting everything that runs after it.

without the change, as root   file_posix_test.cc:336  Expected: true   FAILED
with the change, as root      PASSED, /dev/null still 1:3

file_test passes as an ordinary user on ubuntu-latest, macos-latest and
windows-latest (the Windows build does not compile either file touched here).
The tests that fail as root do so before and after alike:
FilePosixTest.CanAccess and FileTest.TestRemoveRecursivelyPosix.

WriteFile unlinks its target before creating it with O_CREAT. The unlink is
there so that a running executable can be replaced -- you cannot open one
with O_TRUNC -- and it has been in the function since the first import, when
WriteFile's job was to write executables.

//src/test/cpp/util:file_test writes to /dev/null. As an ordinary user the
unlink fails and the write reaches the device, so nothing happens; as root
it succeeds and the node becomes a regular file. On a system with room,
TestLargeFileWrite then leaves a four-gigabyte file in /dev until the next
redirection truncates it.

Reproduced on Debian 13 and on NetBSD 11.0/amd64. file_windows.cc already
returns early for /dev/null; do the same here, and check afterwards in the
POSIX test that /dev/null is still a device, so a run as root fails there
instead of quietly corrupting everything after it.
@github-actions github-actions Bot added team-Rules-CPP Issues for C++ rules awaiting-review PR is awaiting review from an assigned reviewer labels Sep 8, 2026
@meisterT
meisterT requested a review from tjgq September 8, 2026 06:00
@bazel-docs-pr-commenter

Copy link
Copy Markdown

✅ Bazel docs preview is ready!

Preview URL: https://bazel-pr-31038.mintlify.app/

Updated for 387d25a62bacb37fe62dd69b59d2af2aac450fb5

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

Labels

awaiting-review PR is awaiting review from an assigned reviewer team-Rules-CPP Issues for C++ rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant