ShadowCallStack (SCS) คือโหมดเครื่องมือวัดประสิทธิภาพ LLVM ที่ป้องกันไม่ให้มีการเขียนทับที่อยู่สำหรับส่งคืน (เช่น การเขียนทับบัฟเฟอร์สแต็ก) โดยบันทึกที่อยู่สำหรับส่งคืนของฟังก์ชันไปยัง ShadowCallStack ที่จัดสรรแยกต่างหากในส่วนนำหน้าของฟังก์ชันที่ไม่ใช่ฟังก์ชันย่อย และโหลดที่อยู่สำหรับส่งคืนจาก ShadowCallStack ในส่วนปิดท้ายของฟังก์ชัน ระบบจะจัดเก็บที่อยู่สำหรับส่งคืนไว้ในกองซ้อนปกติด้วยเพื่อให้เข้ากันได้กับโปรแกรมเลิกทำ แต่จะไม่ใช้งาน วิธีนี้ช่วยให้มั่นใจได้ว่าการโจมตีที่แก้ไขที่อยู่สำหรับส่งคืนในกองซ้อนปกติจะไม่มีผลต่อการควบคุมการไหลของโปรแกรม
ใน aarch64 เครื่องมือวัดผลจะใช้รีจิสเตอร์ x18
เพื่ออ้างอิง ShadowCallStack ซึ่งหมายความว่าไม่จำเป็นต้องจัดเก็บการอ้างอิงไปยัง ShadowCallStack ในหน่วยความจำ
วิธีนี้ช่วยให้ใช้รันไทม์ที่หลีกเลี่ยงการแสดงที่อยู่ของ ShadowCallStack ต่อผู้โจมตีที่อ่านหน่วยความจำแบบไม่จำกัดได้
การใช้งาน
Android รองรับ ShadowCallStack ทั้งสําหรับเคอร์เนลและพื้นที่ผู้ใช้
เปิดใช้ SCS สำหรับเคอร์เนล
หากต้องการเปิดใช้ ShadowCallStack สําหรับเคอร์เนล ให้เพิ่มบรรทัดต่อไปนี้ลงในไฟล์การกําหนดค่าเคอร์เนล
CONFIG_SHADOW_CALL_STACK=y
เปิดใช้ SCS ใน Userspace
หากต้องการเปิดใช้ ShadowCallStack ในคอมโพเนนต์พื้นที่ผู้ใช้ ให้เพิ่มบรรทัดต่อไปนี้ลงในไฟล์ BluePrint ของคอมโพเนนต์
sanitize: { scs: true }
SCS จะถือว่ามีการจองรีจิสเตอร์ x18
เพื่อจัดเก็บที่อยู่ของ ShadowCallStack และไม่ได้ใช้สําหรับวัตถุประสงค์อื่น แม้ว่าระบบจะคอมไพล์ไลบรารีทั้งหมดเพื่อจองรีจิสเตอร์ x18
แต่การดำเนินการนี้อาจก่อให้เกิดปัญหาหากเปิดใช้ SCS สําหรับคอมโพเนนต์พื้นที่ผู้ใช้ที่ทํางานร่วมกันกับโค้ดเดิมในกระบวนการ (เช่น ไลบรารีที่แอปของบุคคลที่สามโหลดได้) ซึ่งอาจรบกวนรีจิสเตอร์ x18
เราจึงขอแนะนำให้เปิดใช้ SCS ในคอมโพเนนต์แบบสแตนด์อโลนเท่านั้นที่จะไม่โหลดลงในไบนารีเดิม
การตรวจสอบความถูกต้อง
ไม่มีการทดสอบ CTS สำหรับ SCS โดยเฉพาะ แต่ให้ตรวจสอบว่าการทดสอบ CTS ผ่านทั้งที่มีและไม่มีการเปิดใช้ SCS เพื่อยืนยันว่า SCS ไม่ได้ส่งผลกระทบต่ออุปกรณ์