This is an archive of the discontinued LLVM Phabricator instance.

[NFC][compiler-rt][hwasan] Refactor hwasan functions
ClosedPublic

Authored by leonardchan on Jun 2 2021, 3:15 PM.

Details

Summary

This moves the implementations for HandleTagMismatch, __hwasan_tag_mismatch4, and HwasanAtExit from hwasan_linux.cpp to hwasan.cpp and declares them in hwasan.h. This way, calls to those functions can be shared with the fuchsia implementation without duplicating code.

Diff Detail

Event Timeline

leonardchan created this revision.Jun 2 2021, 3:15 PM
leonardchan requested review of this revision.Jun 2 2021, 3:15 PM
Herald added a subscriber: Restricted Project. · View Herald TranscriptJun 2 2021, 3:15 PM
leonardchan edited the summary of this revision. (Show Details)
vitalybuka accepted this revision.Jun 2 2021, 11:15 PM
vitalybuka added inline comments.
compiler-rt/lib/hwasan/hwasan.cpp
192

please clang-format the patch

226

__hwasan:: redundant

This revision is now accepted and ready to land.Jun 2 2021, 11:15 PM
leonardchan marked 2 inline comments as done.
This revision was landed with ongoing or failed builds.Jun 3 2021, 2:27 PM
This revision was automatically updated to reflect the committed changes.
vitalybuka added a subscriber: smd.Aug 5 2022, 11:32 AM
vitalybuka added inline comments.
compiler-rt/lib/hwasan/hwasan.cpp
205

maybe we should pop everything up to "pc" to avoid issues with nested calls?

For most users hwasan frames are not very useful. However if you work on sanitizer, some frames can be a useful info. So I don't mind we just relax test cases to accommodate this nesting.

cc @smd

Herald added a project: Restricted Project. · View Herald TranscriptAug 5 2022, 11:32 AM
Herald added a subscriber: Enna1. · View Herald Transcript
smd added a comment.Aug 5 2022, 12:18 PM

Hi folks,

I've been working on support hwasan for risc-v and I believe I've found an issue with the existing lit tests this commit causes.
Tests stack-{oob,uar,uas}.c check for correct backtrace being printed. From the code and comments the idea is to not to print any hwasan related frames(see the code and comments below).

void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,                                
                       uptr *registers_frame) {                                                     
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);                                           
  BufferedStackTrace *stack = stack_buffer.data();                                                  
  stack->Reset();                                                                                   
  stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal);                               
                                                                                                    
  // The second stack frame contains the failure __hwasan_check function, as                        
  // we have a stack frame for the registers saved in __hwasan_tag_mismatch that                    
  // we wish to ignore. This (currently) only occurs on AArch64, as x64                      
  // implementations use SIGTRAP to implement the failure, and thus do not go                       
  // through the stack saver.                                                                       
  if (registers_frame && stack->trace && stack->size > 0) {                                         
    stack->trace++;                                                                              
    stack->size--;                                                                               
  }

Before this commit the return address and frame pointer to were taken directly from hwasan_tag_mismatch4, while after the commit those addresses are calculated after another function being called from hwasan_tag_mismatch4 (the HwasanTagMismatch one).
So, if I understand it correctly, now it looks like 2 stack frames must be ignored(for hwasan_tag_mismatch4 and HwasanTagMismatch) to get a proper backtrace.
What do you think?

Thanks

fmayer added a subscriber: fmayer.Aug 5 2022, 12:20 PM

Hi folks,

I've been working on support hwasan for risc-v and I believe I've found an issue with the existing lit tests this commit causes.
Tests stack-{oob,uar,uas}.c check for correct backtrace being printed. From the code and comments the idea is to not to print any hwasan related frames(see the code and comments below).

void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc,                                
                       uptr *registers_frame) {                                                     
  InternalMmapVector<BufferedStackTrace> stack_buffer(1);                                           
  BufferedStackTrace *stack = stack_buffer.data();                                                  
  stack->Reset();                                                                                   
  stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal);                               
                                                                                                    
  // The second stack frame contains the failure __hwasan_check function, as                        
  // we have a stack frame for the registers saved in __hwasan_tag_mismatch that                    
  // we wish to ignore. This (currently) only occurs on AArch64, as x64                      
  // implementations use SIGTRAP to implement the failure, and thus do not go                       
  // through the stack saver.                                                                       
  if (registers_frame && stack->trace && stack->size > 0) {                                         
    stack->trace++;                                                                              
    stack->size--;                                                                               
  }

Before this commit the return address and frame pointer to were taken directly from hwasan_tag_mismatch4, while after the commit those addresses are calculated after another function being called from hwasan_tag_mismatch4 (the HwasanTagMismatch one).
So, if I understand it correctly, now it looks like 2 stack frames must be ignored(for hwasan_tag_mismatch4 and HwasanTagMismatch) to get a proper backtrace.
What do you think?

Thanks

Yes, but I am not sure we can *rely* on that being the case as is. LTO could conceivably inline this – in which case it would be one, right?

compiler-rt/lib/hwasan/hwasan.cpp
205

This is probably for another patch though, right? This is already like this on the LHS.

205

nevermind. i accidentally had this left, sent https://reviews.llvm.org/D131279 for that.

fmayer added inline comments.Aug 5 2022, 12:44 PM
compiler-rt/lib/hwasan/hwasan.cpp
205

Sorry, please disregard everything I said here (incl the link). I confused myself where this was posted, and this is all nonsense.

smd added inline comments.Aug 6 2022, 1:18 AM
compiler-rt/lib/hwasan/hwasan.cpp
205

@vitalybuka thanks for the reply.

However if you work on sanitizer, some frames can be a useful info

From my experience most of the time while I'm working on sanitizers I spend in gdb, so I don't actually care about what backtrace is being printed. So it might be a good idea to avoid confusing regular hwasan user and skip printing service hwasan frames.

Maybe we just could keep the current scheme, but get return address and frame pointer in __hwasan_tag_mismatch4 like it was before? Something like:

void HwasanTagMismatch(uptr addr, uptr pc, uptr frame, uptr access_info, uptr *registers_frame, size_t outsize) {
  __hwasan::AccessInfo ai;
  ai.is_store = access_info & 0x10;
  ai.is_load = !ai.is_store;
  ai.recover = access_info & 0x20;
  ai.addr = addr;
  if ((access_info & 0xf) == 0xf)
    ai.size = outsize;
  else
    ai.size = 1 << (access_info & 0xf);

  HandleTagMismatch(ai, pc, frame, nullptr, registers_frame);
}
...
void __hwasan_tag_mismat(uptr)__builtin_frame_address(0)ch4(uptr addr, uptr access_info, uptr *registers_frame,
                            size_t outsize) {
  uptr ra = (uptr)__builtin_return_address(0);
  uptr fp = (uptr)__builtin_frame_address(0);
  __hwasan::HwasanTagMismatch(addr, ra, fp, access_info, registers_frame, outsize);
}

@fmayer

LTO could conceivably inline this – in which case it would be one, right?

Yes, you're totally right.