Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erts: Disable unsafe optimization in bs_append #9372

Conversation

jhogberg
Copy link
Contributor

@jhogberg jhogberg commented Feb 3, 2025

Imagine that we execute the following code, where X and Y are integers:

A = <<0, X>>,
B = <<A/bits, Y:X>>.

The first line sets up erts_current_bin, erts_bin_offset, etc because it obviously should.

However, the second line does not do so if X is zero, as build_size_in_bits being zero short-circuits the relevant logic.

This leaves a dangling pointer that, when we execute erts_new_bs_put_integer on the second line, we can land in a code path that ostensibly does not modify the buffer, but may nevertheless do a dummy read/write that is masked off, which can race with a write to the same address on another scheduler. For example, this can occur if there is a garbage collection between A and B, where the old heap that A lived on is picked up by another process on another scheduler before B executes.

Note that there does not need to be an actual link between A and B here: all that is necessary is that an expression like <<A/bits, Y:X>> is executed where X is zero. This issue was mostly benign before 9256aad that introduced an read-modify-write in certain cases that would be okay if erts_current_bin and erts_bin_offset had been set correctly.

While we could fix the read-modify-write issue separately, the invariant that erts_current_bin and erts_bin_offset are up to date has been broken, and it's difficult to tell whether other parts may suffer the same problem. Therefore, we will disable this optimization and reintroduce it again safely at a later time.

@jhogberg jhogberg added the team:VM Assigned to OTP team VM label Feb 3, 2025
@jhogberg jhogberg self-assigned this Feb 3, 2025
Copy link
Contributor

github-actions bot commented Feb 3, 2025

CT Test Results

  1 files   11 suites   2m 9s ⏱️
 91 tests  87 ✅ 4 💤 0 ❌
106 runs  102 ✅ 4 💤 0 ❌

Results for commit b4c3fe1.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

bjorng
bjorng previously approved these changes Feb 3, 2025
Imagine that we execute the following code, where `X` and `Y` are
integers:

```
A = <<0, X>>,
B = <<A/bits, Y:X>>.
```

The first line sets up `erts_current_bin`, `erts_bin_offset`, etc
because it obviously should.

However, the second line does not do so if X is zero, as
`build_size_in_bits` being zero short-circuits the relevant logic.

This leaves a dangling pointer that, when we execute
`erts_new_bs_put_integer` on the second line, we can land in a code
path that ostensibly does not modify the buffer, but may
nevertheless do a dummy read/write that is masked off, which can
race with a write to the same address on another scheduler. For
example, this can occur if there is a garbage collection between
`A` and `B`, where the old heap that `A` lived on is picked up by
another process before `B` executes.

Note that there does not need to be an actual link between `A` and
`B` here: all that is necessary is that an expression like
`<<A/bits, Y:X>>` is executed where `X` is zero. This issue was
mostly benign before 9256aad that
introduced an read-modify-write in certain cases that would be okay
if `erts_current_bin` and `erts_bin_offset` had been set correctly.

While we could fix the read-modify-write issue separately, the
invariant that `erts_current_bin` and `erts_bin_offset` are up to
date has been broken, and it's difficult to tell whether other
parts may suffer the same problem. Therefore, we will disable this
optimization and reintroduce it again safely at a later time.
@jhogberg jhogberg force-pushed the john/erts/disable-unsafe-bs_append-optimization/ERIERL-1177/OTP-19462 branch from dc0da04 to b4c3fe1 Compare February 4, 2025 08:30
@jhogberg jhogberg merged commit 0729f49 into erlang:maint-25 Feb 12, 2025
19 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team:VM Assigned to OTP team VM
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants