ShadowCallStack

ShadowCallStack (SCS) เป็นโหมด เครื่องมือวัด LLVM ที่ป้องกันการเขียนทับที่อยู่ผู้ส่ง (เช่น stack buffer overflows) โดยบันทึกที่อยู่ผู้ส่งกลับของฟังก์ชันไปยัง ShadowCallStack ที่จัดสรรแยกต่างหากในฟังก์ชัน prolog ของฟังก์ชัน nonleaf และโหลดที่อยู่ผู้ส่งกลับจาก ShadowCallStack ในฟังก์ชัน บทส่งท้าย ที่อยู่ผู้ส่งยังถูกจัดเก็บไว้ในสแต็กปกติเพื่อความเข้ากันได้กับตัวคลายคลัตช์ แต่จะไม่ได้ใช้ เพื่อให้แน่ใจว่าการโจมตีที่แก้ไขที่อยู่ผู้ส่งกลับบนสแต็กปกติจะไม่มีผลต่อโฟลว์การควบคุมโปรแกรม

บน aarch64 เครื่องมือวัดใช้การลงทะเบียน x18 เพื่ออ้างอิง ShadowCallStack ซึ่งหมายความว่าการอ้างอิงถึง ShadowCallStack ไม่จำเป็นต้องเก็บไว้ในหน่วยความจำ ทำให้สามารถใช้รันไทม์เพื่อหลีกเลี่ยงการเปิดเผยที่อยู่ของ ShadowCallStack แก่ผู้โจมตีที่สามารถอ่านหน่วยความจำโดยพลการ

การดำเนินการ

Android รองรับ ShadowCallStack สำหรับทั้งเคอร์เนลและพื้นที่ผู้ใช้

การเปิดใช้งาน SCS สำหรับเคอร์เนล

ในการเปิดใช้งาน ShadowCallStack สำหรับเคอร์เนล ให้เพิ่มบรรทัดต่อไปนี้ในไฟล์กำหนดค่าเคอร์เนล:

CONFIG_SHADOW_CALL_STACK=y

การเปิดใช้งาน SCS ใน userspace

ในการเปิดใช้งาน ShadowCallStack ในส่วนประกอบ userspace ให้เพิ่มบรรทัดต่อไปนี้ในไฟล์พิมพ์เขียวของส่วนประกอบ:

sanitize: {
  scs: true
}

SCS ถือว่าลงทะเบียน x18 สงวนไว้เพื่อเก็บที่อยู่ของ ShadowCallStack และไม่ได้ใช้เพื่อวัตถุประสงค์อื่นใด ในขณะที่ไลบรารีระบบทั้งหมดได้รับการคอมไพล์เพื่อจองการลงทะเบียน x18 นี่อาจเป็นปัญหาได้หากเปิดใช้งาน SCS สำหรับส่วนประกอบพื้นที่ผู้ใช้ที่ทำงานร่วมกับรหัสดั้งเดิมในกระบวนการ (เช่น ไลบรารีที่สามารถโหลดโดยแอปพลิเคชันบุคคลที่สาม) ซึ่งอาจปิดบัง การลงทะเบียน x18 ดังนั้น เราแนะนำให้เปิดใช้งาน SCS ในส่วนประกอบที่มีอยู่ในตัวเองเท่านั้น ซึ่งจะไม่โหลดลงในไบนารีแบบเดิม

การตรวจสอบความถูกต้อง

ไม่มีการทดสอบ CTS สำหรับ SCS โดยเฉพาะ ตรวจสอบให้แน่ใจว่าการทดสอบ CTS ผ่านทั้งที่มีและไม่มีการเปิดใช้งาน SCS เพื่อตรวจสอบว่า SCS ไม่ส่งผลกระทบต่ออุปกรณ์