Page MenuHomePhabricator

[compiler-rt][hwasan] Define fuchsia implementations of required hwasan functions

Authored by leonardchan on Jun 8 2021, 5:21 PM.



This contains all the definitions required by hwasan for the fuchsia implementation and can be landed independently from the remaining parts of D91466.

Diff Detail

Event Timeline

leonardchan created this revision.Jun 8 2021, 5:21 PM
leonardchan requested review of this revision.Jun 8 2021, 5:21 PM
Herald added a subscriber: Restricted Project. · View Herald TranscriptJun 8 2021, 5:21 PM

Let me know if these functions should be split up or can land together.

mcgrathr added inline comments.Jun 8 2021, 6:11 PM

These need comments about what they are and why they need to exist as runtime variables at all.


What actually refers to this?
The optimal implementation for Fuchsia would just know everywhere at compile time that it's a fized value.
If there's reason for the runtime variable to exist at all, it should have comments.


Isn't this __sanitizer::GetMaxUserVirtualAddress() ?


This comment isn't very meaningful, since it only really applies to the two functions after these three.
This is also a weird comment syntax not used elsewhere in this file.


As we discussed before, this is insufficient plumbing for the thread tracking.
It probably makes sense to either do all the necessary refactoring for the thread tracking plumbing first, or else start this file simpler without anything related to thread tracking, and then add more stuff later.

Also, as a matter of style it's best to define C++ functions in the __hwasan namespace or a local anonymous namespace, and then have an extern "C" block at the end where the libc hook API implementation functions are just simple wrapper calls with no more than a line or two in them.

See asan_fuchsia.cpp for a good example of how to arrange the hook functions.


This is not the name of the hook. __sanitizer_process_exit_hook is the name of the hook. This is a good example of a simple wrapper.

However, it's unclear whether this should use the exit hook or not. We don't use that hook in asan, we just use its normal atexit method. In hwasan, the atexit hook doesn't really do much. ReportStats is a no-op in hwasan, and DumpProcessMap is always a no-op on Fuchsia anyway. So all it's really doing in practice is changing the exit code, which is what's a perfect fit for the sanitizer hook.


Why isn't this just in hwasan.cpp?


I'd put blank lines between these.
Most or all of them merit an individual comment about how Fuchsia handles things differently and thus doesn't need that particular thing.


I'd put this comment inside the function. Seems like a good idea to rename this function to something not so Linuxy, e.g. InitializeOsSupport.

leonardchan marked an inline comment as done.
leonardchan added inline comments.

kHighMemEnd and kHighMemBeg are used only by MemIsApp which is only used in hwasan_thread.cpp for some debugging checks:

if (stack_bottom_) {
  int local;
  CHECK(MemIsApp(stack_top_ - 1));

Rather than having these, we could just use their values (__sanitizer::ShadowBounds.memory_limit - 1 and __sanitizer::ShadowBounds.shadow_limit) directly in MemIsApp to avoid these globals.

kAliasRegionStart is used in HwasanAllocatorInit for setting up the allocator, but is only relevant for an experimental x86 implementation that uses page aliasing for placing tags in heap allocations (see D98875). I didn't look too much into the machinery for this since I didn't think we would be using hwasan for x86 anytime soon, but we can explore this now if we want to plan ahead. We could also make it such that this is just defined as 0 on x86 platforms, similar to SHADOW_OFFSET in asan.


It's only used for converting between application memory and shadow memory:

// hwasan_mapping.h
inline uptr MemToShadow(uptr untagged_addr) {
  return (untagged_addr >> kShadowScale) +
inline uptr ShadowToMem(uptr shadow_addr) {
  return (shadow_addr - __hwasan_shadow_memory_dynamic_address) << kShadowScale;

Perhaps we could have something similar to the SHADOW_OFFSET macro in asan where it can be defined to either a constant or __hwasan_shadow_memory_dynamic_address on different platforms and these functions can just use the macro.


It is. It looks there's

namespace __hwasan {
using namespace __sanitizer;

in sanitizer_internal_defs.h included through hwasan.h. Will add the __sanitizer:: bits.




Moved these in D104085 and left the remaining functions here.


Ah, if the functions in HwasanAtExit are no-ops and it only sets the exit code to 1 with internal__exit on an error, then it might not be necessary to have this here.


Removed from this and will move to hwasan.cpp in a separate patch. I imagine other platforms would've had their own versions of this we didn't want to centralize, but it looks like they all share the linux one.


Removed and will rename in a separate patch.

mcgrathr added inline comments.Jun 11 2021, 4:07 PM

MemIsApp is defined in this file so don't define any globals on its account (if it needs anything, make it static in this file).

HWASAN_ALIASING_MODE is not supported for Fuchsia and we don't need to make sure it compiles. Just leave out anything related to it entirely for now.


That sounds good. But we can make that a separate refactoring cleanup of its own. It's fine to just define it to 0 here and leave a TODO comment about removing the runtime variable altogether on Fuchsia.

That's a refactoring you could either land separately on its own first before landing the Fuchsia port, or do afterwards as a separate cleanup change.

leonardchan marked 10 inline comments as done.

Rebase and remove __hwasan_shadow_memory_dynamic_address. We don't need to set it anymore.

*ping* Anything else that should be updated?

mcgrathr accepted this revision.Jul 5 2021, 1:48 PM

lgtm with minor changes + clang-format.


It feels sketchy to modify a variable defined in sanitizer_common directly like that.
Let's move this call into an InitShadowBounds() in sanitizer_common/sanitizer_fuchsia.h factored out of GetMaxUserVirtualAddress.


On further reflection, it's suboptimal that GetMaxUserVirtualAddress always resets the global. It does that because in the asan implementation it's only called once at startup anyway so that was the minimal refactoring there.

Here since we're using ShadowBounds directly in this same code, I think using it directly here is more readable (as well as more optimal).

This revision is now accepted and ready to land.Jul 5 2021, 1:48 PM
This revision was landed with ongoing or failed builds.Jul 8 2021, 10:24 AM
This revision was automatically updated to reflect the committed changes.
leonardchan marked 2 inline comments as done.