# 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