Skip to content

PACStack: an Authenticated Call Stack

Her stack frame'i için bir Pointer Authentication Code (PAC) zincirleyen bir return-address koruması; böylece her return address kriptografik olarak tüm call history'sine bağlanır — özel hardware olmadan bir software shadow-stack eşdeğeri.

Mechanism

Neden çalışır

Klasik backward-edge savunmaları ya return address'leri ayrı bir shadow stack'e kopyalar (ek bellek, isolation gerektirir) ya da her return address'i PAC ile bağımsız olarak imzalar. Bağımsız imzalama zayıftır: PAC için kullanılan modifier frame'ler arasında reuse edilir, dolayısıyla geçerli bir imzalanmış return address okuyabilen bir saldırgan onu başka bir frame'e replay veya transplant edebilir.

PACStack bunun yerine bir authenticated call stack (ACS) kurar. Temel fikir bir MAC zinciridir: frame N'in return address'i için hesaplanan PAC, modifier olarak önceki frame'in authentication token'ını kullanır. Kavramsal olarak:

auth_token_N = PAC( return_addr_N , auth_token_{N-1} , secret_key )

Her token kendinden öncekine bağlı olduğu için, çalışan token tüm call history üzerinde kriptografik bir accumulator'dır. Tek bir forge edilmiş veya yer değiştirilmiş return address zinciri kırar ve uyumsuzluk bir sonraki authenticate edilmiş return'de yüzeye çıkar.

Çalışan token bir reserved register'da tutulur (forge edilebilir biçimde spill edilmez) ve token bitleri maskelenir; böylece saldırganın bellekte gözlemleyebileceği değer secret accumulator'ı ifşa etmez — token'ın memory disclosure yoluyla leak olmasını engeller. Substitution'ı başarısız kılan da budur: geçerli token'ı ile birlikte kopyalanan bir return address bile, gelen token'ı farklı olan mevcut zincir pozisyonuna karşı authenticate edilir.

Walkthrough

Yüksek seviyeli; makalenin prologue/epilogue instrumentation tarifinden alınmıştır. ARMv8.3-A PAC instruction'ları kullanılır:

1. Function prologue — zinciri uzat. Return address'i (x30) PAC modifier'ı olarak mevcut zincirlenmiş token'ı kullanarak imzala:

; x30 = return address, x_chain = current auth token
PACIA  x30, x_chain        ; auth_token_N folds in return addr + prior token
; store/keep the new token; spill protected x30 as needed

2. Function epilogue — doğrula ve geri sar. Branch almadan önce return address'i aynı zincirlenmiş token'a karşı authenticate et:

AUTIA  x30, x_chain        ; recompute & compare; corrupt token -> fault
RET                        ; or BR x30 on success

3. Substitution tasarımı gereği başarısız olur. Derin bir frame'den (return_addr, token) alıp daha sığ bir frame'e yazan bir saldırgan, farklı bir gelen zincir değerine çarpar; bu yüzden AUTIA farklı bir MAC yeniden hesaplar ve CPU fault verir.

Tek bir forgery neden çığ gibi büyür

Herhangi bir frame ile oynamak, o frame'in accumulator'a katkısını değiştirir. O noktadan sonraki her authenticate edilmiş return, artık eşleşmeyen bir token yeniden hesaplar; dolayısıyla, hemen oradaki frame tesadüfen geçmiş olsa bile corruption tespit edilir — izole, bağımsız olarak forge edilebilir bir return address yoktur.

Detection

  • Authentication-failure fault'ları. Başarısız bir AUTIA/AUTIB poison'lanmış bir pointer üretir; sonraki branch/dereference fault verir (Linux'ta SIGSEGV/SIGILL, bare metal'de bir BRK/translation fault). Return edge'lerinde kümelenmiş böyle bir fault patlaması, backward-edge tampering'in veya bir ROP denemesinin güçlü bir sinyalidir.
  • Crash telemetrisi. Fault veren instruction'ı ve fault sınıfını yakalayan EDR/host crash reporter'ları, PAC-auth başarısızlıklarını sıradan null deref'lerden ayrı olarak işaretleyebilir.
  • Aynı korumalı binary'nin tekrar tekrar kısa ömürlü crash'leri, bir saldırganın zinciri yenmeden önce bir PAC signing/oracle için yokladığına işaret eder.

Mitigation

PACStack'in kendisi zaten bir hardening mekanizmasıdır — onu araştırma LLVM toolchain'i aracılığıyla ARMv8.3-A+ hardware üzerinde bir backward-edge savunması olarak konuşlandırın.

  • Diğer PAC savunmalarının yerine değil, yanında konuşlandır. Forward-edge koruması (PARTS veya platform pac-ret) ile ve indirect call'ları kapsamak için BTI ile eşleştirin.
  • Secret state'i koru. Güvenlik, PA key'inin ve register'daki zincirlenmiş token'ın gizli kalmasına dayanır; maskeleme'nin sağlam olduğundan ve token'ın asla kurtarılabilir bir biçimde spill edilmediğinden emin olun.

Bilinen uyarılar

PACStack PA hardware gizliliğine bağlıdır. PAC verification'a karşı speculative side-channel'lar — örn. PACMAN — prensipte crash etmeden bir PAC forge ederek zinciri zayıflatabilir. Address space'te bırakılmış signing/verification gadget'ları (PAC signing-gadget bypass) de bir artık risktir. Bildirilen overhead küçüktür (~%3), ancak ACS yalnızca backward edge'i korur.

References