This is an archive of the discontinued LLVM Phabricator instance.

[Sanitizers] Add interceptor for xdrrec_create
ClosedPublic

Authored by guiand on Jul 7 2020, 4:34 PM.

Details

Summary

For now, xdrrec_create is only intercepted Linux as its signature
is different on Solaris.

Diff Detail

Event Timeline

guiand created this revision.Jul 7 2020, 4:34 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 7 2020, 4:34 PM
Herald added subscribers: Restricted Project, fedor.sergeev. · View Herald Transcript
eugenis added inline comments.Jul 7 2020, 5:02 PM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
5803

I would not do this, we unpoison *xdrs in some places, but its probably better not to rely on it.
This is terrible API and the less we do with it, the better.
Remove these three interceptors.

5880

There is a handle parameter, you can use it wrap both read and write by passing a pointer to {real_handle, ctx, real_write, real_read} as the new handle.

eugenis added inline comments.Jul 7 2020, 5:07 PM
compiler-rt/test/sanitizer_common/TestCases/Linux/xdrrec.cpp
4

This line is unnecessary.

guiand marked an inline comment as done.Jul 7 2020, 5:48 PM
guiand added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
5880

I used that originally, but I was concerned the handle parameter might be saved somewhere inside the XDR struct in a user-accessible way. I actually went with the thread local data because these callbacks are used beyond the stack frame of just this function, so allocating such a struct on the stack would cause problems.

guiand updated this revision to Diff 276287.Jul 7 2020, 5:52 PM
guiand retitled this revision from [Sanitizers] Add interceptor for xdrrec functions to [Sanitizers] Add interceptor for xdrrec_create.
guiand edited the summary of this revision. (Show Details)

Remove interceptors besides xdrrec_create

guiand marked an inline comment as done.Jul 7 2020, 5:52 PM
eugenis added inline comments.Jul 8 2020, 12:47 PM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
5880

Would not thread-local storage cause even bigger problems in that case? Imagine

  1. another xdrrec_create called inside a write callback
  2. or simply two instances of xdrrec created in the same thread
  3. or even xdr_* functions invoked on a different thread from the one where xdrrec was created

read also needs to be wrapped to do COMMON_INTERCEPTOR_UNPOISON_PARAM

guiand updated this revision to Diff 276611.Jul 8 2020, 6:05 PM

This solution isn't super ideal but I couldn't think of a way around it.

We can't just allocate a handle on the heap in xdrrec_create and leave it at that, since there'd be no way to free it later. This is because it doesn't seem to be possible to access handle from the XDR struct, which is the only argument to xdr_destroy.
On the other hand, the callbacks don't have a way to get at the x_private field of XDR, which is what I chose for the HashMap key. So we need to wrap the handle parameter of the callbacks. But we can't just pass x_private as handle (as it hasn't been set yet). We can't put the wrapper struct into the HashMap and pass its pointer as handle, as the key we need (x_private again) hasn't been set yet.

So I allocate the wrapper struct on the heap, pass its pointer as handle, and put it into the HashMap so xdr_destroy can find it later and destroy it.

eugenis accepted this revision.Jul 21 2020, 4:15 PM

LGTM w/ nit

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
5839

Remove _LINUX.
If other platforms need a different implementation, then can add it later, or even add some ifdefs in the interceptor body,

5846

static

This revision is now accepted and ready to land.Jul 21 2020, 4:15 PM
This revision was automatically updated to reflect the committed changes.