Clang Hardening Cheat Sheet - Ten Years Later

20 points by freddyb


olliej

This is obviously linux focused, but on macOS and iOS targeting arm64e-apple-{whatever} gets you what apple calls the pointer auth protected ABI. This is largely what the linux+ptrauth folk are also targeting adoption of. You can get this abi manually with something to the effect of

clang[++] -fptrauth-calls -fptrauth-returns -fptrauth-intrinsics -fptrauth-indirect-gotos -fptrauth-auth-traps -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination

The problem of course is that this is a platform ABI, so anything that crosses an ABI boundary will break, e.g

int compare(void*, void*);
...
qsort(...., compare)

Will crash as the function pointer ABI has broken. The way this is handled on apple platforms is that while the entire system is compiled using the arm64e abi, when you launch an arm64 binary you get null keys and so the ptrauth operations all become no-ops. The biggest unavoidable ABI break is that some types that may previously have been POD types cease to be so by inclusion of address diversified values, and that impacts the calling convention. Butting getting this to happen requires manual use of the __ptrauth intrinsic as the only place ptrauth protected values with address diversified values are C++ dynamic objects where the vtable pointers are address discriminated, but they are already non-pod. However if you were to harden the common C vtable implementation, eg

struct MyType;
typedef MyType* MyTypeRef;
typedef void(*MyTypeDestructorMethodTy)(MyTypeRef);
typedef void(*MyTypeSomeOperationMethodTy)(MyTypeRef);
struct MyTypeVTable {
  DestructorMethodTy destroy;
  SomeOperationMethodTy someOperation;
};

struct MyType {
    MyTypeVTable *VPtr;
    // ...
};

You might want to protect the vtable pointer with an address diversified schema so it can't be copied from one object to another. To demonstrate how you might protect such a structure I banged out this example: https://godbolt.org/z/shGh1KM6M

Anyway if you do do this and were passing either MyType or MyTypeVTable as a value argument the calling convention changes as neither is a POD type anymore, so would get passed on the stack. Yes, even in C: a struct containing an address diversified pointer actually gets a copy constructor.

Now this particular ABI difference only matters if you expect the same generated code to run in a process containing both ptrauth and non-ptrauth aware code (as happens in the apple implementation), but it's also reasonably unlikely that you ever construct such a type manually, and if you do it's pretty clear you're doing it.

If you're even more interested the full ABI is described here https://clang.llvm.org/docs/PointerAuthentication.html#language-abi if you're curious.

vaguelytagged

Perhaps a dumb question but if these are all enabled is it actually possible to exploit the application in the presence of something like a int overflow? Is it just that most developers don't use all these features?