This is an archive of the discontinued LLVM Phabricator instance.

hwasan: Use bits [3..11) of the ring buffer entry address as the base stack tag.
ClosedPublic

Authored by pcc on Jun 14 2019, 1:48 PM.

Details

Summary

This saves roughly 32 bytes of instructions per function with stack objects
and causes us to preserve enough information that we can recover the original
tags of all stack variables.

Now that stack tags are deterministic, we no longer need to pass
-hwasan-generate-tags-with-calls during check-hwasan. This also means that the
new stack tag generation mechanism is exercised by check-hwasan.

Depends on D63119

Diff Detail

Repository
rL LLVM

Event Timeline

pcc created this revision.Jun 14 2019, 1:48 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 14 2019, 1:48 PM
Herald added subscribers: Restricted Project, hiraditya, kubamracek, srhines. · View Herald Transcript
eugenis added inline comments.Jun 14 2019, 1:54 PM
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
1007 ↗(On Diff #204843)

We are losing a lot of entropy by allowing these zero bits in the base tag. Single-alloca functions, for example, will only have 32 different tags.

How about using bits 3 .. 11 ?

pcc updated this revision to Diff 204877.Jun 14 2019, 4:15 PM
pcc marked an inline comment as done.
  • Address review comments
pcc added inline comments.Jun 14 2019, 4:19 PM
llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
1007 ↗(On Diff #204843)

Done. Now tag 0 is as likely as any other tag.

To fix the tests that were assuming that they would never get tag 0, I've added a call to a helper function that bumps the base tag to 128 to the tests that would otherwise fail.

pcc retitled this revision from hwasan: Use the lower 8 bits of the ring buffer entry address as the base stack tag. to hwasan: Use bits [3..11) of the ring buffer entry address as the base stack tag..Jun 14 2019, 4:20 PM
pcc edited the summary of this revision. (Show Details)

We can make the tags undeterministic again by starting each ring buffer at a random index.

pcc updated this revision to Diff 205130.Jun 17 2019, 11:25 AM
  • Sort FastMasks by increasing probability of collisions
eugenis added inline comments.Jun 17 2019, 2:50 PM
compiler-rt/test/hwasan/TestCases/random-align-right.c
30 ↗(On Diff #205130)

why did you copy this line?

compiler-rt/test/hwasan/TestCases/stack-history-length.c
20 ↗(On Diff #205130)

I don't understand this. How does a single additional call to FUNC help guarantee that property?

pcc marked 2 inline comments as done.Jun 17 2019, 3:07 PM
pcc added inline comments.
compiler-rt/test/hwasan/TestCases/random-align-right.c
30 ↗(On Diff #205130)

Because the additional call to GenerateRandomTag in InitRandomState causes the values that we assign to tail_magic in HwasanAllocatorInit to change in such a way that we catch the second bad access and not the first one. Without copying this line the CHECK?-NEXT lines fail to match because the failure doesn't happen on the line after the first message.

compiler-rt/test/hwasan/TestCases/stack-history-length.c
20 ↗(On Diff #205130)

In the case where there are 2046 calls to FUNC we have:

  • tag 1 for FUNC0
  • tag 2..2047 (mod 256) for FUNC1
  • tag 2048 (mod 256) for OOB (i.e. 0)

Adding the call to FUNC shifts all of the tags by 1 so that OOB gets tag 1.

eugenis added inline comments.Jun 17 2019, 3:15 PM
compiler-rt/test/hwasan/TestCases/random-align-right.c
30 ↗(On Diff #205130)

Wait, so the comment above the loop lies? We are testing for the bug on the first iteration, not an any iteration. Maybe remove -NEXT?

compiler-rt/test/hwasan/TestCases/stack-history-length.c
20 ↗(On Diff #205130)

Could we call OOB twice instead? And weaken the test a bit so that it is ok with result being off by 1 or 2 in any direction?

pcc updated this revision to Diff 205204.Jun 17 2019, 3:47 PM
pcc marked 2 inline comments as done.
  • Address review comments
compiler-rt/test/hwasan/TestCases/random-align-right.c
30 ↗(On Diff #205130)

Yeah, looks like a mistake in the test. The intent here was apparently that we'd let any access fail, but the test actually only lets the first access fail (and because of determinism that is always what happens).

We can't just remove -NEXT because it would prevent the test from determining which access found the bug. So I've rewritten this test a bit so that we can do that.

compiler-rt/test/hwasan/TestCases/stack-history-length.c
20 ↗(On Diff #205130)

Works for me, done.

eugenis accepted this revision.Jun 17 2019, 4:06 PM

LGTM

This revision is now accepted and ready to land.Jun 17 2019, 4:06 PM
This revision was automatically updated to reflect the committed changes.