This is an archive of the discontinued LLVM Phabricator instance.

[compile-rt] Reduce #ifdef noise for ptrauth
ClosedPublic

Authored by yln on May 6 2020, 7:15 PM.

Details

Summary

Create a sanitizer_ptrauth.h header that #includes <ptrauth> when
available and defines just the required macros as "no ops"
otherwise. This should avoid the need for excessive #ifdef'ing.

Follow-up to and discussed in: https://reviews.llvm.org/D79132

Diff Detail

Event Timeline

yln created this revision.May 6 2020, 7:15 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 6 2020, 7:15 PM
Herald added subscribers: Restricted Project, Charusso, mgorny. · View Herald Transcript

@yln I did a quick investigation to see if we could do this without macros. Unfortunately this turns out to be really tricky. Below is a rough sketch that almost works. Due to the way the ptrauth calls are implemented Clang enforces that the key and string passed to ptrauth_string_discriminator be literals.
For the key we can use templates to make this work but the string literal proves to be difficult because string literals aren't allowed as template arguments.

#if __has_feature(ptrauth_calls)
#include <ptrauth.h>
#endif

namespace __sanitizer {

struct ptrauth {
  template <int key, typename T>
  static __attribute__((always_inline)) T *strip(T *ptr) {
#if __has_feature(ptrauth_calls)
    return ptrauth_strip(ptr, key);
#else
    return ptr;
#endif
  }

  template <int key, typename T, typename ExtraDataTy>
  static __attribute__((always_inline)) T *auth_data(T *ptr,
                                                     ExtraDataTy extra_data) {
#if __has_feature(ptrauth_calls)
    return ptrauth_auth_data(ptr, key, extra_data);
#else
    return ptr;
#endif
  }

  // FIXME: C++ doesn't allow string literals as template arguments.
  template <const char* const str>
  static __attribute__((always_inline)) size_t
  string_discrminator() {
#if __has_feature(ptrauth_calls)
    return ptrauth_string_discriminator(str);
#else
    return 0;
#endif
  }
};
} // namespace __sanitizer

int main(int argc, char **argv) {
  int a;
  int *a_ptr = &a; 
  char **v = __sanitizer::ptrauth::strip<0>(argv);
  int *a_ptr_cpy = __sanitizer::ptrauth::auth_data<0>(a_ptr, 0); 
  size_t x = __sanitizer::ptrauth::string_discrminator<"foo">(); // FIXME: Doesn't work.
  return 0;
}

Unless you see a way around the string literal problem I think we might have to go with the current patch that uses macros which pains me.

compiler-rt/lib/sanitizer_common/sanitizer_ptrauth.h
19

This also goes against our coding convention of having macros be upper case. Unfortunately I don't see a good way around this.

yln added a comment.May 8 2020, 1:22 PM

I think we should mirror what <ptrauth.h> does. I just copied the "nop macros" from the end of the header for the APIs we use.

In D79540#2027555, @yln wrote:

I think we should mirror what <ptrauth.h> does. I just copied the "nop macros" from the end of the header for the APIs we use.

Okay let's do that for now.

delcypher accepted this revision.May 8 2020, 7:13 PM
This revision is now accepted and ready to land.May 8 2020, 7:13 PM
This revision was automatically updated to reflect the committed changes.