2012 Watchdog

References:

Identifier for all pointers:

  • For pointers in registers: Watchdog extends every register with a sidecar identifier register.
  • For pointers in memory: Watchdog provides a shadow memory that shadows every word of memory with an identifier for pointers.

Propagate and check the identifiers:

  • insert uOps for every memory accesses in hardware: extends the load, store, add immediate and add instructions. call/return instructions.

Identifier = Key + Lock

  • on stack: maintain an in-memory stack of lock locations. Top is stored at stack_lock control register.
    • call: generate a key –> store key in lock stack mem[stack_lock] = stack_key –> store id for the stack frame: rsp.id = (stack_key, stack_lock)
    • return: ( when to check? ) pop stack_lock –> get a new stack_lock position –> set as id for the new stack frame: rsp.id = (current_key, stack_lock)
  • on heap
    • allocation: generate a key (64 bits) –> allocate a lock_ptr –> *lock_ptr = key –> id = (key, lock_ptr) –> q = setident(ptr, id)
    • deallocation: id = getident(p) –> use id to set invalid on the lock *(id.lock) = INVALID –> add the deallocated memory into free list: add_to_free_list(id.lock)

Optimizations

  • Lock Location Cache

  • Identifying Pointer Load/Store Operations - conservative: Watchdog conservatively assumes that only a 64-bit load/store to an integer register may be a pointer operation.

Impl.

an x86-64 simulator, statically linked 64-bit programs.

Eval.

Only use-after-free checking:

  • 25% (conservative pointer identification)
  • 15% (ISA-assisted pionter identification) (24% without Lock Location Cache)

With bound checking: 15% – 18%

More

Created Oct 9, 2022 // Last Updated Oct 9, 2022

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?