This is an archive of the discontinued LLVM Phabricator instance.

[MSan] run materializeChecks() before materializeStores()
AcceptedPublic

Authored by glider on Jul 18 2018, 4:02 AM.

Details

Summary

When pointer checking is enabled, it's important that every pointer is checked before its value is used.
For stores MSan used to generate code that calculates shadow/origin addresses from a pointer before checking it.
For userspace this isn't a problem, because the shadow calculation code is quite simple and compiler is able to move it after the check on -O2.
But for KMSAN getShadowOriginPtr() creates a runtime call, so we want the check to be performed strictly before that call.

Swapping materializeChecks() and materializeStores() resolves the issue: both functions insert code before the given IR location, so the new insertion order guarantees that the code calculating shadow address is between the address check and the memory access.

Diff Detail

Event Timeline

glider created this revision.Jul 18 2018, 4:02 AM
glider updated this revision to Diff 156043.Jul 18 2018, 4:05 AM

Uploaded the full context

Could you simply pass the pointer shadow value as an argument to the runtime call in the kernel, and keep userspace instrumentation as it is?

lib/Transforms/Instrumentation/MemorySanitizer.cpp
1139

It's better to take a step back, add instrumentation, then take a step forward.
Must handle the start of the basic block separately.

glider updated this revision to Diff 156238.Jul 19 2018, 5:12 AM
glider added a reviewer: dvyukov.

Reverted changes to getShadowOriginPtrUserspace()
Dima noticed that the problem we're trying to solve is essentially inserting two code snippets (one for shadow calculation and one for address check) right before the store to a given address so that the second snippet goes before the first one.
Therefore it's natural to insert the second snippet, and then the first one, i.e. to swap the order of calling materializeStores() and materializeChecks().

glider updated this revision to Diff 156240.Jul 19 2018, 5:13 AM

Added a comment

Could you simply pass the pointer shadow value as an argument to the runtime call in the kernel, and keep userspace instrumentation as it is?

This'll cost us two registers (for the pointer shadow value and an origin) and is also conceptually incorrect, as calculation of the shadow for a given address should be considered a use of that address and shouldn't precede its checks for validity.

I've also noticed that currently MSan instruments loads by placing the checks _after_ them, which is also incorrect.
E.g. for the following function:

int foo(int *v) {
  return *v;
}

the following IR is generated by the trunk compiler with -O2:

define dso_local i32 @foo(i32* nocapture readonly %v) local_unnamed_addr #0 {
entry:
  %0 = load i64, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @__msan_param_tls, i64 0, i64 0), align 8
  %1 = load i32, i32* %v, align 4, !tbaa !2
  %2 = ptrtoint i32* %v to i64
  %3 = xor i64 %2, 87960930222080
  %4 = inttoptr i64 %3 to i32*
  %_msld = load i32, i32* %4, align 4
  store i32 %_msld, i32* bitcast ([100 x i64]* @__msan_retval_tls to i32*), align 8
  %_mscmp = icmp eq i64 %0, 0
  br i1 %_mscmp, label %6, label %5, !prof !6

; <label>:5:                                      ; preds = %entry
  call void @__msan_warning_noreturn() #1
  call void asm sideeffect "", ""() #1
  unreachable

; <label>:6:                                      ; preds = %entry
  ret i32 %1
}

Sorry, please disregard the previous comment. It's my patch that breaks this order.

eugenis added inline comments.Jul 19 2018, 1:23 PM
lib/Transforms/Instrumentation/MemorySanitizer.cpp
1490

So all you really need is this chunk, and reordering of materializeStores and materializeChecks? Could you revert the rest of the change then?

I prefer the current, more explicit, way of inserting address checks.

Yes, looks like this chunk is enough.
I'll finish comparing the results and update the patch tomorrow.

glider updated this revision to Diff 156445.Jul 20 2018, 1:52 AM
glider retitled this revision from [MSan] pull insertShadowCheck() into getShadowOriginPtr(). NFC to [MSan] run materializeChecks() before materializeStores().
glider edited the summary of this revision. (Show Details)

Updated the patch.

glider updated this revision to Diff 156446.Jul 20 2018, 2:03 AM

Fixed check_access_address.ll

eugenis accepted this revision.Jul 20 2018, 9:28 AM

LGTM, thanks!

This revision is now accepted and ready to land.Jul 20 2018, 9:28 AM

Landed r337571, thanks!