Skip to content

Fix undefined behavior in StartElevated stderr read loop (#1550)#1687

Merged
idrassi merged 1 commit into
veracrypt:masterfrom
curious-rabbit:master
Apr 23, 2026
Merged

Fix undefined behavior in StartElevated stderr read loop (#1550)#1687
idrassi merged 1 commit into
veracrypt:masterfrom
curious-rabbit:master

Conversation

@curious-rabbit
Copy link
Copy Markdown
Contributor

The read loop that captures stderr from the sudo child process used vector<char> buffer(4096); buffer.clear(); followed by read(fd, &buffer[0], buffer.capacity()). This has two instances of undefined behavior:

  1. operator[](0) on a vector with size() == 0 violates the C++ standard precondition n < size(). libstdc++ built with -D_GLIBCXX_ASSERTIONS aborts the process with:

    stl_vector.h:1128: Assertion '__n < this->size()' failed.

  2. buffer.begin() + bytesRead on the same empty vector constructs an iterator past end(), also UB.

-D_GLIBCXX_ASSERTIONS is in the default build flags of Arch Linux, Fedora, and several other distributions. On those systems, the unprivileged helper process aborts as soon as sudo writes anything to stderr (a password prompt, a 'user is not in the sudoers file' error, etc.). The main process then sees EOF on the service output pipe, and throws InsufficientData, which renders to the user as 'Not enough data available'. A second mount attempt fails at File::Write because the helper is dead and the pipe is broken, producing the bare message 'VeraCrypt::File::Write:395'.

Fix by replacing buffer with a plain char[4096] and using reserve(4096) on errOutput to preserve the original pre-allocation intent. No behavioral change on systems where the UB happened to work; aborts are eliminated on systems where the assertions fire.

Reported-by: multiple users
fixes #1550 #1446 #844

)

The read loop that captures stderr from the sudo child process used
`vector<char> buffer(4096); buffer.clear();` followed by
`read(fd, &buffer[0], buffer.capacity())`. This has two instances of
undefined behavior:

1. `operator[](0)` on a vector with `size() == 0` violates the C++
   standard precondition `n < size()`. libstdc++ built with
   `-D_GLIBCXX_ASSERTIONS` aborts the process with:

     stl_vector.h:1128: Assertion '__n < this->size()' failed.

2. `buffer.begin() + bytesRead` on the same empty vector constructs
   an iterator past `end()`, also UB.

`-D_GLIBCXX_ASSERTIONS` is in the default build flags of Arch Linux,
Fedora, and several other distributions. On those systems, the
unprivileged helper process aborts as soon as sudo writes anything
to stderr (a password prompt, a 'user is not in the sudoers file'
error, etc.). The main process then sees EOF on the service output
pipe, and throws `InsufficientData`, which renders to the user as
'Not enough data available'. A second mount attempt fails at
`File::Write` because the helper is dead and the pipe is broken,
producing the bare message 'VeraCrypt::File::Write:395'.

Fix by replacing `buffer` with a plain `char[4096]` and using
`reserve(4096)` on `errOutput` to preserve the original
pre-allocation intent. No behavioral change on systems where the UB
happened to work; aborts are eliminated on systems where the
assertions fire.

Reported-by: multiple users, see veracrypt#1550,
              veracrypt#1446, veracrypt#844
@idrassi
Copy link
Copy Markdown
Member

idrassi commented Apr 23, 2026

Good catch!
Thank you for fixing this illusive bug.
I'm merging it.

@idrassi idrassi merged commit e7188c9 into veracrypt:master Apr 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Not enough data available

2 participants