# PT Auth **Paper**: https://www.usenix.org/system/files/sec21-farkhani.pdf **Source code** : https://github.com/RiS3-Lab/PTAuth/ ## Core idea * Targets temporal memory safety * UAF (use-after-free) * double-free * invalid-free ## Assumptions * PAC key is confidential * AC computation can only be done by PTAuth ### Threat model * OS and hardware are trusted * DEP and code is ro * _cannot_ perform arbitrary memory read * as this exposes both the UUID and PAC signature * _can_ write/overwrite arbitrary memory ## Heap object signing ```c= #define PAC_SHIFT 48 // 63 void* pt_malloc(size_t sz) { char uuid[8]; void *p = real_alloc(sz + sizeof(uuid)); generate_uuid(&uuid); *p = uuid; p |= (pac_sign(p, uuid) << PAC_SHIFT); return p + sizeof(uuid); } void pt_free(void *p) { pac_check(p, true); // remove uuid *p = 0ul; p &= ~(0xf << PAC_SHIFT); real_free(p); } ``` ## Runtime PAC check ```c= int pac_check(void *p, bool once) { void *base = round_up(p, 16); bool pac_valid = pac_verify(base, *base); do { // 1) go backwards by 16 bytes base -= 16; // 2) *base has the UUID pac_valid = pac_verify(base, *base); // 3) quit if the limit is reached if (p - base > SEARCH_LIMIT) break; } while (!pac_valid && !once); } ``` ```c= struct foo { bool bar; int value; char array[PAGE_SIZE]; }; int baz(int *arr) { for (...) { sum += arr[i]; } call_another_fn(arr); } int bar(int *value) { // *value = 0xcafe; pac_check(value); } int foo() { struct foo *f = pt_malloc(sizeof(*f)); bar(&f->value); } ``` ## Weaknesses * Overhead is high (~26%) * Adding multi-threading capability (deallocation and UUID overwrite should be atomic) would further increase the overhead * CFI is _assumed_ due to CPI, but control-flow bending attacks are still possible