[scudo] Allow for non-Android Shared TSD platforms, part 2
ClosedPublic

Authored by cryptoad on Thu, Oct 12, 10:39 AM.

Details

Summary

Follow up to D38826.

We introduce pthread_{get,set}specific versions of {get,set}CurrentTSD to
allow for non Android platforms to use the Shared TSD model.
We now allow SCUDO_TSD_EXCLUSIVE to be defined at compile time.

A couple of things:

  • I know that #if SANITIZER_ANDROID is not ideal within a function, but in the end I feel it looks more compact and clean than going the .inc route; I am open to an alternative if anyone has one;
  • SCUDO_TSD_EXCLUSIVE=1 requires ELF TLS support (and not emutls as this uses malloc). I haven't found anything to enforce that, so it's currently not checked.
cryptoad created this revision.Thu, Oct 12, 10:39 AM
cryptoad updated this revision to Diff 118845.Thu, Oct 12, 2:22 PM

Remove a comment that is no longer relevant: the pthread key is used.

alekseyshl added inline comments.Thu, Oct 12, 4:59 PM
lib/scudo/scudo_platform.h
29–30

What's going to happen if we define SCUDO_TSD_EXCLUSIVE at compile time on these platforms?

lib/scudo/scudo_tsd_shared.cpp
21

Why is it not static anymore?

35

You do not need this PThreadKey on Android, right? Maybe it does make sense to separate implementations along these lines? Move PThreadKey and Android into separate cpp files and link what you need?

cryptoad added inline comments.Thu, Oct 12, 5:54 PM
lib/scudo/scudo_platform.h
29–30

It will blow up at runtime (see main comment of the patch).
Android doesn't have ELF TLS but it's planned for some point. They do have emutls but it doesn't work for us.
Fuchsia I think supports a non emulated TLS, I'd have to double check.
I can put some safeguards?

lib/scudo/scudo_tsd_shared.cpp
21

It is used from scudo_tsd_shared.inc (defined as extern there).

35

Correct, it's not needed, it's useful on Android to makes things work on older platforms (the comment that I removed explains it).
I guess the issue with the separation is that it will end up affecting the .inc as well, which would have to be split or have further #ifs (the pthread key is used there). If you see a way to make this work, I can accommodate that.

alekseyshl added inline comments.Fri, Oct 13, 11:32 AM
lib/scudo/scudo_platform.h
29–30

Yep, something like this:

#define SCUDO_TSD_EXCLUSIVE_SUPPORTED (!SANITIZER_ANDROID && !SANITIZER_FUCHSIA)

#ifndef SCUDO_TSD_EXCLUSIVE
...
#endif  // SCUDO_TSD_EXCLUSIVE

#if SCUDO_TSD_EXCLUSIVE && !SCUDO_TSD_EXCLUSIVE_SUPPORTED
# error ...
#endif
lib/scudo/scudo_tsd_shared.cpp
35

If you are going to support O and below, I guess, the current way is fine. If you are not going to support releases before N, I'd suggest to separate implementations and either have 4 more files:
for getCurrentTSD:

scudo_tsd_shared_android.inc
scudo_tsd_shared_pthread.inc

for setCurrentTSD and the function called from initOnce (empty for Android):

scudo_tsd_shared_android_impl.inc
scudo_tsd_shared_pthread_impl.inc

or, another option is to define SCUDO_TSD_CPP_ and add two files, scudo_tsd_shared_android.inc and scudo_tsd_shared_pthread.inc, the pthread one will do something like this (android inc will look a bit simpler):

#ifdef SCUDO_TSD_CPP_
pthread_key_t PThreadKey;
ALWAYS_INLINE void setCurrentTSD(ScudoTSD *TSD) { ... }
void initSharedTsdOnce() { ... }
#else
extern pthread_key_t PThreadKey;
ALWAYS_INLINE ScudoTSD* getCurrentTSD() { ... }
#endif

Both ways are pretty ugly.

Well, ok, I guess enough with that, I'll let you pick the way and accept your choice.

cryptoad added inline comments.Fri, Oct 13, 11:43 AM
lib/scudo/scudo_tsd_shared.cpp
35

Does me picking a way allows for keeping things the way they are now? :)

cryptoad updated this revision to Diff 118956.Fri, Oct 13, 12:27 PM
cryptoad marked 5 inline comments as done.

Safeguarding the use of the exclusive TSD model against misuse (eg: using it
on a platform that doesn't support it).

alekseyshl accepted this revision.Fri, Oct 13, 1:26 PM
alekseyshl added inline comments.
lib/scudo/scudo_platform.h
36

No a big deal at all, but why add "#else" part? Less nesting in these # statements is always better. But, anyway, whatever works better for you.

lib/scudo/scudo_tsd_shared.cpp
35

Yep, none of the ways I came up with is significantly better. So, up to you.

This revision is now accepted and ready to land.Fri, Oct 13, 1:26 PM
cryptoad added inline comments.Fri, Oct 13, 1:31 PM
lib/scudo/scudo_platform.h
36

In my head it's one this check applies if SCUDO_TSD_EXCLUSIVE was defined initially, hence the #else.
I'll unnest it, it's not like we lose any performance that way!

lib/scudo/scudo_tsd_shared.cpp
35

I'd like to keep it that way for now.
If more platform specific stuff comes up in the future, I can see the split becoming necessary, but right now I feel it's less fragmented this way.

cryptoad updated this revision to Diff 118970.Fri, Oct 13, 1:39 PM
cryptoad marked 8 inline comments as done.

Unnesting the #if.

cryptoad closed this revision.Fri, Oct 13, 1:55 PM