This is an archive of the discontinued LLVM Phabricator instance.

[asan] Clean up some confusing code in `test/asan/TestCases/Darwin/segv_read_write.c`
ClosedPublic

Authored by delcypher on Mar 16 2018, 1:05 PM.

Details

Summary

[asan] Clean up some confusing code in
test/asan/TestCases/Darwin/segv_read_write.c

  • The fd arg passed to mmap() should be -1. It is not definedwhat passing 0 does on Darwin.
  • The comment about the shadow memory doesn't make any sense to me, so I'm removing it.

Diff Detail

Event Timeline

delcypher created this revision.Mar 16 2018, 1:05 PM
Herald added a subscriber: Restricted Project. · View Herald TranscriptMar 16 2018, 1:05 PM
delcypher edited the summary of this revision. (Show Details)Mar 16 2018, 1:05 PM
kubamracek accepted this revision.Mar 19 2018, 11:25 AM
This revision is now accepted and ready to land.Mar 19 2018, 11:25 AM

@aizatsky Any comments on this? It appears you are the author of this test, so I'd like to make sure you're happy with the change.

The comment makes sense to me. Writes are instrumented with reads from shadow in ASan. Therefore a write to addr in shadow will result in a read from shadow(addr), which is located in the mprotect-ed shadow gap, and will be reported as a read SEGV, not a write SEGV.

mmap() argument change looks fine.

delcypher added a comment.EditedJul 12 2018, 6:55 AM

The comment makes sense to me. Writes are instrumented with reads from shadow in ASan. Therefore a write to addr in shadow will result in a read from shadow(addr), which is located in the mprotect-ed shadow gap, and will be reported as a read SEGV, not a write SEGV.

mmap() argument change looks fine.

Thanks for that explanation. That makes more sense now. I'm going to integrate your explanation into the comment and merge.

The comment makes sense to me. Writes are instrumented with reads from shadow in ASan. Therefore a write to addr in shadow will result in a read from shadow(addr), which is located in the mprotect-ed shadow gap, and will be reported as a read SEGV, not a write SEGV.

mmap() argument change looks fine.

Thanks for that explanation. That makes more sense now. I'm going to integrate your explanation into the comment and merge.

Actually now I'm completely confused. Running the test on macOS I observe that

  • The Read() function triggers: The signal is caused by a READ memory access. The access is on the memory location p which indicates the access check instrumentation that reads the shadow passed.
  • The Write() function triggers: The signal is caused by a WRITE memory access. The access is on the memory location p which indicates the access check instrumentation that reads the shadow passed.
  • The Read() function has instrumentation to read from the shadow to check the access is okay. There are no writes to the shadow in this function.
  • The Write() function has instrumentation to read from the shadow to check the access is okay. There are no writes to the shadow in this function.
  • We do intercept mmap() but it doesn't look like we update the shadow memory in the interceptor.
  • We don't intercept munmap() so we aren't updating the shadow here either.

In light of this the comments do not make sense.

  • There are no writes to the shadow (okay there is some instrumentation in main() that looks like its setting up the shadow stack but that seems unrelated). Where are the writes to the shadow mentioned in the comments coming from?
  • The comments imply doing a write will result in reporting a read in the SEGV handler. That's not what the test is checking for and is not what I observe when running it.

The comment makes sense to me. Writes are instrumented with reads from shadow in ASan. Therefore a write to addr in shadow will result in a read from shadow(addr), which is located in the mprotect-ed shadow gap, and will be reported as a read SEGV, not a write SEGV.

What I'm reading from the test is that we're accessing a normal address in normal app part of memory. This is backed by an ordinary byte in the shadow memory. The gap is not involved here at all. We know whether the faulty access is a read or write based because the instrumentation passes this information to __asan_report_error. I don't see how the comment is helpful.

Actually, it's even simpler that that. The access is always valid (from the shadow's perspective). We're just trapping on a regular SEGV and the signal handler gets the information whether this is a read or a write.

Actually, it's even simpler that that. The access is always valid (from the shadow's perspective). We're just trapping on a regular SEGV and the signal handler gets the information whether this is a read or a write.

Yes that's what I observed. Presumably we don't update the shadow for mmap() and munmap() calls because the OS will handle bad accesses for us by trapping?

This revision was automatically updated to reflect the committed changes.