Skip to content

KAFKA-9835; Protect FileRecords.slice from concurrent write#8451

Merged
hachikuji merged 1 commit into
apache:trunkfrom
hachikuji:KAFKA-9835
Apr 8, 2020
Merged

KAFKA-9835; Protect FileRecords.slice from concurrent write#8451
hachikuji merged 1 commit into
apache:trunkfrom
hachikuji:KAFKA-9835

Conversation

@hachikuji

@hachikuji hachikuji commented Apr 8, 2020

Copy link
Copy Markdown
Contributor

A read from the end of the log interleaved with a concurrent write can result in reading data above the expected limit. In particular, this would allow a read above the high watermark. The root of the problem is consecutive calls to sizeInBytes in FileRecords.slice which do not account for an increase in size. This patch fixes the problem by using a single call to sizeInBytes and caching the result.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

// handle integer overflow or if end is beyond the end of the file
if (end < 0 || end >= start + sizeInBytes())
end = start + sizeInBytes();
if (end < 0 || end > start + currentSizeInBytes)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the boundary check wrong? You changed >= to >.

@hachikuji hachikuji Apr 8, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The common case that we would see this is when the limit matches the file end exactly. So changing this to > would also have fixed this problem for that case. I decided to remove it here though just because the equality check is redundant (if end == start + currentSizeInBytes, then there's no need to update it).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

@ijuma ijuma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, LGTM.

Let's please mention in the PR description that the common case for triggering this would be a read to the end of the log where the if check was interleaved with an append to the log.

writerCompletion.get();
readerCompletion.get();
} finally {
executor.shutdownNow();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How often does this fail?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It fails consistently for me without the fix.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@hachikuji
hachikuji merged commit 778b1e3 into apache:trunk Apr 8, 2020
hachikuji added a commit that referenced this pull request Apr 8, 2020
A read from the end of the log interleaved with a concurrent write can result in reading data above the expected read limit. In particular, this would allow a read above the high watermark. The root of the problem is consecutive calls to `sizeInBytes` in `FileRecords.slice` which do not account for an increase in size due to a concurrent write. This patch fixes the problem by using a single call to `sizeInBytes` and caching the result.

Reviewers: Ismael Juma <ismael@juma.me.uk>
hachikuji added a commit that referenced this pull request Apr 8, 2020
A read from the end of the log interleaved with a concurrent write can result in reading data above the expected read limit. In particular, this would allow a read above the high watermark. The root of the problem is consecutive calls to `sizeInBytes` in `FileRecords.slice` which do not account for an increase in size due to a concurrent write. This patch fixes the problem by using a single call to `sizeInBytes` and caching the result.

Reviewers: Ismael Juma <ismael@juma.me.uk>
qq619618919 pushed a commit to qq619618919/kafka that referenced this pull request May 12, 2020
…#8451)

A read from the end of the log interleaved with a concurrent write can result in reading data above the expected read limit. In particular, this would allow a read above the high watermark. The root of the problem is consecutive calls to `sizeInBytes` in `FileRecords.slice` which do not account for an increase in size due to a concurrent write. This patch fixes the problem by using a single call to `sizeInBytes` and caching the result.

Reviewers: Ismael Juma <ismael@juma.me.uk>
andrey-klochkov-liftoff pushed a commit to liftoffio/kafka that referenced this pull request Aug 17, 2020
…#8451)

A read from the end of the log interleaved with a concurrent write can result in reading data above the expected read limit. In particular, this would allow a read above the high watermark. The root of the problem is consecutive calls to `sizeInBytes` in `FileRecords.slice` which do not account for an increase in size due to a concurrent write. This patch fixes the problem by using a single call to `sizeInBytes` and caching the result.

Reviewers: Ismael Juma <ismael@juma.me.uk>
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.

2 participants