I had the same question. So a quick run down of what the architecture actually does:

The core feature is Domain Tagging. The architecture adds 2 bits to data that define its 'domain' (code, code pointer, data, and data pointer). On its own this does nothing for security but it allows the churn unit to implement the two moving target defenses.

Pointer Displacement is the first moving target defense. It obscures pointer values by adding a random display to them and is domain dependent. So, the churn unit is able to find all code and data pointers and obfuscate them. Basically the same as encrypted pointers except they can be encrypted with a new key at run time.

Domain Encryption is the second moving target defense. It'll encrypt each domain with its own key. Details are sparse on how the encryption works, just the following quote:

> the domain encryption defense randomizes the representation of code, code pointers, and data pointers in memory using a strong cipher. These assets are encrypted in memory under their own distinct domain keys.

Both of these are actions performed by the churn unit which can be turned to run at a desired frequency or when certain rules are violated.

On the topic of rules, there are two types of rules the architecture enforces. ABORT and CHURN. Abort does the obvious and terminates the program, CHURN causes a re-randomization.

Aborts can be caused by:

- Attempting to execute anything not in the Code domain

- Use a Code data (not code pointer) in any instruction

- A jump target that isn't tagged as a Code Pointer

- A Load/Store address that isn't tagged as a Data Pointer

CHURNS can be caused by

- Performing an inter-domain comparison, the tags must match

- Any Code pointer arithmetic

- Any Data pointer arithmetic

- Any overflow occurs

- Invalid shift length (shifting by more bits than there are)

So on-to your question regarding ret2libc and friends. Basically, its an extra layer. A lot of attacks require that you leak some memory address (assuming ASLR is enabled) that is then used in the attack to, for example, craft a ROP or JOP chain. With pointer encryption you also need to leak the encryption key in order to craft a valid pointer.

Then you need to do so without causing violating an abort rule (shouldn't be too hard) and without violating a churn rule. The churn rules are potentially problematic as overflows are a common trick to getting certain values, and pointer arithmetic in general. As both cause churn that could invalidate the data you just leaked.

As for the root question of how can a valid application look up the memory, well its the architecture that decrypts the pointers/data in the architectures instructions (not adding new instructions like some pointer encryption implementations for example). So the program just needs the right pointer at run time, and the churn unit will rewrite them when it runs and changes the keys.

Honestly, it seems like a pretty solid mitigation for the types of attacks its designed to mitigate. An impossible barrier, I doubt it, without being hands on and trying to exploit it I can't speak with absolutes, but it certainly would be a challenge.

Though as many other have said, there are plenty of attacks it does nothing against but the paper is far more modest and accurate about the intent than the .edu post.