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

[CodeHealth] Use span for SecureZeroData #23700

Merged
merged 1 commit into from
May 28, 2024

Conversation

cdesouza-chromium
Copy link
Collaborator

@cdesouza-chromium cdesouza-chromium commented May 16, 2024

SecureZeroData is used to clean up memory in a way the data is zeroed out once out of scope. The use of a custom allocator helps to enforce that. However the current way buffers are handled runs into issues when using Wunsafe-buffers-usage.

This change changes the interface of this function to use span to communicate the buffer. Additionally, this change simplifies the way different platforms are handled by having a single handling for all of them.

Finally, this change corrects the UB in the tests, where instatiated types like vector, and string were being menset to naught.

For more information: https://chromium.googlesource.com/chromium/src/+/main/docs/unsafe_buffers.md

Resolves brave/brave-browser#38371

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

Copy link
Contributor

The security team is monitoring all repositories for certain keywords. This PR includes the word(s) "secure" and so security team members have been added as reviewers to take a look.

No need to request a full security review at this stage, the security team will take a look shortly and either clear the label or request more information/changes.

Notifications have already been sent, but if this is blocking your merge feel free to reach out directly to the security team on Slack so that we can expedite this check.

@cdesouza-chromium cdesouza-chromium force-pushed the use-span-for-secure-zero-data branch 2 times, most recently from 3bf7c0e to d8d4f62 Compare May 16, 2024 14:19
@thypon thypon assigned fmarier and unassigned thypon and bcaller May 16, 2024
@fmarier fmarier requested a review from a team May 16, 2024 18:04
@fmarier
Copy link
Member

fmarier commented May 16, 2024

Adding Chromium reviewers since this is a security-critical change, but it requires deep knowledge of Chromium abstractions in order to review.

@darkdh darkdh requested a review from supermassive May 16, 2024 20:27
@cdesouza-chromium cdesouza-chromium force-pushed the use-span-for-secure-zero-data branch 2 times, most recently from 0a2765a to 0bc9ad6 Compare May 16, 2024 23:03
Comment on lines 17 to 18
std::fill(
reinterpret_cast<volatile uint8_t*>(base::to_address(bytes.begin())),
reinterpret_cast<volatile uint8_t*>(base::to_address(bytes.end())), 0u);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Attached guide suggests to use std::ranges::fill base::ranges::fill

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why we need to_address?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm using to_address to convert the typed iterators into a pointer, so I can have a pointer that I can cast to volatile. It seems to me to be a more elegant way to explicit get the iterator to yield the underlying pointer.

Comment on lines +36 to +37
SecureZeroData(
base::as_writable_bytes(UNSAFE_BUFFERS(base::make_span(p, n))));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Did we have a potential bug there? It was allocating n * sizeof(T) bytes, but clearing only first n bytes. Works correctly only when sizeof(T) == 1 which seems the only way it was instantiated with.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There was indeed a bug here that was flying undetected. There was also some very bad UB in the tests for the SecureZeroData function.

#endif
base::ranges::fill(
reinterpret_cast<volatile uint8_t*>(base::to_address(bytes.begin())),
reinterpret_cast<volatile uint8_t*>(base::to_address(bytes.end())), 0u);
Copy link
Member

Choose a reason for hiding this comment

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

is this actually the required form to write this?

can this be written like this?

volatile uint8_t* begin = bytes.data();
volatile uint8_t* end = begin + bytes.size_bytes();
base::ranges::fill(begin, end, 0u);

or this?

base::span<volatile uint8_t> range = bytes;
base::ranges::fill(range, 0u);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed.

`SecureZeroData` is used to clean up memory in a way the data is zeroed
out once out of scope. The use of a custom allocator helps to enforce
that. However the current way buffers are handled runs into issues when
using `Wunsafe-buffers-usage`.

This change changes the interface of this function to use `span` to
communicate the buffer. Additionally, this change simplifies the way
different platforms are handled by having a single handling for all of
them.

Finally, this change corrects the UB in the tests, where instatiated
types like `vector`, and `string` were being menset to naught.
@cdesouza-chromium cdesouza-chromium merged commit 86a1d87 into master May 28, 2024
19 checks passed
@cdesouza-chromium cdesouza-chromium deleted the use-span-for-secure-zero-data branch May 28, 2024 15:24
@github-actions github-actions bot added this to the 1.68.x - Nightly milestone May 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants